PATH变量的GetEnvironmentVariable()和SetEnvironmentVariable()

时间:2021-07-14 11:33:30

I want to extend the current PATH variable with a C# program. Here I have several problems:

我想用C#程序扩展当前的PATH变量。我有几个问题:

  1. Using GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine) replaces the placeholders (i.e. '%SystemRoot%\system32' is replaced by the current path 'C:\Windows\system32'). Updating the PATH variable, I dont want to replace the placeholder with the path.

    使用GetEnvironmentVariable(“PATH”,EnvironmentVariableTarget.Machine)替换占位符(即'%SystemRoot%\ system32'替换为当前路径'C:\ Windows \ system32')。更新PATH变量,我不想用路径替换占位符。

  2. After SetEnvironmentVariable no program can't be opened from the command box anymore (i.e. calc.exe in the command box doesn't work). Im using following code:

    在SetEnvironmentVariable之后,无法再从命令框中打开任何程序(即命令框中的calc.exe不起作用)。我使用以下代码:

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

After editing and changing the PATH variable with Windows everything works again. (I thing changes are required, otherwise it is not overwritten)

在使用Windows编辑和更改PATH变量后,一切都可以正常工作。 (我需要更改内容,否则不会覆盖)

6 个解决方案

#1


5  

You can use the registry to read and update:

您可以使用注册表来读取和更新:

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


1  

You can use WMI to retrieve the raw values (not sure about updating them though):

您可以使用WMI检索原始值(不确定更新它们):

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

Check WMI Reference on MSDN

检查MSDN上的WMI参考

#3


1  

You could try this mix. It gets the Path variables from the registry, and adds the "NewPathEntry" to Path, if not already there.

你可以尝试这种混合。它从注册表中获取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


0  

You could go through the registry...

你可以通过注册表......

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


0  

While working on the application we had to have an option to use Oracle instantclient from user-defined folder. In order to use the instantclient we had to modify the environment path variable and add this folder before calling any Oracle related functionality. Here is method that we use for that:

在处理应用程序时,我们必须选择使用来自用户定义文件夹的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);
    }

Note that this has to be called before anything else, possibly as the first line in your Main file (not sure about console applications).

请注意,必须先调用它,可能是主文件中的第一行(不确定控制台应用程序)。

#6


0  

Using Registry.GetValue will expand the placeholders, so I recommend using Registry.LocalMachine.OpenSubKey, then get the value from the sub key with options set to not expand environment variables. Once you've manipulated the path to your liking, use the registry to set the value again. This will prevent Windows "forgetting" your path as you mentioned in the second part of your question.

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

#1


5  

You can use the registry to read and update:

您可以使用注册表来读取和更新:

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


1  

You can use WMI to retrieve the raw values (not sure about updating them though):

您可以使用WMI检索原始值(不确定更新它们):

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

Check WMI Reference on MSDN

检查MSDN上的WMI参考

#3


1  

You could try this mix. It gets the Path variables from the registry, and adds the "NewPathEntry" to Path, if not already there.

你可以尝试这种混合。它从注册表中获取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


0  

You could go through the registry...

你可以通过注册表......

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


0  

While working on the application we had to have an option to use Oracle instantclient from user-defined folder. In order to use the instantclient we had to modify the environment path variable and add this folder before calling any Oracle related functionality. Here is method that we use for that:

在处理应用程序时,我们必须选择使用来自用户定义文件夹的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);
    }

Note that this has to be called before anything else, possibly as the first line in your Main file (not sure about console applications).

请注意,必须先调用它,可能是主文件中的第一行(不确定控制台应用程序)。

#6


0  

Using Registry.GetValue will expand the placeholders, so I recommend using Registry.LocalMachine.OpenSubKey, then get the value from the sub key with options set to not expand environment variables. Once you've manipulated the path to your liking, use the registry to set the value again. This will prevent Windows "forgetting" your path as you mentioned in the second part of your question.

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