2009-12-17 164 views
15

我正在使用将目录添加到Windows PATH环境变量(用于安装程序)的函数来编写Win32 DLL。以编程方式将目录添加到Windows PATH环境变量

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

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

我认为我的程序没有做好通知系统PATH已经改变,或者它可能在更改完全生效之前通知他们。我读了article by Microsoft,说改变一个环境变量后,广播WM_SETTINGCHANGE消息,我做的是与此代码:

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 ... */ } 

我的电话的顺序是:RegCreateKeyExRegSetValueExRegCloseKeySendMessageTimeout

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

有谁知道我该怎么办?

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

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

+0

你可能想看看一些开源安装程序的源代码,例如NSIS或Inno Setup。他们这样做是正确的。 – bialix

+6

一个小巧的快速提示,只需输入“path”并按下回车即可在命令提示符下显示PATH内容。每次测试可以保存7次击键(9次计算Shift键)! – Todd

+0

嗯,你必须建立一个Unicode应用程序,所以'windows.h'引入了API的版本('SendMessageTimeoutW'),这需要'LPCWSTR'来代替'LPCSTR'。我认为如果你想支持“ANSI”和Unicode编译,那么正确的做法是使用“LPCTSTR”(即通过'_T()'宏)。我的库可能可以使用更新来使其“Unicode意识到”。它目前仅支持使用“ANSI”设置环境变量,如果在路径中需要带有西里尔文字符的目录,则可能会产生问题。 –

回答

11

事实证明那里真的不是任何新的东西在阳光下。这至少已经完成了一次。由我。我创建了一个非常类似于您为完全相同目的而描述的DLL(用于修改NSIS安装程序的路径)。它由Visual Leak Detector安装程序使用。

该DLL被称为editenv.dll。 github上有The source。我只是测试了安装程序,它更新了系统 PATH环境变量,没问题。根据你写的内容,我没有看到任何突出的错误。我也没有看到任何明显的缺失。但值得看看editenv.dll源代码(你最感兴趣的是的EnvVar.cpp,可能还有editenv.cpppathAdd()pathRemove() C API)。

+0

感谢代码Dan!即使认为我无法通过查看代码来找到自己的具体解决方案,但您的答案将对未来的读者有很大的帮助。 –

0

我有一个程序调用相同的Win32 API来更新环境,它工作正常。

有一点需要注意的是如何你打开命令提示符。

如果通过这样打开命令提示符:

Start -> Run -> cmd.exe 

然后在提示符环境表明,新的变量。

但是,我在我的键盘上也有一个可编程功能键,我已经设置为运行cmd.exe过程。如果通过该功能键打开命令提示符,然后输入env,则不会显示该变量正在设置。

我不知道为什么它的工作方式不同,但它必须有一些与cmd.exe过程中推出的方式做(虽然两者都是在我的用户名来运行,而不是SYSTEM)。

你怎么打开命令提示符?

+4

管理您的可编程功能键的程序正在启动CMD.EXE及其自己的环境副本,如果您在更改完成后未重新启动它,该程序尚未更新路径。 – Todd

+0

有趣。我在开始菜单中点击“命令提示符”开始我的命令提示符。这是Windows附带的一个快捷方式,在附件菜单中,我将它“固定”到开始菜单。目标是%SystemRoot%\ system32 \ cmd.exe –

+0

@Todd - 这听起来是对的。良好的分析! @David - 如果从Start-> Run运行cmd.exe,会有什么区别? – LeopardSkinPillBoxHat