15

我正在编写一个 Win32 DLL,其函数将目录添加到 Windows PATH 环境变量(在安装程序中使用)。

在 DLL 运行后查看 Regedit 或控制面板中的环境变量显示我的 DLL 已成功添加路径HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\EnvironmentHKEY_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){ /* ... Display error message to user ... */ }

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

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

有谁知道我应该怎么做?

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

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

4

2 回答 2

12

事实证明,太阳底下真的没有什么新鲜事。这在以前已经做过了,至少一次。由我。我创建了一个与您描述的完全相同的 DLL(用于从 NSIS 安装程序修改路径)。它被Visual Leak Detector安装程序使用。

该 DLL 称为 editenv.dll。源代码可在 github 上找到。我刚刚测试了安装程序,它更新了系统PATH 环境变量,没问题。根据您所写的内容,我认为没有任何明显错误的地方。我也没有看到任何明显的缺失。但可能值得一看 editenv.dll 源代码(您最感兴趣的EnvVar::set()EnvVar.cpp,可能还有 editenv.cpp 中的pathAdd()C pathRemove()API )。

于 2009-12-17T02:49:45.973 回答
0

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

需要注意的一件事是如何打开命令提示符。

如果您通过执行以下操作打开命令提示符:

Start -> Run -> cmd.exe

然后提示中的环境显示设置了新变量。

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

我不确定为什么它的工作方式不同,但它必须与cmd.exe进程的启动方式有关(尽管两者都在我的用户名下运行,而不是SYSTEM)。

你如何打开命令提示符?

于 2009-12-17T02:42:16.663 回答