Computers, Programming, Technology, Music, Literature

What happens when you set the Path environment variable – Part 2

with one comment

This article was originally published for www.prowareness.com and could be located at http://www.prowareness.com/blog/what-happens-when-you-set-the-path-environment-variable-part-2/.

 

Part 1 of the article focussed on reviewing, editing the Path via System Properties dialog, via the Registry Editor, via the Command Prompt. Let’s look at how to do the same thing via the .Net APIs, and a couple of workarounds when you want to add a path that is exceeds the 2047 chars limit.

4. Updating Path via the APIs

In the .Net framework Environment.SetEnvironmentVariable method allows you to make changes to the Path environment variable at a Process level, User level, and Machine level. Setting the Path variable at the Machine level is equivalent of using the Edit System Variable dialog box and the SETX command. Setting the Path variable at the Process level is equivalent to using the SET command in a command prompt, where only that cmd.exe has an updated copy of the Path variable.

Code samples at the MSDN are ample enough to get you started.

Also, as an alternative, you could directly read and write to the Path string aforementioned registry location.

We have seen instances above where a process that was spawned before the edit of the Path variable, not reflecting the updated Path till it was restarted. The solution here is: If you want the command processor and other windows processes to have an option to read update the Path variable, you could broadcast a WM_SETTINGCHANGE message, so the command shell and other processes would pick the updates. Broadcasting a WM_SETTINGCHANGE message does not mean all the applications running in the computer would pick up the Path variable changes. It just means that the process or the application that modified the Path variable was gracious enough to notify other processes about the change. If you are building an application that is required to have a copy of the updated Path variable then you should write an event handler to trap the Windows message broadcasted with WM_SETTINGCHANGE and reload the Path variable from the registry key.

Broadcasting a WM_SETTINGCHANGE message with “Environment” parameter:

public enum SendMessageTimeoutFlags : uint
    {
        SMTO_NORMAL = 0x0000
        ,
        SMTO_BLOCK = 0x0001
            ,
        SMTO_ABORTING = 0x0002
            , SMTO_NOTIMEOUTIFNOTHING = 0x0008
    }

    public class SendWindowsSettingChangeMessage
    {
        [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam, SendMessageTimeoutFlags fuFlags, uint uTimeout, out UIntPtr lpdwResult);

        private static void NotifyWindowsAboutSettingChange()
        {
            IntPtr HWND_BROADCAST = (IntPtr)0xffff;
            const uint WM_SETTINGCHANGE = 0x001A;
            UIntPtr result;
            IntPtr settingResult = SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, (UIntPtr)0, "Environment", SendMessageTimeoutFlags.SMTO_NORMAL, 10000, out result);
        }
    }

 

Trapping a WM_SETTINGCHANGE message:

    public class TrapWindowsSettingChangeMessage : System.Windows.Forms.Form
    {
        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            const uint WM_SETTINGCHANGE = 0x001A;
            switch ((uint)m.Msg)
            {
                case WM_SETTINGCHANGE:
                    {
                        //attempt to reload the Path variable from the registry
                        break;
                    }
            }
            base.WndProc(ref m);
        }
    }


Another not so elegant, archaic kind of solution would be to run a background listener every couple of some duration that would directly read the registry value of Path and refresh itself.

string keyName = @"SYSTEM\CurrentControlSet\Control\Session Manager\Environment\";
string existingPathVariable = (string)Registry.LocalMachine.OpenSubKey(keyName).GetValue("PATH", "", RegistryValueOptions.DoNotExpandEnvironmentNames);

 

Overcoming the 2047 chars limitation

If you would like to circumvent the 1024 chars limitation, and want to add more directories to your Path variable, you could consider using the 8dot3 naming format for all commonly used windows locations like Program Files, Favorites, etc.

For instance, a Path variable like this

1. C:\Program Files\Common Files\Microsoft Shared\Windows Live;

2. C:\Program Files (x86)\Common Files\Microsoft Shared\Windows Live;

could be shortened to

1. C:\PROGRA~1\COMMON~1\MICROS~1\WINDOW~2;

2. C:\PROGRA~2\COMMON~1\MICROS~1\WINDOW~2;

You could obtain the 8dot3 naming using the DIR command with the /X and /-N switches.

clip_image002

Or you could create all commonly used tools/applications under one folder and add that folder to the Path variable. This is an additional effort, but you get use a lot more shortcuts for your favourite programs. What I do, is create a folder called m.Shortcuts and append the path of m.Shortcuts (in my case, it is – C:\Windows\System32\m.Shortcuts) to the Path variable.

clip_image004

That’s about it. Besides the Path variable and other System Environment Variables displayed in the System Properties dialog, there are a couple of other System wide environment variables that are created for every user – documented here, here and here.

 

Disclaimer: All these facts are explored based on tests ran on a Windows 7 x64 Enterprise. If you find any incorrect content, please let me know.

Advertisements

Written by gmaran23

July 5, 2013 at 4:39 pm

One Response

Subscribe to comments with RSS.

  1. […] follow up article Part 2 will focus on updating the Path variable via the APIs, broadcasting windows settings change message […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: