Программное добавление каталога в переменную среды Windows PATH
Я пишу Win32 DLL с функцией, которая добавляет каталог в переменную среды PATH Windows (для использования в установщике).
Рассмотрение переменных среды в Regedit или панели управления после запуска DLL показывает мне, что моей DLL удалось добавить путь к HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
и HKEY_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 "Окружающая среда" . (Я думал, что я уже пробовал это, прежде чем публиковать этот вопрос, но, видимо, я не пробовал это правильно!) Но любой, кто хочет получить полное решение на С++ для этой задачи, должен посмотреть на ответ Дэна Молдинга.
Ответы
Ответ 1
Оказывается, на солнце не бывает ничего нового. Это уже было сделано раньше, по крайней мере, один раз. Мной. Я создал DLL, очень похожую на то, что вы описали, для той же цели (для использования в изменении пути от установщика NSIS). Он используется установщиком Visual Leak Detector.
DLL называется editenv.dll. Источник доступен в github. Я просто протестировал установщик и обновил переменную среды PATH системы, без проблем. Основываясь на том, что вы написали, я не вижу ничего, что выделяется как неправильное. Я также не вижу ничего очевидного, что не хватает. Но может быть стоит посмотреть на источник editenv.dll(вас больше всего интересует EnvVar::set()
в EnvVar.cpp и, возможно, API pathAdd()
и pathRemove()
C в editenv.cpp).
Ответ 2
У меня есть программа, которая вызывает тот же самый Win32 API для обновления среды, и она отлично работает.
Одна вещь, о которой нужно заботиться, это то, как вы открываете командную строку.
Если вы откроете командную строку, сделав следующее:
Start -> Run -> cmd.exe
тогда среда в приглашении показывает, что установлена новая переменная.
Однако у меня также есть программируемый функциональный ключ на моей клавиатуре, который я установил для запуска процесса cmd.exe
. Если я открою командную строку с помощью этой функциональной клавиши, а затем введите env
, она не покажет переменную как установленную.
Я не уверен, почему он работает по-другому, но он должен иметь какое-то отношение к способу запуска процесса cmd.exe
(хотя обе работают под моим именем пользователя, а не SYSTEM
).
Как вы открываете командную строку?