【问题标题】:C# Reload Systems environment variablesC# 重新加载系统环境变量
【发布时间】:2012-12-24 14:09:00
【问题描述】:

当我启动 C# 进程时,系统环境变量会被其他一些进程更改。所以我想将环境重新加载到我的进程中,因为这个应用程序也会启动需要具有更新环境的子进程。这是我尝试获取和设置环境变量的方式:

Dictionary<String,String> uservars= new Dictionary<String,String>();
  Dictionary<String, String> sysvars = new Dictionary<String, String>();
  foreach (System.Collections.DictionaryEntry de in System.Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine))
    sysvars.Add(de.Key.ToString().ToUpper(),de.Value.ToString());

  foreach (System.Collections.DictionaryEntry de in System.Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User))
  {
    uservars.Add(de.Key.ToString().ToUpper(), de.Value.ToString());
  }
  Dictionary<string, string> newdict = new Dictionary<string, string>();
  foreach (KeyValuePair<String, String> kvp in uservars)
  {
    if (sysvars.ContainsKey(kvp.Key))
    {
      newdict.Add(kvp.Key, kvp.Value + ";" + sysvars[kvp.Key]);
      sysvars.Remove(kvp.Key);
    }
    else
      newdict.Add(kvp.Key, kvp.Value);
  }
  foreach (KeyValuePair<string, string> kvp in sysvars)
    newdict.Add(kvp.Key, kvp.Value);

  foreach (KeyValuePair<string, string> kvp in newdict)
  {
    System.Environment.SetEnvironmentVariable(kvp.Key, kvp.Value);
  }

问题是,我使用System.Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User) 获得的环境变量与我的应用程序启动时的变量相同。但这不是更新变量。

有没有办法直接从系统中获取这些变量。

【问题讨论】:

  • 另外我想提一下:如果我尝试使用 RegistryKey regEnvir = Registry.CurrentUser.OpenSubKey("Environment"); 从注册表中获取环境变量从我启动应用程序开始,我也得到了旧的变量集。
  • 密钥错误,系统环境存放在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment。如果你没有看到它改变,那么这个程序只会修改它自己的环境。并可能将其传递给它启动的进程。

标签: c# .net environment-variables


【解决方案1】:

有3组环境变量——来自机器的全局变量、用户保存的变量和当前进程的变量

Environment.SetEnvironmentVariable(key, value)设置当前进程的变量,不改变全局或用户变量,读取当前进程变量需要使用Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Process)

当您运行子进程时,您的进程环境变量会被复制到子进程环境变量中。

更新(并回复评论):

我想你误解了环境变量的工作原理,它们只能用于在进程创建过程中将数据从父进程传递给子进程,不能用于在进程之间传递数据。

这就是环境变量的工作方式:

每个进程都有自己的环境变量私有副本,每个进程都可以随时更改该私有副本,它是一个私有副本,对系统的其余部分没有任何影响。

当一个进程启动另一个进程时,父进程的私有环境变量将复制到新的子进程,在该操作之后,新的子进程拥有一个不再连接到父进程的环境变量的私有副本。

注册表中存储了机器和用户环境变量,这些是在启动时第一个进程传递的值(并且,为了保存重启,如果您发送正确的通知,Windows 资源管理器将在启动新进程时加载它们) 更改进程的环境变量不会更改用户/机器设置,更改用户/机器设置不会影响任何正在运行的进程。

例如,运行两个命令(cmd.exe)窗口,在一个窗口中使用 SET 命令更改环境,然后在另一个窗口中运行 SET 命令,发现没有任何变化。

所以,没有“系统当前环境”这样的东西,如果一个进程改变了它的环境,另一个进程就没有办法发现和读取这个变化(除了使用让调试器读取其他进程内存的 API,但你真的不想去那里)。

【讨论】:

  • 这是我所知道的。我的问题是,如何获取系统当前环境变量集。场景如下:当我的应用程序在时间 t0 运行时,用户或脚本更改系统环境变量。在时间 t1,用户想要在应用程序上启动操作。到目前为止,我的应用程序将从系统获取当前环境集并更新它自己的环境变量。然后这个应用程序也会创建子进程等。
【解决方案2】:

我相信如果您在创建新进程之前广播 WM_SETTINGCHANGED 消息,它将继承新的环境设置。因此,您需要 pInvoke Windows SDK PostMessage() 或 SendMessage() 函数。只需为 LPARAM 和 WPARAM 参数传递 0。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-17
    • 1970-01-01
    • 2015-08-04
    • 2010-11-24
    • 2012-03-29
    • 1970-01-01
    • 2021-11-29
    • 2015-05-25
    相关资源
    最近更新 更多