5

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)が、アプリケーションの起動時の変数と同じであることです。しかし、それは更新変数ではありません。

これらの変数をシステムから直接取得する方法はありますか?

4

2 に答える 2

3

環境変数には 3 つのセットがあります - マシンからのグローバル変数、ユーザーが保存した変数、現在のプロセスの変数です。

Environment.SetEnvironmentVariable(key, value)現在のプロセスの変数を設定します。使用する必要がある現在のプロセス変数を読み取るために、グローバルまたはユーザーの変数は変更しません。Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Process)

子プロセスを実行すると、プロセス環境変数が子プロセス環境変数にコピーされます。

更新(およびコメントへの回答):

環境変数がどのように機能するかを誤解していると思います。プロセスの作成中に親プロセスから子プロセスにデータを渡すためにのみ使用でき、プロセス間でデータを渡すために使用することはできません。

これは、環境変数がどのように機能するかです:

各プロセスには、環境変数の独自のプライベート コピーがあり、各プロセスはいつでもそのプライベート コピーを変更できます。これは、システムの残りの部分にまったく影響を与えないプライベート コピーです。

あるプロセスが別のプロセスを開始すると、親のプライベート環境変数が新しい子プロセスにコピーされます。その操作の後、新しい子プロセスには、親プロセスに接続されていない環境変数のプライベート コピーがあります。

レジストリに格納されているマシンとユーザーの環境変数があります。これらは、起動時に最初のプロセスに渡される値です (また、再起動を節約するために、適切な通知を送信すると、Windows エクスプローラーは新しいプロセスの開始時にそれらを読み込みます)。プロセスの環境変数は、ユーザー/マシンの設定を変更しません。ユーザー/マシンの設定を変更しても、実行中のプロセスには影響しません。

たとえば、2 つのコマンド (cmd.exe) ウィンドウを実行し、一方のウィンドウで SET コマンドを使用して環境を変更し、もう一方のウィンドウで SET コマンドを実行して、何も変更されていないことを確認します。

したがって、「システムの現在の環境」などというものはありません。あるプロセスがその環境を変更した場合、別のプロセスがこの変更を検出して読み取る方法はありません (デバッガーが他のプロセスのメモリを読み取れるようにする API を使用する場合を除きますが、実際にはそこには行きたくない)。

于 2012-12-24T14:45:34.967 に答える
1

新しいプロセスを作成する前に WM_SETTINGCHANGED メッセージをブロードキャストすると、新しい環境設定が継承されると思います。そのため、Windows SDK の PostMessage() または SendMessage() 関数を pInvoke する必要があります。LPARAM および WPARAM パラメータに 0 を渡すだけです。

于 2012-12-24T14:27:15.127 に答える