Windowsの環境変数とは?システムとユーザーの違い・優先順位を解説

当ページのリンクには広告が含まれています。
Windowsのシステム環境変数とユーザー環境変数の違い、同名変数はユーザー側が優先され、Pathは結合される仕組みを示した解説画像

PowerShellで新しいツールを入れた後パスを通そうとして「システム環境変数とユーザー環境変数どっちに追加すればいいんだっけ」と手が止まったこと、ありませんか。筆者も最初のころは適当に両方へ似たような値を追加してしまい、あとで「思った通りに反映されない」と首をかしげたことがあります。

個人だけで使う設定はユーザー環境変数、PCの全ユーザーで使う設定はシステム環境変数に入れるのが基本です。同名の通常変数が両方にある場合はユーザー側が優先されます。一方、Pathは上書きではなくMachine側とUser側が1つの検索パスとして結合されます。同名の実行ファイルが複数ある場合は、最終的なPathの前にあるフォルダーのものが先に使われます。

目次

この記事でわかること

  • システム環境変数とユーザー環境変数の適用範囲の違い
  • 同じ変数名が両方にあるとき、どちらが優先されるかのルール
  • Path変数だけが特別扱いされる理由
  • PowerShellで安全に確認・設定する具体的な方法

環境変数とは?

環境変数はWindowsという建物の掲示板に貼ってある共有メモのようなものです。プログラムは起動するときにこのメモを覗きに行き「実行ファイルはどこにあるんだっけ」「一時ファイルはどこに置けばいいんだっけ」といった情報を確認します。

たとえばPathという環境変数には「実行ファイルを探しにいくフォルダの一覧」が入っています。コマンドプロンプトやPowerShellでnodegitとだけ打って動くのは、これらの実行ファイルが置かれているフォルダがPathに登録されているからです。逆にPathに登録されていないフォルダにある実行ファイルは、フルパスを指定しない限り見つけてもらえません。

システム環境変数とユーザー環境変数の違い

環境変数には大きく分けて2種類あり、保存場所と適用範囲が異なります。

Windowsの環境変数は、プログラムが実行時に参照する設定値です。永続的な設定には「PC全体に適用されるMachineスコープ」「ログインユーザーだけに適用されるUserスコープ」があります。現在起動中のプログラムはそれらを元に作られたProcessスコープの環境変数を使います。

項目システム環境変数ユーザー環境変数
保存場所(レジストリ)HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\EnvironmentHKEY_CURRENT_USER\Environment
適用範囲そのPCを使う全ユーザーログイン中の自分だけ
変更に必要な権限管理者権限が必要特別な権限は不要
主な用途全ユーザー共通のツール(Node.jsやGitなど)の実行パス自分専用の環境(venvや個人ツールなど)

自分しか使わないPCであれば正直どちらに追加しても動作は変わらないことが多いです。チームで共有するPCや複数アカウントでログインする環境では、ユーザー環境変数に追加した設定は自分以外のアカウントには反映されない点に注意が必要です。

UserやMachineの環境変数を書き換えても既に起動しているPowerShell自身のProcess環境は自動で入れ替わりません。新しく起動したプロセスで確認してください。Windows Terminalなど親プロセスが古い環境を保持している場合は、タブだけでなくアプリ自体を開き直すと確実です。

同じ変数名をシステムとユーザーの両方に作ってみた

同じ名前の変数がシステム側とユーザー側の両方に存在した場合、Windowsはどちらの値を使うのでしょうか。

管理者権限のPowerShellでシステム側に値を設定します。

PowerShell
[System.Environment]::SetEnvironmentVariable('TEST_VAR', 'システム側の値です', 'Machine')

続けて通常権限のPowerShellでユーザー側にも同じ変数名で値を設定します。

PowerShell
[System.Environment]::SetEnvironmentVariable('TEST_VAR', 'ユーザー側の値です', 'User')

ここで新しいPowerShellウィンドウを開き直して確認してみます。

確認結果
PS C:\> $env:TEST_VAR
ユーザー側の値です

ユーザー側の値が優先されてますね。これはWindowsが環境変数を組み立てる際、システム側の値を先に読み込んだあとにユーザー側の値を読み込み、同じ名前があれば後から読んだ方で上書きするという処理をしているためです。

ではPathでも同じことをしたらどうなるでしょうか。システム側のPathにC:\SystemToolを、ユーザー側のPathにC:\MyToolを追加してみます。

確認結果
PS C:\> $env:Path -split ';' | Select-Object -First 3
C:\Program Files\PowerShell\7
C:\SystemTool
C:\MyTool

TEST_VARのときとは違い、ユーザー側の値がシステム側を消してしまうことはありません。システムのPathが先頭に並び、その後ろにユーザーのPathが結合される形になります。これはPathだけに用意された特別ルールで、システム定義の後ろにユーザー定義が「追記」される仕組みになっているので「Pathを上書きしてしまわないか」という心配は基本的に不要ということです。

Pathの優先順位は結合後の並び順で決まる

Pathはユーザー側がシステム側を上書きするのではなくWindowsが1本の検索パスとして組み合わせます。同じ名前の実行ファイルが複数のフォルダーにある場合、最終的な$env:Pathの前にあるフォルダーから順番に探されます。

