Подтвердить что ты не робот

GetEnvironmentVariable() и SetEnvironmentVariable() для переменной PATH

Я хочу расширить текущую переменную PATH с помощью программы на С#. Здесь у меня есть несколько проблем:

  • Использование GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine) заменяет заполнители (т.е. '%SystemRoot%\system32' заменяется текущим путем 'C:\Windows\system32'). Обновление переменной PATH, я не хочу заменять местозаполнитель пути.

  • После SetEnvironmentVariable программа больше не может быть открыта из командной строки (т.е. calc.exe в командной строке не работает). Im используя следующий код:

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

После редактирования и изменения переменной PATH с Windows все работает снова. (Мне нужны изменения, в противном случае они не перезаписываются)

4b9b3361

Ответ 1

Вы можете использовать реестр для чтения и обновления:

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);

Ответ 2

Вы можете использовать WMI для извлечения необработанных значений (не уверены в их обновлении):

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

Отметьте Ссылка WMI на MSDN

Ответ 3

Вы можете попробовать этот микс. Он получает переменные Path из реестра и добавляет "NewPathEntry" к Path, если он еще не существует.

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);
        }
    }

Ответ 4

Вы можете пройти через реестр...

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);

Ответ 5

При работе над приложением мы должны были иметь возможность использовать Oracle instantclient из пользовательской папки. Чтобы использовать instantclient, нам пришлось изменить переменную пути окружения и добавить эту папку перед вызовом любой связанной с Oracle функциональности. Вот метод, который мы используем для этого:

    /// <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);
    }

Обратите внимание, что это нужно вызывать перед чем-либо еще, возможно, как первая строка в главном файле (не уверены в консольных приложениях).

Ответ 6

С помощью Registry.GetValue будут разворачиваться заполнители, поэтому я рекомендую использовать Registry.LocalMachine.OpenSubKey, затем получить значение из вспомогательного ключа с параметрами, установленными для того, чтобы не расширять переменные среды. После того, как вы обработали путь по своему вкусу, используйте реестр, чтобы снова установить значение. Это не позволит Windows "забыть" ваш путь, как вы упомянули во второй части вашего вопроса.

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);