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

查看:148
本文介绍了以编程方式将目录添加到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已经改变,或者是在改变完全生效之前通知他们。我阅读了广播 WM_SETTINGCHANGE 消息的 Microsoft文章更改环境变量后,我使用此代码:

  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 ++解决方案这个任务应该看看丹莫林的答案。

解决方案

事实证明, 不是太阳下的新东西。这已经在之前做过,至少一次。由我。我创建了一个DLL非常像你描述的完全相同的目的(用于修改NSIS安装程序的路径)。它由视觉泄漏检测器安装程序使用。



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


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天全站免登陆