c++ - restaurar - Agregando programáticamente un directorio a la variable de entorno Windows PATH
variable path windows 10 (2)
Resulta que realmente no hay nada nuevo bajo el sol. Esto ya se ha hecho antes, al menos una vez. Por mi. Creé una DLL muy parecida a lo que describes para exactamente el mismo propósito (para usar en la modificación de la ruta desde un instalador de NSIS). Se usa por el instalador Visual Leak Detector .
La DLL se llama editenv.dll. La fuente está disponible en github. Acabo de probar el instalador y actualizó la variable de entorno PATH del sistema , no hay problema. Basado en lo que has escrito, no veo nada que se destaque como incorrecto. Tampoco veo nada obvio que falta. Pero puede valer la pena echar un vistazo a la fuente editenv.dll (lo que más le interesaría sería EnvVar::set()
en EnvVar.cpp , y posiblemente las API C de pathAdd()
y pathRemove()
en editenv.cpp ).
Estoy escribiendo un archivo DLL Win32 con una función que agrega un directorio a la variable de entorno PATH de Windows (para ser utilizado en un instalador).
Al observar las variables de entorno en Regedit o en el Panel de control después de que se haya ejecutado la DLL, se muestra que mi DLL ha logrado agregar la ruta a HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Session Manager/Environment
y HKEY_CURRENT_USER/Environment
.
Pero cuando inicio un nuevo símbolo del sistema (después de ejecutar el DLL), el directorio que agregué no aparece en el resultado de echo %PATH%
y no puedo acceder al ejecutable que vive en ese directorio escribiendo su nombre.
Creo que mi programa no está haciendo un buen trabajo notificando al sistema que la RUTA ha cambiado, o tal vez los está notificando antes de que el cambio haya entrado en vigor. Leí un artículo de Microsoft que dice que se debe transmitir el mensaje WM_SETTINGCHANGE
después de cambiar una variable de entorno, y lo hago con este código:
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 ... */ }
El orden de mis llamadas es: RegCreateKeyEx
, RegSetValueEx
, RegCloseKey
, SendMessageTimeout
Si presiono "Aceptar" en la ventana "Variables de entorno" del Panel de control, los cambios realizados por mi DLL a la PATH aparecen en las nuevas instrucciones del comando, por lo que el Panel de control está haciendo algo para propagar los cambios de PATH; Quiero descubrir qué es y hacer lo mismo.
¿Alguien sabe lo que debería hacer?
Estoy ejecutando Windows Vista de 64 bits, pero quiero que esto funcione en todos los sistemas operativos Windows XP, Vista y Windows 7.
Actualización: El problema con el código que publiqué anteriormente es que no puse el prefijo L en la cadena "Entorno". Aunque no lo dice explícitamente en ninguna parte de la documentación de Microsoft que puedo encontrar, el LPARAM debe ser un puntero a una cadena WCHAR (caracteres de 2 bytes) en oposición a una cadena CHAR, que es lo que el compilador de Visual Studio genera de manera predeterminada cuando escribo una cadena literal. La solución a mi problema fue cambiar "Entorno" a "Medio ambiente". (Pensé que ya lo intenté antes de publicar esta pregunta, ¡pero aparentemente no lo intenté correctamente!) Pero cualquiera que quiera una solución completa de C ++ para esta tarea debería mirar la respuesta de Dan Moulding.
Tengo un programa que llama a la API Win32 misma para actualizar el entorno y funciona bien.
Una cosa a tener cuidado es cómo está abriendo el símbolo del sistema.
Si abre el símbolo del sistema haciendo esto:
Start -> Run -> cmd.exe
entonces el entorno en el prompt muestra que la nueva variable está configurada.
Sin embargo, también tengo una tecla de función programable en mi teclado que he configurado para ejecutar el proceso cmd.exe
. Si abro un símbolo del sistema a través de esa tecla de función y luego env
, no muestra la variable como configurada.
No estoy seguro de por qué funciona de manera diferente, pero debe tener algo que ver con la forma en que se inicia el proceso cmd.exe
(aunque ambos se ejecutan bajo mi nombre de usuario, no el SYSTEM
).
¿Cómo está abriendo el símbolo del sistema?