システム環境変数Pathにパスを追加する


作成しているアプリケーションを別のPCに実装することになりました。その中で、システム環境変数Pathへの登録が前提となっているソフトがあるので、どうせならその設定を自動で行ってくれるアプリを作成しようと考えました。

管理者権限の付与

システム環境変数の変更なので管理者権限での実行が必要となります。

  1. 「ソリューションエクスプローラー」の中にあるプロジェクトのノードを右クリックする
  2. 追加を選択し、その中の「新しい項目」を左クリックする

  3. Visual C# アイテムから「アプリケーション マニフェスト ファイル」を追加する(名前はデフォルトのままでOK)

app.manifestは下のような構成をしています。

app.manifest
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
  <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
        <!-- UAC マニフェスト オプション
             Windows のユーザー アカウント制御のレベルを変更するには、
             requestedExecutionLevel ノードを以下のいずれかで置換します。

        <requestedExecutionLevel  level="asInvoker" uiAccess="false" />
        <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />
        <requestedExecutionLevel  level="highestAvailable" uiAccess="false" />

            requestedExecutionLevel 要素を指定すると、ファイルおよびレジストリの仮想化が無効にされます。
            アプリケーションが下位互換性を保つためにこの仮想化を要求する場合、この要素を
            削除します。
        -->
        <requestedExecutionLevel level="asInvoker" uiAccess="false" />
      </requestedPrivileges>
    </security>
  </trustInfo>

  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>

(以下略……)

このうち19行目付近にあるrequestedExecutionLevel level="asInvoker"内「asInvoker」を「requireAdministrator」に変更することでアプリケーション実行前に付与の確認を行うウィンドウを出すことができます。
このほかコードで処理ごとに付与の確認をする方法もありますが、実行時に挙動がおかしくなったのでおすすめしません。

環境変数Pathへの追加

さて本題。システム環境変数への追加はEnvironment.SetEnvironmentVariableを使うと楽に設定が可能です。こんな風に。

Form1.cs
Environment.SetEnvironmentVariable("SofTalk", 
$"C:\\softalk\\", EnvironmentVariableTarget.Machine);

しかし、追加と言っても実際はPathといった既に変数が存在する場合は値を上書きしてしまいます。システム環境変数を変更前に戻すには修復ポイントからのシステム修復くらいしか方法がないため、非常に面倒。そこで変更前のPath内の値を取得し、それに追加したいパスを付け加えた値を新たに定義する必要があります。
という事で、以下がパスの追加に関するコード。C:\\softalk\\の部分は適宜変えてください。

2/11改訂:文字列取得した場合、複数の値の場合は「;」で区切っているため追加したいパスの前に「;」を追加した方がいいようです。コードは修正済み。

Form1.cs
//変更前の環境変数Pathの値を全て取得
string base_paths = System.Environment.GetEnvironmentVariable("Path", 
System.EnvironmentVariableTarget.Machine);

//環境パス設定
Environment.SetEnvironmentVariable("Path", 
base_paths + ";" + "C:\\softalk\\", EnvironmentVariableTarget.Machine);

参考サイト

管理者権限の付与方法
https://www.ipentec.com/document/csharp-run-as-administrator-using-manifest-file
システム環境変数への追加方法
http://hensa40.cutegirl.jp/archives/2733