如何在C#中设置系统环境变量?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19705401/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 15:41:03  来源:igfitidea点击:

How to set system environment variable in C#?

c#.netenvironment-variables

提问by alex555

I'm trying to set a system environment variable in my application, but get an SecurityException. I tested everything I found in google - without success. Here is my code (note, that I'm administrator of my pc and run VS2012 as admin):

我试图在我的应用程序中设置一个系统环境变量,但得到一个SecurityException. 我测试了我在谷歌中找到的所有内容 - 没有成功。这是我的代码(注意,我是我的电脑的管理员并以管理员身份运行 VS2012):

Attempt 1

尝试 1

new EnvironmentPermission(EnvironmentPermissionAccess.Write, "TEST1").Demand();
Environment.SetEnvironmentVariable("TEST1", "MyTest", EnvironmentVariableTarget.Machine);

Attempt 2

尝试 2

new EnvironmentPermission(EnvironmentPermissionAccess.Write, "TEST1").Demand();

using (var envKey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment", true))
{

  Contract.Assert(envKey != null, @"HKLM\System\CurrentControlSet\Control\Session Manager\Environment is missing!");
  envKey.SetValue("TEST1", "TestValue");
}

Attempt 3Also I tried to fit out my app with administrator priviliges.

尝试 3此外,我还尝试使用管理员权限来安装我的应用程序

Do you have any other suggestions?

你有什么其他的建议?

采纳答案by David Heffernan

The documentationtells you how to do this.

文档告诉您如何执行此操作。

Calling SetEnvironmentVariablehas no effect on the system environment variables. To programmatically add or modify system environment variables, add them to the HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environmentregistry key, then broadcast a WM_SETTINGCHANGEmessage with lParamset to the string "Environment". This allows applications, such as the shell, to pick up your updates.

调用SetEnvironmentVariable对系统环境变量没有影响。要以编程方式添加或修改系统环境变量,请将它们添加到HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment注册表项,然后WM_SETTINGCHANGE使用lParamset 为 string广播一条消息"Environment"。这允许应用程序(例如 shell)获取您的更新。

So, you need to write to the registry setting that you are already attempting to write to. And then broadcast a WM_SETTINGCHANGEmessage as detailed above. You will need to be running with elevated rights in order for this to succeed.

因此,您需要写入您已经尝试写入的注册表设置。然后广播一条WM_SETTINGCHANGE消息,如上详述。您需要以更高的权限运行才能成功。

Some example code:

一些示例代码:

using Microsoft.Win32;
using System;
using System.Diagnostics.Contracts;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
    class Program
    {
        const int HWND_BROADCAST = 0xffff;
        const uint WM_SETTINGCHANGE = 0x001a;

        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern bool SendNotifyMessage(IntPtr hWnd, uint Msg, 
            UIntPtr wParam, string lParam);

        static void Main(string[] args)
        {
            using (var envKey = Registry.LocalMachine.OpenSubKey(
                @"SYSTEM\CurrentControlSet\Control\Session Manager\Environment",
                true))
            {
                Contract.Assert(envKey != null, @"registry key is missing!");
                envKey.SetValue("TEST1", "TestValue");
                SendNotifyMessage((IntPtr)HWND_BROADCAST, WM_SETTINGCHANGE,
                    (UIntPtr)0, "Environment");
            }
        }
    }
}

However, whilst this code does work, the .net framework provides functionality to perform the same task much more simply.

然而,虽然此代码确实有效,但 .net 框架提供了更简单地执行相同任务的功能。

Environment.SetEnvironmentVariable("TEST1", "TestValue", 
    EnvironmentVariableTarget.Machine);

The documentationfor the three argument Environment.SetEnvironmentVariableoverload says:

三参数重载的文档Environment.SetEnvironmentVariable说:

If target is EnvironmentVariableTarget.Machine, the environment variable is stored in the HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager\Environment key of the local computer's registry. It is also copied to all instances of File Explorer. The environment variable is then inherited by any new processes that are launched from File Explorer.

If target is User or Machine, other applications are notified of the set operation by a Windows WM_SETTINGCHANGE message.

如果目标是 EnvironmentVariableTarget.Machine,则环境变量存储在本地计算机注册表的 HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager\Environment 键中。它还会复制到文件资源管理器的所有实例。然后,从文件资源管理器启动的任何新进程都会继承环境变量。

如果目标是用户或机器,则通过 Windows WM_SETTINGCHANGE 消息通知其他应用程序设置操作。

回答by Whosdatdev

In addition to David Heffernan's answer, here is a function that avoids a few gotchas for setting and appending a value to an environment variable:

除了 David Heffernan 的回答之外,这里还有一个函数可以避免一些设置和附加值到环境变量的问题:

void AddToEnvironmentVariable(string variable, string newValue, EnvironmentVariableTarget target)
{
    var content = Environment.GetEnvironmentVariable(variable, target) ?? string.Empty;
    if (content.Contains(newValue))
        return;

    var varBuilder = new StringBuilder(content);
    if (content != string.Empty && !content.EndsWith(';'))
        varBuilder.Append(";");
    varBuilder.Append(newValue);
    var finalValue = varBuilder.ToString();

    Environment.SetEnvironmentVariable(variable, finalValue, EnvironmentVariableTarget.Process);
    if (target != EnvironmentVariableTarget.Process)
        Environment.SetEnvironmentVariable(variable, finalValue, target);
}

It handles proper appending using ;and also ensures that subsequent calls to GetEnvironmentVariablecontain the added value by setting in with the Processtarget.

它处理正确的附加使用,;GetEnvironmentVariable通过设置Process目标来确保后续调用包含添加的值。