Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 24 additions & 14 deletions src/chocolatey.resources/redirects/RefreshEnv.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -11,53 +11,63 @@
::echo "RefreshEnv.cmd only works from cmd.exe, please install the Chocolatey Profile to take advantage of refreshenv from PowerShell"
echo | set /p dummy="Refreshing environment variables from registry for cmd.exe. Please wait..."

:: Generate unique file names
for /F "tokens=* usebackq" %%F IN (`powershell -command "[guid]::NewGuid().ToString()"`) do set REFRESHENV_GUID=%%F
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would require at least a 2 second start up time for PowerShell. Not that I'm against that, but that is longer than the entire thing takes to run now. So this is more than doubling the time. Are there any other methods?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm afraid pure CMD doesn't provide anything reliable we could really use. Sounds an odd idea but what if we just implemented some tiny win32 application (with C) that would only print its process ID and that would be used as the random part of the temporary file names? The executable would be so small that it could be even put into version control beside RefreshEnv.cmd.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LOL! 13 824 bytes :)

#include <stdio.h>
#include <processthreadsapi.h>

void main()
{
    printf("%d", GetCurrentProcessId());
}

gcc pid.c -o pid.exe -s -Os

set REFRESHENV_ENVSET_TMP="%TEMP%\refreshenv_envset_%REFRESHENV_GUID%.tmp"
set REFRESHENV_ENVGET_TMP="%TEMP%\refreshenv_envget_%REFRESHENV_GUID%.tmp"
set REFRESHENV_ENV_CMD="%TEMP%\refreshenv_env_%REFRESHENV_GUID%.cmd"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's put this somewhere else besides temp. Somewhere more locked down, like a temp folder under the Chocolatey directories that is locked down.


goto main

:: Set one environment variable from registry key
:SetFromReg
"%WinDir%\System32\Reg" QUERY "%~1" /v "%~2" > "%TEMP%\_envset.tmp" 2>NUL
for /f "usebackq skip=2 tokens=2,*" %%A IN ("%TEMP%\_envset.tmp") do (
"%WinDir%\System32\Reg" QUERY "%~1" /v "%~2" > %REFRESHENV_ENVSET_TMP% 2>NUL
for /f "usebackq skip=2 tokens=2,*" %%A IN (%REFRESHENV_ENVSET_TMP%) do (
echo/set "%~3=%%B"
)
goto :EOF

:: Get a list of environment variables from registry
:GetRegEnv
"%WinDir%\System32\Reg" QUERY "%~1" > "%TEMP%\_envget.tmp"
for /f "usebackq skip=2" %%A IN ("%TEMP%\_envget.tmp") do (
"%WinDir%\System32\Reg" QUERY "%~1" > %REFRESHENV_ENVGET_TMP%
for /f "usebackq skip=2" %%A IN (%REFRESHENV_ENVGET_TMP%) do (
if /I not "%%~A"=="Path" (
call :SetFromReg "%~1" "%%~A" "%%~A"
)
)
goto :EOF

:main
echo/@echo off >"%TEMP%\_env.cmd"
echo/@echo off >%REFRESHENV_ENV_CMD%

:: Slowly generating final file
call :GetRegEnv "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" >> "%TEMP%\_env.cmd"
call :GetRegEnv "HKCU\Environment">>"%TEMP%\_env.cmd" >> "%TEMP%\_env.cmd"
call :GetRegEnv "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" >> %REFRESHENV_ENV_CMD%
call :GetRegEnv "HKCU\Environment">>%REFRESHENV_ENV_CMD% >> %REFRESHENV_ENV_CMD%

:: Special handling for PATH - mix both User and System
call :SetFromReg "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" Path Path_HKLM >> "%TEMP%\_env.cmd"
call :SetFromReg "HKCU\Environment" Path Path_HKCU >> "%TEMP%\_env.cmd"
call :SetFromReg "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" Path Path_HKLM >> %REFRESHENV_ENV_CMD%
call :SetFromReg "HKCU\Environment" Path Path_HKCU >> %REFRESHENV_ENV_CMD%

:: Caution: do not insert space-chars before >> redirection sign
echo/set "Path=%%Path_HKLM%%;%%Path_HKCU%%" >> "%TEMP%\_env.cmd"
echo/set "Path=%%Path_HKLM%%;%%Path_HKCU%%" >> %REFRESHENV_ENV_CMD%

:: Cleanup
del /f /q "%TEMP%\_envset.tmp" 2>nul
del /f /q "%TEMP%\_envget.tmp" 2>nul
del /f /q %REFRESHENV_ENVSET_TMP% 2>nul
del /f /q %REFRESHENV_ENVGET_TMP% 2>nul
set REFRESHENV_GUID=
set REFRESHENV_ENVSET_TMP=
set REFRESHENV_ENVGET_TMP=

:: capture user / architecture
SET "OriginalUserName=%USERNAME%"
SET "OriginalArchitecture=%PROCESSOR_ARCHITECTURE%"

:: Set these variables
call "%TEMP%\_env.cmd"
call %REFRESHENV_ENV_CMD%

:: Cleanup
del /f /q "%TEMP%\_env.cmd" 2>nul
del /f /q %REFRESHENV_ENV_CMD% 2>nul
set REFRESHENV_ENV_CMD=

:: reset user / architecture
SET "USERNAME=%OriginalUserName%"
Expand Down