Search code examples
windowspowershellpathchef-infrachef-solo

append to path for all users in windows programmatically.


I am appending to windows path in chef but it only reflects for administrator (uses to administrator to append to path)

# append dnx.exe to %PATH%
windows_path '%USERPROFILE%\\.dnx\\runtimes\\dnx-coreclr-win-x64.1.0.0-rc1-update1\\bin' do
  action :add
end

Is there a command to append to path and make it available for all users of windows programmatically ?


Solution

  • I don't have experience with Chef, but the canonical way to add something to the PATH environment variable for all users is to append it to the variable in the machine environment rather than the user environment. In PowerShell you do it like this:

    $path = [Environment]::GetEnvironmentVariable('PATH', 'Machine')
    $path += ';%USERPROFILE%\.dnx\runtimes\dnx-coreclr-win-x64.1.0.0-rc1-update1\bin'
    [Environment]::SetEnvironmentVariable('PATH', $path, 'Machine')
    

    If you want to merge that into a single statement it'd look somewhat like this:

    [Environment]::SetEnvironmentVariable('PATH', ([Environment]::GetEnvironmentVariable('PATH', 'Machine') + ';%USERPROFILE%\.dnx\runtimes\dnx-coreclr-win-x64.1.0.0-rc1-update1\bin'), 'Machine')
    

    However, you may not want to simply append to the variable, as that might keep adding the path to the variable over and over again. To avoid that you could do something like this:

    $dir  = '%USERPROFILE%\.dnx\runtimes\dnx-coreclr-win-x64.1.0.0-rc1-update1\bin'
    $path = [Environment]::GetEnvironmentVariable('PATH', 'Machine') -split ';' |
            Where-Object { $_ -ne $dir }
    $path += $dir
    [Environment]::SetEnvironmentVariable('PATH', ($path -join ';'), 'Machine')
    

    Edit: I just realized that [Environment]::SetEnvironmentVariable() can't be used in your case. While the method will set the variable to the string you pass into it, that string will be stored as a REG_SZ value in the registry. Which will prevent variables inside the string (like %USERPROFILE%) from being expanded when the path is looked up, kinda making the whole thing pointless.

    To avoid this pitfall you must ensure that the path is stored in a REG_EXPAND_SZ value, e.g. like this:

    $regkey = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
    Set-ItemProperty -Path $regkey -Name 'Path' -Value $path -Type ExpandString