以编程方式将目录添加到Windows PATH环境变量

时间:2009-12-17 02:29:36

标签: c++ winapi registry environment-variables environment

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

2 个答案:

答案 0 :(得分:11)

事实证明,并非在阳光下的任何新东西。这已经做过,至少一次。由我。我创建了一个非常类似于你所描述的DLL的目的(用于修改NSIS安装程序的路径)。它由Visual Leak Detector安装程序使用。

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

答案 1 :(得分:0)

我有一个程序可以调用相同的Win32 API来更新环境,它运行正常。

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

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

Start -> Run -> cmd.exe

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

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

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

如何打开命令提示符?