Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#/.NET app doesn't recognize Environment Var Change (PATH)

In my C# app, I am programmatically installing an Oracle client if one is not present, which requires adding a dir to the PATH system environment variable. This all works fine, but it doesn't take effect until the user logs out/in to windows, or reboots. How can I get my app to recognize and use the new PATH var without this step? Even restarting my app would be better than requiring the user to log out/in.

Supposedly, broadcasting this change to other processes should work. Here's what I've tried, with no success:

    using System.Runtime.InteropServices;

    private const int HWND_BROADCAST = 0xffff;
    private const int WM_WININICHANGE = 0x001a, WM_SETTINGCHANGE = WM_WININICHANGE, INI_INTL = 1;
    [DllImport("user32.dll")]
    private static extern int SendMessageTimeoutA(int hWnd, uint wMsg, uint wParam, string lParam, int fuFlags, int uTimeout, int lpdwResult);

    int rtnVal = 0;
    SendMessageTimeoutA(HWND_BROADCAST, WM_SETTINGCHANGE, 0, "Environment", 2, 5000, rtnVal);

I've been told if you stop and restart the process in question, it should pick up these kinds of changes, but restarting my app doesn't do it. I suppose it could be an Oracle issue, that something about Oracle requires the login to recognize the change, I'm not sure. Thanks in advance.

like image 568
Randy Gamage Avatar asked Nov 05 '22 18:11

Randy Gamage


2 Answers

Does Environment.GetEnvironmentVariable("MYVAR", EnvironmentVariableTarget.Machine) not work?

If my app is running elevated then I can

 Environment.SetEnvironmentVariable("MYVAR", "cool", EnvironmentVariableTarget.Machine);

//do some other stuff...

Console.WriteLine(Environment.GetEnvironmentVariable("MYVAR", EnvironmentVariableTarget.Machine));

C:\TestApp>>TestApp.exe
cool

I don't know if this will work for other running processes but it should for your app doing the getting/setting

like image 186
nick Avatar answered Nov 13 '22 05:11

nick


Your problem is only certain apps listen for that message (such as explorer) so it will not be used by your application at all. As the environment is generally inherited then restarting your app from within itself isn't going to help as it will get your current Environment block. If the user restarts from the start menu it will work (assuming the WM_SETTINGCHANGE has been broadcast).

You are best using Environment.GetEnvironmentVariable to read out the current value from the registry and merge it back into you current environment. Basically doing

Environment.SetEnvironmentVariable("PATH", Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine) + ";" + (Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.User)));
like image 45
tyranid Avatar answered Nov 13 '22 04:11

tyranid