以编程方式将目录添加到Windows PATH环境变量中 [英] Programmatically adding a directory to Windows PATH environment variable

查看:248
本文介绍了以编程方式将目录添加到Windows PATH环境变量中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个带有一个功能的Win32 DLL,该函数向Windows PATH环境变量添加一个目录(在安装程序中使用)。



在DLL运行后,Regedit或控制面板中的环境变量显示,我的DLL已成功添加路径到 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment HKEY_CURRENT_USER\Environment



但是当我启动一个新的命令提示符(之后)运行DLL),我添加的目录不会显示在 echo%PATH%的输出中,我无法通过键入其名称来访问该目录中的可执行文件



我认为我的程序没有做好通知系统PATH已经改变的工作,也可能是在变更完全生效之前通知他们。我阅读了一个 Microsoft的文章,宣称 WM_SETTINGCHANGE 更改环境变量后的消息,我正在使用以下代码:

  DWORD result2 = 0; 
LRESULT result = SendMessageTimeout(HWND_BROADCAST,WM_SETTINGCHANGE,0,
(LPARAM)Environment,SMTO_ABORTIFHUNG,5000,& result2);
if(result == 0){/ * ...显示错误消息给用户... * /}

我的电话的顺序是: RegCreateKeyEx RegSetValueEx RegCloseKey SendMessageTimeout



如果在控制面板环境中按确定变量窗口,我的DLL对PATH所做的更改显示在新创建的命令提示符中,因此控制面板正在进行传播PATH更改的操作;我想知道它是什么,做同样的事情。



有谁知道我应该做什么?



我正在运行64位Windows Vista,但我希望这可以在所有Windows XP,Vista和Windows 7操作系统上工作。



更新: / strong>我上面发布的代码的问题是我没有将L前缀放在环境字符串上。尽管在Microsoft文档中没有明确指出,LPARAM需要是一个指向WCHAR字符串(2字节字符)的指针,而不是CHAR字符串,这是Visual Studio的编译器默认生成的字符串当我写一个字符串文字。解决我的问题是把环境变成L环境。 (我以为我已经在发布这个问题之前已经尝试过了,但是显然我没有正确尝试!)但是任何想要完成这个任务的C ++解决方案的人都应该看看Dan Molding的答案。

解决方案

事实证明,真正的不是太阳下的任何新东西。这已经在之前完成了,至少一次。由我。我创建的DLL非常类似于所描述的完全相同的目的(用于修改NSIS安装程序的路径)。它被可视泄漏检测器安装程序使用。



该DLL称为editenv.dll。 可在github获得。我刚刚测试了安装程序,并更新了系统 PATH环境变量,没有问题。根据你写的内容,我看不出任何突出的错误。我也没有看到有什么明显的缺失。但是可能值得一看editenv.dll源码(你最感兴趣的是在 EnvVar :: set() github.com/dmoulding/editenv/blob/master/EnvVar.cpprel =noreferrer> EnvVar.cpp ,以及可能的 pathAdd() pathRemove() C API在 editenv.cpp )。


I'm writing a Win32 DLL with a function that adds a directory to the Windows PATH environment variable (to be used in an installer).

Looking at the environment variables in Regedit or the Control Panel after the DLL has run shows me that my DLL has succeeded in adding the path to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment and HKEY_CURRENT_USER\Environment.

But when I start up a new Command Prompt (after running the DLL), the directory I added does not show up in the output of echo %PATH% and I can not access the executable that lives in that directory by typing its name.

I think my program is not doing a good job of notifying the system that the PATH has changed, or maybe it is notifying them before the change has fully taken effect. I read an article by Microsoft that says to broadcast the WM_SETTINGCHANGE message after changing an environment variable, and I am doing that with this code:

DWORD result2 = 0;
LRESULT result = SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
    (LPARAM)"Environment", SMTO_ABORTIFHUNG, 5000, &result2);
if (result == 0){ /* ... Display error message to user ... */ }

The order of my calls is: RegCreateKeyEx, RegSetValueEx, RegCloseKey, SendMessageTimeout

If I press "OK" in the Control Panel "Environment Variables" window, the changes made by my DLL to the PATH show up in newly-created command prompts, so there is something that the Control Panel is doing to propagate PATH changes; I want to figure out what it is and do the same thing.

Does anyone know what I should do?

I'm running 64-bit Windows Vista but I want this to work on all Windows XP, Vista and Windows 7 operating systems.

Update: The problem with the code I posted above is that I did not put the L prefix on the "Environment" string. Although it does not say it explicitly anywhere in the Microsoft documentation that I can find, the LPARAM needs to be a pointer to a WCHAR string (2-byte characters) as opposed to a CHAR string, which is what Visual Studio's compiler generates by default when I write a string literal. The solution to my problem was to change "Environment" to L"Environment". (I thought I already tried that before posting this question, but apparently I didn't try it correctly!) But anyone who wants a complete C++ solution for this task should look at Dan Moulding's answer.

解决方案

It turns out there really isn't anything new under the sun. This has already been done before, at least once. By me. I created a DLL very much like what you describe for exactly the same purpose (for use in modifying the path from an NSIS installer). It gets used by the Visual Leak Detector installer.

The DLL is called editenv.dll. The source is available at github. I just tested the installer and it updated the system PATH environment variable, no problem. Based on what you've written, I don't see anything that stands out as being wrong. I also don't see anything obvious that's missing. But it may be worth a look at the editenv.dll source (you'd be most interested in EnvVar::set() in EnvVar.cpp, and possibly the pathAdd() and pathRemove() C APIs in editenv.cpp).

这篇关于以编程方式将目录添加到Windows PATH环境变量中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