C#Reload Systems环境变量

时间:2012-12-24 14:09:00

标签: c# .net environment-variables

当我启动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)获得的环境变量与我的应用程序启动时的变量相同。但那不是更新变量。

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

2 个答案:

答案 0 :(得分:3)

有3组环境变量 - 来自机器的全局变量,用户保存的变量和当前过程的变量

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

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

更新(并回答评论):

我认为您误解了环境变量的工作原理,它们只能用于在创建流程期间将数据从父流程传递到子流程,它们不能用于在流程之间传递数据。

环境变量的工作原理如下:

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

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

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

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

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

答案 1 :(得分:1)

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