English 中文(简体)
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.

问题回答

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

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

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





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签