Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 以编程方式将目录添加到Windows PATH环境变量_C++_Winapi_Registry_Environment Variables_Environment - Fatal编程技术网

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

C++ 以编程方式将目录添加到Windows PATH环境变量,c++,winapi,registry,environment-variables,environment,C++,Winapi,Registry,Environment Variables,Environment,我正在编写一个Win32 DLL,其中包含一个将目录添加到Windows PATH环境变量(将在安装程序中使用)的函数 运行DLL后,查看Regedit或控制面板中的环境变量,我的DLL已成功地将路径添加到HKEY\U LOCAL\U MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\environment和HKEY\U CURRENT\U USER\environment 但是,当我启动一个新的命令提示符时(在运行DLL之后),我

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

运行DLL后,查看Regedit或控制面板中的环境变量,我的DLL已成功地将路径添加到
HKEY\U LOCAL\U MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\environment
HKEY\U CURRENT\U USER\environment

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

我认为我的程序没有很好地通知系统路径已更改,或者可能是在更改完全生效之前通知他们。我读到一篇文章,说在更改环境变量后广播
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对路径所做的更改将显示在新创建的命令提示中,因此控制面板正在进行一些传播路径更改的操作;我想弄清楚这是什么,然后做同样的事情

有人知道我该怎么做吗

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


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

< P>我有一个程序调用同一个Win32 API来更新环境,它工作得很好。 需要注意的一件事是如何打开命令提示符

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

Start -> Run -> cmd.exe
然后提示中的环境显示新变量已设置

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

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

你是如何打开命令提示符的?

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


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

您可能想看看一些开源安装程序的源代码,例如NSIS或Inno安装程序。一个小小的提示,你可以在命令提示符下显示路径内容,只需键入“PATH”并按enter键。每次测试可为您节省7次击键次数(9次计shift键)!啊,您必须构建一个Unicode应用程序,因此
windows.h
引入了Unicode版本的API(
sendMessageTimeOut
),这将需要
LPARAM
使用
LPCWSTR
,而不是
LPCSTR
。我认为如果您想同时支持“ANSI”和Unicode构建,那么正确的做法是使用
LPCTSTR
(即通过
\u T()
宏)。我的库可能会使用一个更新,使其“Unicode感知”。它目前只支持使用“ANSI”设置环境变量,如果您的路径中需要一个包含(比如)西里尔字符的目录,这可能会有问题。我怀疑SendMessageTimeout[W]是否会将LPRAM从一种字符串类型转换为另一种字符串类型,因为据我所知,LPRAM只是一个通用指针,可以指向任何东西。因此,在生成字符串时,必须确保它是Unicode格式的,然后才能将其发送给SendMessageTimeOut[W]。我使用的是VisualStudio2008,包括windows.h,而不是Unicode。在我的程序中,像“Environment”这样的文字字符串默认是ANSI(这导致了我的问题)。您使用的编译器是什么?默认情况下,什么编码是文本字符串?对,函数有两个版本:
SendMessageTimeoutA
sendMessageTimeOut
。“A”版本的LPRAM应该是LPCSTR,而“W”版本的LPRAM应该是LPCWSTR。如果您仅通过
SendMessageTimeout
调用函数,那么您确实应该将LPRAM包含在
\u T()
宏中,即:
\u T(“环境”)
。然后,如果windows.h展开
SendMessageTimeout<