views:

667

answers:

3

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.

+1  A: 

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

nick
Yes, that works. Any write I do to the PATH variable, is then read back correctly by my app.
Randy Gamage
Just to clarify, my app still doesn't work, because it's really the Oracle client I am using that needs to recognize and use the new PATH var. For some reason, that's not happening, even after stopping and re-launching my app. It requires windows logout/login.
Randy Gamage
Is your Oracle client running as a service or a standalone exe? What user is it running under? (System, NT Authority, logged in user etc)If it is a service this might be applicable: http://support.microsoft.com/kb/821761
nick
I'm using InstantClient, version 10.x, and there's no service or .exe, it's just a collection of .dll files. You just put them somewhere on your C drive and add that path to your system path, and like magic you have an oracle client.In my app, I'm using System.Data.OracleClient.This is running on an XP system, and the user does have admin priveleges. Regarding that link, I don't know if my app is being run under the Local System account or not.I suppose that once those Oracle .dlls are loaded/launched, they may be staying in memory or running as a service, even after my app closes.
Randy Gamage
To ensure that all was clear. InstantClient is not a SERVICE. It is a bunch of dlls.
Sasha
+1  A: 

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)));

tyranid
Thanks for the idea. I tried setting both the machine target PATH and the Process target PATH var similar to your example, with no success. By the way, I haven't been restarting from within the app - I've always been manually restarting from the Start menu, again with no success.
Randy Gamage
A: 

In our project we setup Oracle Instant Client with use of "install.bat" from Instant Client archive. For example:

install.bat odp.net1x %1 name

Sasha