PowerShellで環境変数を取り扱う（永続的な変更）

[PowerShellで環境変数を取り扱う（現在のコンソール）](https://qiita.com/SAITO_Keita/items/c78aac6d03e400b5127f) にてPowerShellの現在のコンソールで環境変数を取り扱う記事を書きました。

本記事では一時的な変更ではなく、PowerShellでの永続的な変更について記載します。

## ドキュメント

[about_Environment_Variables](https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_environment_variables)

公式ドキュメントに環境変数についての資料が用意されており、ここを確認すればOK。

## 永続的な変更について

[環境変数に対する変更の保存](https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_environment_variables?view=powershell-7.3#saving-changes-to-environment-variables)

上記記事では、下記の3種類の方法に記載されています。

- ①プロファイルでの環境変数の保存
- ②SetEnvironmentVariable を使用した環境変数の保存
- ③System コントロール パネル を使用した環境変数の保存

本記事では、①プロファイルでの環境変数の保存と②SetEnvironmentVariable を使用した環境変数の保存の方法について記載します。

### プロファイルでの環境変数の保存

PowerShellの起動プロファイルに、現在のコンソールのときと同様な,`$Env:<variable-name> = "<new-value>"`の形式で書くことで、PowerShellを起動する際に毎回、環境変数を定義して永続化する方法となります。

PowerShellの起動プロファイルの場所については、変数`$profile`で確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/120d09fb-2128-c3e7-0dff-b254c5dd52d1.png)

ここで表示されるパスのファイルに記載すればOKです。

下記は`Oh My Posh`で利用する環境変数`POSH_GIT_ENABLED`を起動プロファイルに記載することで、PowerShellコンソールを起動する際に毎度設定している例。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/e8d664d7-823a-8408-b7db-6b9b7f122ca8.png)

### SetEnvironmentVariable を使用した環境変数の保存

[Environment.SetEnvironmentVariable メソッド](https://learn.microsoft.com/ja-jp/dotnet/api/system.environment.setenvironmentvariable?view=net-7.0)

環境変数にはプロセススコープ、ユーザースコープ、マシンスコープといった3種類のスコープが用意されており。
ここまででの変更はすべてプロセススコープへの変更となっていました。

プロセススコープの範囲は現在のコンソールのみとなっており、コンソールが終了すると設定が消えてしまいますが、ユーザースコープとマシンスコープの設定については、現在のプロセス外部で保持されるため、現在のコンソールが終了しても、設定が永続的に保持されます。

PowerShellでユーザースコープ、マシンスコープの設定変更を行うには、.Netで用意されている　`SetEnvironmentVariable`メソッド　を利用します。

`SetEnvironmentVariable`メソッドでは環境変数を設定するスコープを指定する事ができ、引数に指定がない場合プロセススコープに設定されますが、引数にスコープを設定することで、ユーザースコープ、マシンスコープに永続的に環境変数を設定する事ができます。

なおマシンスコープに設定を行う際は、適切なアクセス許可がないと失敗するので、注意してください。

なお今回の例ではユーザースコープに設定変更を追加しています。

```powershell
# 環境変数Fooに Bar　という値　ユーザーコープに設定
[Environment]::SetEnvironmentVariable('Foo', 'Bar', 'User')

# GetEnvironmentVariablesメソッドで引数をMachineにしてユーザーコープの環境変数を取得
[Environment]::GetEnvironmentVariables('User')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/ce2680db-6cc3-584a-f75d-370e8dd02727.png)

上記コマンドでユーザースコープに環境変数が設定とその設定を確認できます。

ユーザースコープに追加された環境変数となるため。
一度コンソールを閉じて別のコンソールを開いた場合でも環境変数Fooが設定されており、永続化されている事を確認できるかと思います。

なおユーザースコープに設定した環境変数を削除する場合は、空文字をSetEnvironmentVariableで設定すれば削除されます。

```powershell
# GetEnvironmentVariableで引数に環境変数名とスコープを指定して取得
[Environment]::GetEnvironmentVariable('Foo','User')

# ユーザースコープの環境変数Fooに空文字を設定して環境変数Fooを削除
[Environment]::SetEnvironmentVariable('Foo', '', 'User')

# GetEnvironmentVariableで引数に環境変数名とスコープを指定して取得
[Environment]::GetEnvironmentVariable('Foo','User')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/a5ffe2dd-6495-4600-46b4-9701106554e9.png)

## 総評

環境変数を永続的に変更する場合は、環境変数のプロセススコープ、ユーザースコープ、マシンスコープについて理解している必要があるかと思います。

プロファイルでの環境変数の保存　ではPowerShellコンソールを開く度にプロセススコープに環境変数を書き込み、永続化。（プロセススコープでは毎回設定が消えてしまうが、起動するたびに書いているので永続化される）

SetEnvironmentVariable については、ユーザースコープ、マシンスコープについて書き込み、ユーザスコープ、マシンスコープはプロセス外部で保存されるため設定が永続化される。

なお今回のSetEnvironmentVariableメソッドを使った方法は永続的な変更となり、既存環境設定を破壊してしまう危険もあるため。
実行前には設定内容についてはよく確認してから実行して下さい。