C#でWindowsのシステム環境変数を取得するときに値として埋め込まれている環境変数を展開しないで取得する

題名長い (;´д`)

環境変数を取得して改変してセットしたいときに値として埋め込まれた環境変数が展開されてしまうと不都合があると思います。

システム環境変数Pathを取得して変更する例

システム環境変数(例えばPath)を取得したい場合、いくつかやり方があるけど以下のようにすると簡単ですよね。

string env = "Path";
string value = Environment.GetEnvironmentVariable(env, EnvironmentVariableTarget.Machine);
Console.WriteLine(string.Format("{0}={1}", env, value);

以下のような値が取れたとします。

Path=C:\Program Files\Java\jre1.8.0_111\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\ProgramData\chocolatey\bin

ただ環境変数GUIから確認すると、以下のようになっています。

Path=%JAVA_HOME%\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\ProgramData\chocolatey\bin

取得した値に追加のパスを入れて保存したら%JAVA_HOME%\binC:\Program Files\Java\jre1.8.0_111\binに変わってしまいますよね。これは嬉しくありません。

というわけで、レジストリから取得すれば展開前の値が取れました。

using Microsoft.Win32;

string env = "Path";
RegistryKey reg = Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Control\Session Manager\Environment");
string value = (String)reg.GetValue(env, "", RegistryValueOptions.DoNotExpandEnvironmentNames);
Console.WriteLine(string.Format("{0}={1}", env, value);

GetValueの第3引数にRegistryValueOptions.DoNotExpandEnvironmentNames渡すと展開されずに取得できます。

意外と手こずったのでφ(..)メモメモ