Pregunta GetEnvironmentVariable () y SetEnvironmentVariable () para la variable PATH


Quiero extender la variable PATH actual con un programa C #. Aquí tengo varios problemas:

  1. Utilizando GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine) reemplaza los marcadores de posición (es decir '%SystemRoot%\system32' es reemplazado por el camino actual 'C:\Windows\system32') Actualizando la variable PATH, no quiero reemplazar el marcador de posición con la ruta.

  2. Después SetEnvironmentVariable ya no se puede abrir ningún programa desde el cuadro de comando (es decir, calc.exe en el cuadro de comandos no funciona). Estoy usando el siguiente código:

String oldPath = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine);
Environment.SetEnvironmentVariable("PATH", oldPath + ";%MYDIR%", EnvironmentVariableTarget.Machine);

Después de editar y cambiar el PATH variable con Windows todo funciona de nuevo. (Creo que se requieren cambios, de lo contrario no se sobrescribe)


13
2017-08-19 12:51


origen


Respuestas:


Puede usar el registro para leer y actualizar:

string keyName = @"SYSTEM\CurrentControlSet\Control\Session Manager\Environment";
//get non-expanded PATH environment variable            
string oldPath = (string)Registry.LocalMachine.CreateSubKey(keyName).GetValue("Path", "", RegistryValueOptions.DoNotExpandEnvironmentNames);

//set the path as an an expandable string
Registry.LocalMachine.CreateSubKey(keyName).SetValue("Path", oldPath + ";%MYDIR%",    RegistryValueKind.ExpandString);

5
2017-10-12 11:28



Puede usar WMI para recuperar los valores sin procesar (aunque no estoy seguro de actualizarlos):

ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from Win32_Environment WHERE Name = 'PATH'");
foreach (ManagementBaseObject managementBaseObject in searcher.Get())
     Console.WriteLine(managementBaseObject["VariableValue"]);

Comprobar Referencia de WMI en MSDN


1
2017-08-19 16:49



Podrías probar esta mezcla. Obtiene las variables de ruta del registro y agrega el "NewPathEntry" a la ruta, si no está ya allí.

static void Main(string[] args)
    {
        string NewPathEntry = @"%temp%\data";
        string NewPath = "";
        bool MustUpdate = true;
        string RegKeyName = @"SYSTEM\CurrentControlSet\Control\Session Manager\Environment";
        string path = (string)Microsoft.Win32.Registry.LocalMachine.OpenSubKey(RegKeyName).GetValue
            ("Path", "", Microsoft.Win32.RegistryValueOptions.DoNotExpandEnvironmentNames);
        string[] paths = path.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
        foreach (string subPath in paths)
        {
            NewPath += subPath + ";";
            if (subPath.ToLower() == NewPathEntry.ToLower())
            {
                MustUpdate = false;
            }
        }
        if (MustUpdate == true)
        {
            Environment.SetEnvironmentVariable("Path", NewPath + NewPathEntry, EnvironmentVariableTarget.Machine);
        }
    }

1
2017-11-06 19:03



Podrías pasar por el registro ...

string keyName = @"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment";
//get raw PATH environment variable
string path = (string)Registry.GetValue(keyName, "Path", "");

//... Make some changes

//update raw PATH environment variable
Registry.SetValue(keyName, "Path", path);

0
2017-10-10 15:35



Mientras trabajábamos en la aplicación, teníamos que tener una opción para usar Oracle instantclient desde la carpeta definida por el usuario. Para usar el cliente instantáneo tuvimos que modificar la variable de ruta de entorno y agregar esta carpeta antes de llamando a cualquier funcionalidad relacionada con Oracle. Este es el método que usamos para eso:

    /// <summary>
    /// Adds an environment path segments (the PATH varialbe).
    /// </summary>
    /// <param name="pathSegment">The path segment.</param>
    public static void AddPathSegments(string pathSegment)
    {
        LogHelper.Log(LogType.Dbg, "EnvironmentHelper.AddPathSegments", "Adding path segment: {0}", pathSegment);
        string allPaths = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Process);
        if (allPaths != null)
            allPaths = pathSegment + "; " + allPaths;
        else
            allPaths = pathSegment;
        Environment.SetEnvironmentVariable("PATH", allPaths, EnvironmentVariableTarget.Process);
    }

Tenga en cuenta que esto debe invocarse antes que cualquier otra cosa, posiblemente como la primera línea en su archivo principal (no estoy seguro acerca de las aplicaciones de la consola).


0
2017-10-31 12:14



Utilizando Registry.GetValue ampliará los marcadores de posición, por lo que recomiendo usar Registry.LocalMachine.OpenSubKey, luego obtenga el valor de la clave secundaria con las opciones configuradas para no expandir las variables de entorno. Una vez que haya manipulado la ruta a su gusto, use el registro para establecer el valor nuevamente. Esto evitará que Windows "olvide" su ruta como mencionó en la segunda parte de su pregunta.

const string pathKeyName = @"SYSTEM\CurrentControlSet\Control\Session Manager\Environment";
var pathKey = Registry.LocalMachine.OpenSubKey(pathKeyName);
var path = (string)pathKey.GetValue("PATH", "", RegistryValueOptions.DoNotExpandEnvironmentNames);
// Manipulate path here, storing in path
Registry.SetValue(String.Concat(@"HKEY_LOCAL_MACHINE\", pathKeyName), "PATH", path);

0
2018-04-17 17:09