以编程方式将目录添加到 Windows PATH 环境变量
我正在编写一个 Win32 DLL,其中包含一个将目录添加到 Windows PATH 环境变量(将在安装程序中使用)的函数.
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).
在 DLL 运行后查看 Regedit 或控制面板中的环境变量显示我的 DLL 已成功将路径添加到 HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession ManagerEnvironment
和 HKEY_CURRENT_USEREnvironment
.
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_MACHINESYSTEMCurrentControlSetControlSession ManagerEnvironment
and HKEY_CURRENT_USEREnvironment
.
但是当我启动一个新的命令提示符时(在运行 DLL 之后),我添加的目录没有显示在 echo %PATH%
的输出中,并且我无法访问该可执行文件通过键入其名称位于该目录中.
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.
我认为我的程序在通知系统 PATH 已更改方面做得不好,或者它可能在更改完全生效之前通知他们.我读了一篇 Microsoft 的文章 说要在之后广播 WM_SETTINGCHANGE
消息更改环境变量,我正在使用以下代码:
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 ... */ }
我的调用顺序是:RegCreateKeyEx
、RegSetValueEx
、RegCloseKey
、SendMessageTimeout
The order of my calls is: RegCreateKeyEx
, RegSetValueEx
, RegCloseKey
, SendMessageTimeout
如果我在控制面板环境变量"窗口中按确定",我的 DLL 对 PATH 所做的更改会显示在新创建的命令提示符中,因此控制面板正在做一些事情来传播 PATH变化;我想弄清楚它是什么并做同样的事情.
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?
我运行的是 64 位 Windows Vista,但我希望它能够在所有 Windows XP、Vista 和 Windows 7 操作系统上运行.
I'm running 64-bit Windows Vista but I want this to work on all Windows XP, Vista and Windows 7 operating systems.
更新: 我上面发布的代码的问题是我没有在环境"字符串上加上 L 前缀.虽然它没有在我能找到的 Microsoft 文档的任何地方明确说明,但 LPARAM 需要是指向 WCHAR 字符串(2 字节字符)的指针,而不是 CHAR 字符串,这是 Visual Studio 的编译器默认生成的当我写一个字符串文字时.我的问题的解决方案是将环境"更改为 L环境".(我以为在发布这个问题之前我已经尝试过了,但显然我没有正确尝试!)但是任何想要完成这项任务的 C++ 解决方案的人都应该看看 Dan Moulding 的答案.
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.
推荐答案
事实证明,太阳底下真的没有什么新鲜事.这在以前已经做过了,至少一次.由我.我创建了一个与您描述的完全相同的 DLL(用于从 NSIS 安装程序修改路径).Visual Leak Detector 安装程序会使用它.
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.
该 DLL 称为 editenv.dll.源代码可在 github 上找到.我刚刚测试了安装程序,它更新了 system PATH 环境变量,没问题.根据您所写的内容,我认为没有任何明显错误的地方.我也没有看到任何明显的缺失.但可能值得一看 editenv.dll 源代码(您最感兴趣的是 EnvVar::set()editenv/blob/master/EnvVar.cpp" rel="noreferrer">EnvVar.cpp,可能还有 pathAdd()
和 pathRemove()
C API在 editenv.cpp).
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).
相关文章