「結局どのexeが使われているの?」という場合はPowerShellでGet-Commandを使うと確認できます。

PowerShell
Get-Command node

PowerShell 7のインストーラーにも「Add PowerShell to Path Environment Variable」という設定があります。実際のインストール画面を見ながら確認したい場合はこちらも参考にしてください。

PowerShellで安全に確認・設定する方法

環境変数についての公式情報もどうぞ。

現在の値をスコープ別に確認する

GetEnvironmentVariableの第2引数にスコープを指定するとシステム側とユーザー側を別々に確認できます。

PowerShell
# システム環境変数のPathを確認
[System.Environment]::GetEnvironmentVariable('Path', 'Machine')

# ユーザー環境変数のPathを確認
[System.Environment]::GetEnvironmentVariable('Path', 'User')

# 現在のセッションで実際に使われている合体後のPathを確認
$env:Path -split ';'

第2引数に指定できる値は次の3つです。

Machine

システム環境変数を意味します。書き込みには管理者権限が必要です。

User

ユーザー環境変数を意味します。管理者権限は不要です。

Process

現在動いているPowerShellプロセスが実際に持っている環境変数です。通常は親プロセスから引き継いだ値を持っていますが、起動後に変更することもできるためUserやMachineに保存されている値と必ず同じとは限りません。

ユーザー環境変数にPathを安全に追加する

いきなり値を代入すると既存のPathが消えてしまうので、必ず現在のPathの値を読み出してから前なり後ろに追加します。

PowerShell
$currentUserPath = [System.Environment]::GetEnvironmentVariable('Path', 'User')
$newPath = $currentUserPath + ';【追加したいフォルダのパス】'
[System.Environment]::SetEnvironmentVariable('Path', $newPath, 'User')

管理者権限は不要なので通常のPowerShellでそのまま実行できます。

システム環境変数を変更する場合の注意点

全ユーザーで共通のツールをPathに登録したい場合はMachineスコープを使いますが、必ず管理者としてPowerShellを起動してください。

PowerShell
$currentMachinePath = [System.Environment]::GetEnvironmentVariable('Path', 'Machine')
$newMachinePath = $currentMachinePath + ';【追加したいフォルダのパス】'
[System.Environment]::SetEnvironmentVariable('Path', $newMachinePath, 'Machine')

システム側は全ユーザーに影響するため、既存の値を消してしまうと他のアプリまで動かなくなることがあります。実行前に$currentMachinePathの中身をどこかにメモしておくと安心です。

setxコマンドを使うときに気をつけたいこと

Path編集の方法を調べるとsetx PATH "%PATH%;C:\追加したいフォルダ"のようなコマンドプロンプト向けの書き方もよく紹介されています。ただしsetxコマンドには1024文字の制限があります。1024文字を超えると警告は表示されますが、値は途中で切り詰められた状態で保存されるため、既存のPathを壊す原因になります。Pathの編集には、[System.Environment]::SetEnvironmentVariable()か、Windowsの環境変数画面を使う方が安全です。

Windowsの環境変数画面はWin + R > sysdm.cplと入力 > 詳細設定 > 環境変数でアクセスできます。

Windowsの「環境変数」画面で、ユーザー環境変数とシステム環境変数の一覧を表示
Windowsの環境変数画面ではユーザー変数とシステム変数を確認・編集できます

よくある質問

GUI(設定画面)とPowerShell、環境変数はどちらで編集すればいい?

一度だけの追加であればシステムのプロパティ画面から開ける「環境変数」ダイアログでも十分です。一覧形式で編集できるので誤操作が少なく済みます。何度も同じ作業をする場合やセットアップ手順をスクリプト化したい場合はPowerShellが向いています。

環境変数を変更したのにPowerShellで認識されない

新しいウィンドウを開いていない可能性が高いです。すでに開いているPowerShellやコマンドプロンプトのセッションは起動した時点の環境変数を持ったままなので、変更を反映するには新しいウィンドウを開くか、一度ログアウトしてログインし直す必要があります。

レジストリを直接編集して大丈夫?

可能ですが編集後にWM_SETTINGCHANGEというメッセージをシステムに送らないと既に起動しているエクスプローラーなどに変更がすぐ反映されないことがあります。特別な理由がなければシステムのプロパティ画面か[System.Environment]クラス経由での編集をおすすめします。

環境変数以外のPowerShell基本操作や実行ポリシー、よく使うコマンドもまとめて確認したい場合はこちら。

まとめ

  • システム環境変数は全ユーザー共通、ユーザー環境変数は自分専用の設定だよ。
  • 同じ名前の変数が両方にある場合はユーザー環境変数が優先されるよ。
  • でもPathだけは特別で、システムとユーザーの両方が結合されて使われるよ。
  • Pathを編集するときはsetxコマンドの1024文字制限に気をつけてね。
  • 変更を反映するには新しいウィンドウを開くのを忘れないでね。

Windowsの設定変更やトラブル対処をまとめて探したい場合はこちらも参考にしてください。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次