Persistently set environment variables on Windows

Set a user or machine environment variable for good — the three scopes ($env:, User, Machine) explained, and why setx truncates.

WindowsenvironmentdeveloperpowershellMedium risk
Run `[Environment]::SetEnvironmentVariable('JAVA_HOME', '<path>', 'User')` to persist a variable; pass 'Machine' system-wide.

01Command

Command
$ [Environment]::SetEnvironmentVariable('JAVA_HOME', 'C:\Program Files\Java\jdk-21', 'User')

02What it does

$env:JAVA_HOME = '...' only lasts for that PowerShell session; SetEnvironmentVariable with a Target writes to the registry so every future process inherits it. A deliberate quirk: the current session still won't see it — also set $env:JAVA_HOME in the same script if you need it immediately. In CMD the equivalent is `setx JAVA_HOME "..."`, which persists too but silently truncates values over 1024 characters — a famous trap when editing PATH this way.

03Risk

RiskMedium risk
Requirements'Machine' scope requires an elevated prompt. Already-open terminals won't see the change until restarted.
!Warning: Never set the whole PATH with setx or SetEnvironmentVariable by hand — it merges User and Machine PATH for processes, and naive overwrites have destroyed users' PATHs.

04Undo

Undo
$ [Environment]::SetEnvironmentVariable('JAVA_HOME', $null, 'User')

05Sources

  • Environment.SetEnvironmentVariable Method | Microsoft Learn
    Microsoft · vendor-doc · 2026-09-17
    Evidence: Microsoft documents SetEnvironmentVariable(name, value, EnvironmentVariableTarget) where Machine/User persist to the registry and passing null deletes the variable.
  • SETX - Windows CMD
    SS64 · technical · 2026-09-17
    Evidence: SS64 documents setx persisting environment variables to the registry for future sessions, without affecting the current one.

Last verified: 2026-09-17 · Category: Developer

06Related solutions