Windows PATH Variable Expansion Issue: Unexpanded Environment Variables in Non-Admin CMD


2 views

On Windows 7 systems, we're observing an odd behavior where environment variables in the %PATH% aren't being expanded when Command Prompt (cmd.exe) is launched with standard user privileges, while they expand correctly when running as Administrator.

# Non-admin CMD output:
Path=%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;C:\Program Files\Microsoft Windows Performance Toolkit\

# Admin CMD output: 
Path=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;C:\Program Files\Microsoft Windows Performance Toolkit\

The system appears to be reading the correct PATH definitions:

  • No user-specific override in HKEY_CURRENT_USER\Environment\PATH
  • System PATH in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\Path matches GUI settings

Here are several approaches to resolve this:

1. Forced Expansion via Batch Script

@echo off
:: This script forces PATH expansion
for /f "usebackq tokens=*" %%i in (reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v Path ^| find "REG_EXPAND_SZ") do (
    set "raw_path=%%i"
)
set "expanded_path=%raw_path:*REG_EXPAND_SZ=%"
set "expanded_path=%expanded_path:%%SystemRoot%%=%SystemRoot%"
set "PATH=%expanded_path%"

2. PowerShell Alternative

# Get expanded PATH value
$expandedPath = [System.Environment]::ExpandEnvironmentVariables([System.Environment]::GetEnvironmentVariable('Path', 'Machine'))

# Apply to current session
[System.Environment]::SetEnvironmentVariable('Path', $expandedPath, 'Process')

This behavior might stem from:

  • Registry permissions preventing proper variable expansion
  • Group Policy settings affecting environment variable processing
  • Corrupted user profile templates
  • Windows 7 specific bugs in environment variable handling

To further investigate:

# Check environment variable source
reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v Path

# Verify process environment block
wmic process where name='cmd.exe' get Caption,CommandLine,ProcessId,Environment

For a lasting solution:

  1. Create a login script that expands variables
  2. Modify system PATH to use absolute paths instead of variables
  3. Update to a newer Windows version if possible

The unexpanded PATH primarily affects:

  • Command-line tools relying on system directories
  • Build systems and development tools
  • Scripts assuming expanded PATH variables

When diagnosing PATH issues on Windows 7, I stumbled upon a peculiar behavior where environment variables in %PATH% wouldn't expand for standard users but worked perfectly in elevated command prompts. Here's what I found:

REM Standard user CMD output:
set path
Path=%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\Wbem;...

REM Admin CMD output:
set path
Path=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\Wbem;...

The system stores PATH values in two key locations:

REM System-wide PATH
reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v Path

REM User-specific PATH (absent in this case)
reg query "HKCU\Environment" /v Path

Surprisingly, both standard and admin sessions read from the same registry location, yet process the values differently.

Using Sysinternals Process Monitor, I captured the difference in behavior:

  1. Standard user CMD reads PATH but doesn't expand environment variables
  2. Admin CMD performs full environment variable expansion
  3. Both inherit from the same registry key

Here are three approaches to resolve this:

1. Manual Expansion in Batch Files

@echo off
for /f "tokens=1,* delims==" %%A in ('set PATH') do (
    if /i "%%A"=="PATH" (
        set ExpandedPath=%%B
    )
)
set ExpandedPath

2. PowerShell Alternative

$env:Path = [System.Environment]::ExpandEnvironmentVariables($env:Path)
Write-Output "Expanded PATH: $env:Path"

3. Permanent Registry Fix

Create a login script that updates the PATH:

reg add "HKCU\Environment" /v Path /t REG_EXPAND_SZ /d "%SystemRoot%\system32;%SystemRoot%;..." /f

Windows 7 handles environment variable inheritance differently between standard and elevated sessions. The security context affects how the OS processes REG_EXPAND_SZ values from the registry.

For administrators, Windows performs complete expansion during session creation. Standard users get the raw registry values with variables intact, requiring manual expansion.

Use this batch script to verify PATH expansion:

@echo off
echo Standard PATH: %PATH%
echo.
echo Expanded PATH:
for %%A in (%PATH%) do echo %%~A
pause

Remember that some applications may still fail to expand variables even after these fixes, particularly older Win32 apps that read the registry directly.