【问题标题】:How to set system environment variable in C#?如何在 C# 中设置系统环境变量?
【发布时间】:2013-11-11 09:25:53
【问题描述】:

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

尝试 1

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

尝试 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");
}

尝试 3 我也尝试过调整我的app with administrator priviliges

您还有其他建议吗?

【问题讨论】:

  • 你不能只是去获得许可。你需要被提升。这需要在进程启动时完成。

标签: c# .net environment-variables


【解决方案1】:

documentation 告诉您如何执行此操作。

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

因此,您需要写入您已经尝试写入的注册表设置。然后如上所述广播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");
            }
        }
    }
}

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

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

三个参数Environment.SetEnvironmentVariable 重载的documentation 表示:

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

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

【讨论】:

  • 如我所说,调用OpenSubKey 函数也会以异常结束,尽管密钥可用
  • 正如我所说,你需要运行这个提升。当你这样做时,你会发现它有效。我确实测试了你知道的这段代码!
  • 啊,它有效!非常感谢。是否有命令或参数来确认此 UAC 警告?
  • 如果有这样的事情,那会使 UAC 毫无意义,不是吗。如果你想做管理员任务,你需要成为管理员。没有办法摆脱这一点。
  • 值得注意的是,即使在最新的 4.6.2 版本中,.Net Framework 中的 SetEnvironmentVariabl() 函数也存在不检查您是否正在设置 PATH 变量的错误——它对待它们都是一样的,并且它会默默地将 PATH 的注册表项类型从 REG_EXPAND_SZ 更改为 REG_SZ,从而取消在 PATH 中使用变量扩展的能力。不用说,许多程序(和计算机用户)都依赖于 PATH 扩展。
猜你喜欢
  • 2017-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多