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

ale*_*555 7 .net c# environment-variables

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

尝试1

new EnvironmentPermission(EnvironmentPermissionAccess.Write, "TEST1").Demand();
Environment.SetEnvironmentVariable("TEST1", "MyTest", EnvironmentVariableTarget.Machine);
Run Code Online (Sandbox Code Playgroud)

尝试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");
}
Run Code Online (Sandbox Code Playgroud)

尝试3 此外,我试图用管理员权限装配我的应用程序.

你有什么其他的建议?

Dav*_*nan 23

文件会告诉你如何做到这一点.

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

因此,您需要写入您已尝试写入的注册表设置.然后WM_SETTINGCHANGE如上所述广播消息.您需要以提升的权限运行才能成功.

一些示例代码:

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");
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Environment.SetEnvironmentVariable("TEST1", "TestValue", 
    EnvironmentVariableTarget.Machine);
Run Code Online (Sandbox Code Playgroud)

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

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

如果target是User或Machine,则通过Windows WM_SETTINGCHANGE消息向其他应用程序通知设置操作.

  • 如果有这样的事情,那将使UAC变得毫无意义.如果要执行管理任务,则需要成为管理员.没有远离那个. (4认同)
  • 值得注意的是,即使在最新的 4.6.2 版本中,.Net Framework 中的 SetEnvironmentVariabl() 函数也有一个错误,即不检查您是否正在设置 PATH 变量 - 它对它们都是相同的,并且会默默地更改注册表项类型将 PATH 从 REG_EXPAND_SZ 更改为 REG_SZ,从而终止在 PATH 中使用变量扩展的能力。不用说,许多程序(和计算机用户)都依赖于 PATH 扩展。 (2认同)