Windows Path Environment Variable Length

10. February 2014 13:14 by Cameron in Windows  //  Tags: , , , , , ,   //   Comments

I recently started getting "Target Invocation" errors while trying to launch Visual Studio 2012 or Visual Studio 2013. This was a strange error message as not much else was given to diagnose the problem. After some extended research, I found that having an extra long PATH variable can cause Visual Studio to hang on startup. Windows limits this length to 2048 characters. Although you can still have a PATH variable longer than that, some programs like Visual Studio can't address a PATH environment variable larger than 2048 characters. A remedy to this problem is to split out your PATH variable into at least two variables. 

First, you need to open your PATH variable and copy its value into a safe spot in case it gets messed up. Then you can extract the last half of your path and create a new environment variable and call it PATH2. After your new environment variable is setup, you can reference it in your main PATH

C:\bin;C:\anotherfolder\bin;%PATH2%

Some may be asking, why would my PATH ever exceed 2048 characters? The answer is that if you're a developer and have lots of compilers, IDEs, and toolchains installed on your development machine such as Visual Studio, Net Beans, GCC, Qt, or devkitpro, your PATH can grow fairly quickly. 

If you ever exceed 2048 characters in PATH2, you can append another variable such as PATH3 or PATH4. I'm not certain if there is a real physical limit to user created environment variables, but if you experience problems, you can do as I mentioned. Note, I have a Windows 7 x64 development machine at work and I haven't seen this issue in Windows XP or Windows 8. I haven't done development on Windows XP in several years since it is now showing its age and Microsoft is discontinuing support in April 2014.

On-the-Fly Windows Impersonation with C#

6. February 2014 09:37 by Cameron in Programming  //  Tags:   //   Comments

Occasionally I need to perform tasks under another user so I created a nice wrapper class that allows me to impersonate as another user on the fly:

using System;

using System.Runtime.InteropServices;

using System.Security.Permissions;

using System.Security.Principal;

using Microsoft.Win32.SafeHandles;

using System.Runtime.ConstrainedExecution;

using System.Security;

using System.Configuration;



namespace Tinksoft.Tools

{

    /// <summary>

    /// Facilitates impersonation of a Windows User.

    /// </summary>

    [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]

    public class Impersonation : IDisposable

    {

        public string Environment { get; set; }



        public string UserName { get; set; }



        public string Password { get; set; }



        public string DomainName { get; set; }



        public enum LogonType

        {

            Interactive = 2,

            Network = 3,

            Batch = 4,

            Service = 5,

            Unlock = 7,

            NetworkClearText = 8,

            NewCredentials = 9

        }



        public enum LogonProvider

        {

            Default = 0,

            WinNT35 = 1,

            WinNT40 = 2,

            WinNT50 = 3

        }



        /// <summary>

        /// Windows Token.

        /// </summary>

        private readonly SafeTokenHandle _handle;



        /// <summary>

        /// The impersonated User.

        /// </summary>

        private WindowsImpersonationContext impersonatedUser;



        public Impersonation()

        {

        }



        /// <summary>

        /// Initializes a new instance of the Impersonation class. Provides domain, user name, and password for impersonation.

        /// </summary>

        /// <param name="domainName">Domain name of the impersonated user.</param>

        /// <param name="userName">Name of the impersonated user.</param>

        /// <param name="password">Password of the impersonated user.</param>

        /// <remarks>

        /// Uses the unmanaged LogonUser function to get the user token for

        /// the specified user, domain, and password.

        /// </remarks>

        public Impersonation(AccountCredentials credentials)

        {            

            string[] splitName = WindowsIdentity.GetCurrent().Name.Split('\\');

            string name = (splitName.Length > 0) ? splitName[0] : null;



            LogonType logonType = LogonType.Interactive;

            LogonProvider logonProvider = LogonProvider.Default;



            if (name != credentials.Domain)

            {

                logonType = LogonType.NewCredentials;

                logonProvider = LogonProvider.WinNT50;

            }



            // Call LogonUser to obtain a handle to an access token.

            bool returnValue = LogonUser(

                                credentials.UserName,

                                credentials.Domain,

                                credentials.Password,

                                (int)logonType,

                                (int)logonProvider,

                                out this._handle);



            if (false == returnValue)

            {

                // Something went wrong.

                int ret = Marshal.GetLastWin32Error();

                throw new System.ComponentModel.Win32Exception(ret);

            }



            this.impersonatedUser = WindowsIdentity.Impersonate(this._handle.DangerousGetHandle());    

        }



        /// <summary>

        /// Initializes a new instance of the Impersonation class. Provide domain, user name, and password for impersonation.

        /// </summary>

        /// <param name="domainName">Domain name of the impersonated user.</param>

        /// <param name="userName">Name of the impersonated user.</param>

        /// <param name="password">Password of the impersonated user.</param>

        /// <remarks>

        /// Uses the unmanaged LogonUser function to get the user token for

        /// the specified user, domain, and password.

        /// </remarks>

        public Impersonation(string domainName, string userName, string password)

        {

            string[] splitName = WindowsIdentity.GetCurrent().Name.Split('\\');

            string name = (splitName.Length > 0) ? splitName[0] : null;



            LogonType logonType = LogonType.Interactive;

            LogonProvider logonProvider = LogonProvider.Default;



            if (name != domainName)

            {

                logonType = LogonType.NewCredentials;

                logonProvider = LogonProvider.WinNT50;

            }



            // Call LogonUser to obtain a handle to an access token.

            bool returnValue = LogonUser(

                                userName,

                                domainName,

                                password,

                                (int)logonType,

                                (int)logonProvider,

                                out this._handle);



            if (false == returnValue)

            {

                // Something went wrong.

                int ret = Marshal.GetLastWin32Error();

                throw new System.ComponentModel.Win32Exception(ret);

            }



            this.impersonatedUser = WindowsIdentity.Impersonate(this._handle.DangerousGetHandle());

        }



        [DllImport("advapi32.dll", SetLastError = true)]

        private static extern bool LogonUser(

                string lpszUsername,

                string lpszDomain,

                string lpszPassword,

                int dwLogonType,

                int dwLogonProvider,

                out SafeTokenHandle phToken);



        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]

        private static extern bool CloseHandle(IntPtr handle);



        public void Dispose()

        {

            this.impersonatedUser.Dispose();

            this._handle.Dispose();

        }



        private static string[] GetAccountInfo(string accountInfo)

        {

            return accountInfo.Split(' ');

        }

    }



    public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid

    {

        private SafeTokenHandle()

            : base(true) { }



        [DllImport("kernel32.dll")]

        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]

        [SuppressUnmanagedCodeSecurity]

        [return: MarshalAs(UnmanagedType.Bool)]

        private static extern bool CloseHandle(IntPtr handle);



        protected override bool ReleaseHandle()

        {

            return CloseHandle(handle);

        }

    }

}
 

Month List

Tag cloud