Set environment variables with NSIS in Window 7
Asked Answered
D

3

0

I want to set environment variable using NSIS installer. I will run script on Windows 7, if it is important. Thanks!

Donegan answered 16/10, 2012 at 12:4 Comment(5)
Set them for what? A child process? Permanent per-user or machine wide?Echo
Sorry, I dont know NSIS as well, to answer your question. I just want to add a new variable , during installation process. Thanks!Donegan
My question is not NSIS specific, these "subtypes" exist on Windows (Basically, where they come from and whom they affect)Echo
I need this variables for my application, per-user or machine, doesn't matterDonegan
Well it matters, if you install the application in program files you should set it machine wide. If you install in the users profile it should be per-user...Echo
E
1

How can I create or change an environment variable

Note: Changing %path% this way is unsafe and can corrupt the entry if it is longer than the NSIS string length!

Echo answered 16/10, 2012 at 12:22 Comment(2)
Is there some "safe" way? Thanks!Donegan
You would have to allocate memory with the system plugin and call string and registry functions directly. I don't think there exists sample code doing it that way...Echo
I
1

You can create a windows batch file, pack it with the setup just like other files, on install unpack it to the plugins directory and execute it:

File "/oname=$PluginsDir\appendvar.bat" "PathToScriptDir\appendvar.bat"

nsExec::ExecToLog '"$SYSDIR\cmd.exe" /C "$PluginsDir\appendvar.bat" -g -all'
Pop $R0 ; last error

Delete "$PluginsDir\appendvar.bat"

The appendvar.bat script (some kind of universal implementation for global and local append):

@echo off

rem Drop last error level
cd .

rem Create local variable's stack
setlocal

set "?~nx0=%~nx0"

rem script flags
rem set variable in global registry for a current user
set __FLAG_SET_GLOBAL_REGISTRY=0
rem Set variable in global registry for all users.
rem Has no meaning if global flag has not used.
set __FLAG_SET_GLOBAL_REGISTRY_ALL_USERS=0
rem If setting global variable, then do include changes for a local cmd.exe process environment (by default, it is excluded)
rem Has no meaning if global flag has not used.
set __FLAG_SET_LOCAL=0
rem Force append even if exist.
set __FLAG_FORCE=0

:FLAGS_LOOP

rem flags always at first
set "__FLAG=%~1"

if not "%__FLAG%" == "" ^
if not "%__FLAG:~0,1%" == "-" set "__FLAG="

if not "%__FLAG%" == "" (
  if "%__FLAG%" == "-g" (
    set __FLAG_SET_GLOBAL_REGISTRY=1
    shift
  ) else if "%__FLAG%" == "-all" (
    if %__FLAG_SET_GLOBAL_REGISTRY% NEQ 0 set __FLAG_SET_GLOBAL_REGISTRY_ALL_USERS=1
    shift
  ) else if "%__FLAG%" == "-l" (
    set __FLAG_SET_LOCAL=1
    shift
  ) else if "%__FLAG%" == "-f" (
    set __FLAG_FORCE=1
    shift
  ) else (
    echo.%?~nx0%: error: invalid flag: %__FLAG%
    exit /b -255
  ) >&2

  rem read until no flags
  goto FLAGS_LOOP
)

if "%~1" == "" (
  echo.%?~nx0%: error: variable name is not set.
  exit /b 1
)

set "__SEPARATOR="
if not "%~3" == "" set "__SEPARATOR=%~3"
if "%__SEPARATOR%" == "" set "__SEPARATOR=;"
set "__SEPARATOR=%__SEPARATOR:~0,1%"

set "__NEW_VALUE=%~2"

rem remove trailing separator character
if not "%__NEW_VALUE%" == "" (
  if "%__SEPARATOR%" == "%__NEW_VALUE:~-1%" (
    set "__NEW_VALUE=%__NEW_VALUE:~0,-1%"
  )
)

rem remove trailing "\" character
if not "%__NEW_VALUE%" == "" (
  if "\" == "%__NEW_VALUE:~-1%" (
    set "__NEW_VALUE=%__NEW_VALUE:~0,-1%"
  )
)

if "%__NEW_VALUE%" == "" (
  if "%~2" == "" exit /b 0
  rem the variable value is a separator character only
  exit /b 2
)

rem set local at least
if %__FLAG_SET_GLOBAL_REGISTRY%%__FLAG_SET_LOCAL% EQU 0 set __FLAG_SET_LOCAL=1
if %__FLAG_SET_GLOBAL_REGISTRY% EQU 0 goto SET_GLOBAL_END

rem global setup
set "__VAR_VALUE="

if %__FLAG_SET_GLOBAL_REGISTRY_ALL_USERS% NEQ 0 (
  set __FLAG_SET_GLOBAL_REGISTRY_WMIC_WHERE_EXP=where "Name='Path' and UserName='<SYSTEM>'"
) else (
  set __FLAG_SET_GLOBAL_REGISTRY_WMIC_WHERE_EXP=where "Name='Path' and UserName!='<SYSTEM>'"
)

for /F "usebackq eol= tokens=1,* delims==" %%i in (`wmic environment %__FLAG_SET_GLOBAL_REGISTRY_WMIC_WHERE_EXP% get VariableValue /VALUE 2^>NUL`) do if "%%i" == "VariableValue" set "__VAR_VALUE=%%j"

if not "%__VAR_VALUE%" == "" (
  if "%__SEPARATOR%" == "%__VAR_VALUE:~-1%" (
    set "__VAR_VALUE=%__VAR_VALUE:~0,-1%"
  )
)

rem check on existance
if %__FLAG_FORCE% NEQ 0 goto SET_GLOBAL_IMPL
if "%__VAR_VALUE%" == "" goto SET_GLOBAL_IMPL

set "__VAR_VALUE_TMP=%__SEPARATOR%%__VAR_VALUE%%__SEPARATOR%"

call set "__VAR_VALUE_TMP_EXCLUDED=%%__VAR_VALUE_TMP:%__SEPARATOR%%__NEW_VALUE%%__SEPARATOR%=%%"

if /i not "%__VAR_VALUE_TMP_EXCLUDED%" == "%__VAR_VALUE_TMP%" goto SET_GLOBAL_END

:SET_GLOBAL_IMPL
if not "%__VAR_VALUE%" == "" (
  wmic environment %__FLAG_SET_GLOBAL_REGISTRY_WMIC_WHERE_EXP% set VariableValue="%__VAR_VALUE%%__SEPARATOR%%__NEW_VALUE%"
) else (
  wmic environment %__FLAG_SET_GLOBAL_REGISTRY_WMIC_WHERE_EXP% set VariableValue="%__NEW_VALUE%"
)

:SET_GLOBAL_END
if %__FLAG_SET_LOCAL% EQU 0 exit /b

rem local setup
call set "__VAR_VALUE=%%%~1%%"

if not "%__VAR_VALUE%" == "" (
  if "%__SEPARATOR%" == "%__VAR_VALUE:~-1%" (
    set "__VAR_VALUE=%__VAR_VALUE:~0,-1%"
  )
)

rem check on existance
if %__FLAG_FORCE% NEQ 0 goto SET_LOCAL_IMPL
if "%__VAR_VALUE%" == "" goto SET_LOCAL_IMPL

set "__VAR_VALUE_TMP=%__SEPARATOR%%__VAR_VALUE%%__SEPARATOR%"

call set "__VAR_VALUE_TMP_EXCLUDED=%%__VAR_VALUE_TMP:%__SEPARATOR%%__NEW_VALUE%%__SEPARATOR%=%%"

if /i not "%__VAR_VALUE_TMP_EXCLUDED%" == "%__VAR_VALUE_TMP%" goto SET_LOCAL_END

:SET_LOCAL_IMPL
if not "%__VAR_VALUE%" == "" (
  endlocal
  set "%~1=%__VAR_VALUE%%__SEPARATOR%%__NEW_VALUE%"
) else (
  endlocal
  set "%~1=%__NEW_VALUE%"
)

:SET_LOCAL_END

exit /b 0

You can replace

%__VAR_VALUE%%__SEPARATOR%%__NEW_VALUE%

to

%__NEW_VALUE%%__SEPARATOR%%__VAR_VALUE%

If want to prepend a variable value.

Note: The script has issues:

  • values compares with ignore case
  • can update variables longer than 1024 characters (tested), but not longer than 4096 characters i think (not tested)
  • if -g and -all flags is used, then the cmd.exe process must be run under the administrator privileges.
Insufflate answered 14/3, 2017 at 22:48 Comment(0)
I
1

UPDATE: The latest version of the RegAddPathToVar function is here: https://sf.net/p/nsisplus (full test example: https://sf.net/p/nsisplus/NsisSetupLib/HEAD/tree/trunk/tests/test_RegAddRemovePathGUI/main.nsi)

Here is full and direct implementation example for the NSIS 3.0.

Consist of 3 files.

build.bat - build script file.

@echo off

set "MAKENSIS_EXE=makensis.exe"

"%MAKENSIS_EXE%" /V4 "/Obuild.log" "/XOutFile '%~dp0test.exe'" "%~dp0main.nsi"

echo.Return code: %ERRORLEVEL%

pause

Edit the MAKENSIS_EXE variable to there the makensis executable is on your system.

stack.nsi - helper functions file.

!define PushStack11 "!insertmacro PushStack11"
!macro PushStack11 var0 var1 var2 var3 var4 var5 var6 var7 var8 var9 var10
Push `${var0}`
Push `${var1}`
Push `${var2}`
Push `${var3}`
Push `${var4}`
Push `${var5}`
Push `${var6}`
Push `${var7}`
Push `${var8}`
Push `${var9}`
Push `${var10}`
!macroend

!define ExchStack4 "!insertmacro ExchStack4"
!macro ExchStack4 var0 var1 var2 var3
Exch `${var3}`
Exch 1
Exch `${var2}`
Exch 1
Exch 2
Exch `${var1}`
Exch 2
Exch 3
Exch `${var0}`
Exch 3
!macroend

!define PopStack15 "!insertmacro PopStack15"
!macro PopStack15 var0 var1 var2 var3 var4 var5 var6 var7 var8 var9 var10 var11 var12 var13 var14
Pop `${var14}`
Pop `${var13}`
Pop `${var12}`
Pop `${var11}`
Pop `${var10}`
Pop `${var9}`
Pop `${var8}`
Pop `${var7}`
Pop `${var6}`
Pop `${var5}`
Pop `${var4}`
Pop `${var3}`
Pop `${var2}`
Pop `${var1}`
Pop `${var0}`
!macroend

main.nsi - full NSIS implementation example.

!include "nsDialogs.nsh"
!include "WinCore.nsh"
!include "LogicLib.nsh"
!include "stack.nsi"

RequestExecutionLevel admin ; for all users

Page Custom Show Leave

Var /GLOBAL DialogID
Var /GLOBAL EditID
Var /GLOBAL Edit
Var /GLOBAL ButtonAppendID

!define GotoIf "!insertmacro GotoIf"
!macro GotoIf label exp
${If} ${exp}
  Goto `${label}`
${EndIf}
!macroend

!define RegGetKeyMap "!insertmacro RegGetKeyMap"
!macro RegGetKeyMap var value
  ${Switch} ${value}
    ${Case} "HKCR"
      StrCpy ${var} ${HKEY_CLASSES_ROOT}
    ${Break}
    ${Case} "HKCU"
      StrCpy ${var} ${HKEY_CURRENT_USER}
    ${Break}
    ${Case} "HKLM"
      StrCpy ${var} ${HKEY_LOCAL_MACHINE}
    ${Break}
    ${Case} "HKU"
      StrCpy ${var} ${HKEY_USERS}
    ${Break}
    ${Case} "HKPD"
      StrCpy ${var} ${HKEY_PERFORMANCE_DATA}
    ${Break}
    ${Case} "HKDD"
      StrCpy ${var} ${HKEY_DYN_DATA}
    ${Break}
    ${Case} "HKCC"
      StrCpy ${var} ${HKEY_CURRENT_CONFIG}
    ${Break}
    ${Case} "HKEY_CLASSES_ROOT"
      StrCpy ${var} ${HKEY_CLASSES_ROOT}
    ${Break}
    ${Case} "HKEY_CURRENT_USER"
      StrCpy ${var} ${HKEY_CURRENT_USER}
    ${Break}
    ${Case} "HKEY_LOCAL_MACHINE"
      StrCpy ${var} ${HKEY_LOCAL_MACHINE}
    ${Break}
    ${Case} "HKEY_USERS"
      StrCpy ${var} ${HKEY_USERS}
    ${Break}
    ${Case} "HKEY_PERFORMANCE_DATA"
      StrCpy ${var} ${HKEY_PERFORMANCE_DATA}
    ${Break}
    ${Case} "HKEY_DYN_DATA"
      StrCpy ${var} ${HKEY_DYN_DATA}
    ${Break}
    ${Case} "HKEY_CURRENT_CONFIG"
      StrCpy ${var} ${HKEY_CURRENT_CONFIG}
    ${Break}
    ${Default}
      StrCpy ${var} ${HKEY_CURRENT_USER}
    ${Break}
  ${EndSwitch}
!macroend

; Usage:
; All users:
;   ${Push} "<path>"
;   ${Push} "HKLM"
;   ${Push} "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
;   ${Push} "<env_var>"
;   Call RegAddPathToVar
; Current user only:
;   ${Push} "<path>"
;   ${Push} "HKCU"
;   ${Push} "Environment"
;   ${Push} "<env_var>"
;   Call RegAddPathToVar
!macro Func_RegAddPathToVar un
!ifndef ${un}RegAddPathToVar_INCLUDED
!define ${un}RegAddPathToVar_INCLUDED
Function ${un}RegAddPathToVar
  ${ExchStack4} $R0 $R1 $R2 $R3

  ${PushStack11} $R4 $R5 $R6 $R7 $R8 $R9 $0 $1 $2 $8 $9

  ; WARNING:
  ;   NSIS ReadRegStr returns empty string on string overflow, so native calls are used here:
  ;   1. To check actual length of <env_var>.
  ;   2. To process the PATH variable of any length long.

  ; The IDEAL algorithm for any length long PATH variable, where each subpath is not longer than ${NSIS_MAX_STRLEN}-${NSIS_CHAR_SIZE} bytes:
  ;   1. Init current string list if does not have any before or take as current has created after the previous algorithm run.
  ;   2. Read string of ${NSIS_MAX_STRLEN}-${NSIS_CHAR_SIZE} bytes length into the array of ${NSIS_MAX_STRLEN} bytes length from the input address, add NSIS_CHAR_SIZE nulls at the end.
  ;   3. Go to 20 if empty or nothing else except the ; characters in the array.
  ;   4. Truncate all in the array after the last ; character, where the ; character has found not under " character quoted string (see description in the 6).
  ;   5. Split strings in the array by the ; character if it has found not under " character quoted string into the list.
  ;   6. Move the last string from the list into the next repeat cycle list if it begins by the " character but not ends by the same character (not completely fitted into the limited to ${NSIS_MAX_STRLEN} bytes window).
  ;   7. Unquote all strings in the list and create the second list with flags marked where the quotes has removed.
  ;   8. Search for "$R0" or "$R0\" in the list, if found then raise a flag and leave the algorithm.
  ;   9. Move ${NSIS_MAX_STRLEN} byte window by the array current string length long multiple to NSIS_CHAR_SIZE value along the input address.
  ;  10. Repeat the algorithm.
  ;  20. Append path to the list.
  ;  21. Restore quotes for those strings in the first list what been quoted before by the second list.
  ;  22. Join first list by the separator into one string.

  ; The REAL algorithm for any length long PATH variable, where each subpath is not longer than ${NSIS_MAX_STRLEN}-${NSIS_CHAR_SIZE} bytes:
  ;   1. Read string from registry into dynamic buffer enough to store more characters: length of being searched string + length of separator + length of string to search + length of null character.
  ;   2. Copy string from the buffer to the second dynamic buffer enough to store more characters: length of separator + length of being searched string + length of separator + length of null character.
  ;   3. Prepend and append separator character to second buffer.
  ;   4. Try to find multiple instances of the string to search in the second buffer through the shlwapi::StrStrI, where search instances are:
  ;      `<Separator><StringToSearch><Separator>'
  ;      `<Separator><StringToSearch>\<Separator>'
  ;   5. If found any instance then leave the algorithm.
  ;   6. Append separator character to the first buffer if it does not ending by it.
  ;   7. Append the string to search to the first buffer.

  ; handles and pointers init
  StrCpy $R7 0
  StrCpy $R9 0
  StrCpy $0 0
  StrCpy $1 0
  StrCpy $2 0

  ; keys map
  ${RegGetKeyMap} $R8 $R1

  System::Call "advapi32::RegOpenKey(i R8, t R2, *i.R6) i.R4"
  ${If} $R4 <> 0
    DetailPrint "RegAddPathToVar: advapi32::RegOpenKey error: code=$R4 hive=$\"$R8$\" key=$\"$R2$\""
    MessageBox MB_OK "RegAddPathToVar: advapi32::RegOpenKey error: code=$R4 hive=$\"$R8$\" key=$\"$R2$\"" /SD IDOK
    Goto done
  ${EndIf}

  System::Call "advapi32::RegQueryValueEx(i R6, t R3, i 0, *i .r9, p 0, *i 0 R7) i.R4"
  ${If} $R4 <> 0
    DetailPrint "RegAddPathToVar: advapi32::RegQueryValueEx (1) is failed, unexpected error code: code=$R4 length=$\"$R7$\""
    MessageBox MB_OK "RegAddPathToVar: advapi32::RegQueryValueEx (1) is failed, unexpected error code: code=$R4 length=$\"$R7$\"" /SD IDOK
    Goto done
  ${EndIf}

  ; remove trailing "\" character from the string to search
  StrCpy $R5 $R0 "" -1
  ${If} $R5 == "\"
    StrCpy $R0 $R0 -1
  ${EndIf}

  StrLen $R8 $R0
  ; first buffer: length of being searched string + length of separator + length of string to search + length of null character
  IntOp $R5 $R8 + 1 ; ";"
  IntOp $R5 $R5 * ${NSIS_CHAR_SIZE}
  IntOp $R5 $R5 + $R7 ; already in bytes including null character

  ; allocate first dynamic buffer
  System::Alloc $R5
  Pop $0
  ${If} $0 = 0
    DetailPrint "RegAddPathToVar: System::Alloc (1) is failed: size=$R5"
    MessageBox MB_OK "RegAddPathToVar: System::Alloc (1) is failed: size=$R5" /SD IDOK
    Goto done
  ${EndIf}

  System::Call "advapi32::RegQueryValueEx(i R6, t R3, i 0, i 0, p r0, *i R5 R7) i.R4"
  ${If} $R4 <> 0
    DetailPrint "RegAddPathToVar: advapi32::RegQueryValueEx (2) is failed, unexpected error: code=$R4 length=$\"$R7$\""
    MessageBox MB_OK "RegAddPathToVar: advapi32::RegQueryValueEx (2) is failed, unexpected error: code=$R4 length=$\"$R7$\"" /SD IDOK
    Goto done
  ${EndIf}

  ; strip separator characters from the first buffer end
  ${If} $R7 > ${NSIS_CHAR_SIZE}
    ; excluding null character
    IntOp $R5 $R7 - ${NSIS_CHAR_SIZE}
    IntOp $R5 $R5 - ${NSIS_CHAR_SIZE}
    IntOp $R9 $0 + $R5
strip_loop1:
    System::Call "*$R9(&t1 .r8)"
    ${If} $8 == ";"
      System::Call "*$R9(&t1 '')" ; null character
      IntOp $R7 $R7 - ${NSIS_CHAR_SIZE}
      ${If} $R9 >= ${NSIS_CHAR_SIZE}
        IntOp $R9 $R9 - ${NSIS_CHAR_SIZE}
        Goto strip_loop1
      ${EndIf}
    ${EndIf}
  ${EndIf}

  ; second buffer: length of separator + length of being searched string + length of separator + length of null character
  IntOp $R5 2 * ${NSIS_CHAR_SIZE} ; 2 x ";"
  IntOp $R5 $R5 + $R7 ; already in bytes including null character

  ; allocate second dynamic buffer
  System::Alloc $R5
  Pop $1
  ${If} $1 = 0
    DetailPrint "RegAddPathToVar: System::Alloc (2) is failed: size=$R5"
    MessageBox MB_OK "RegAddPathToVar: System::Alloc (2) is failed: size=$R5" /SD IDOK
    Goto done
  ${EndIf}

  System::Call "*$1(&t1 ';')"

  IntOp $R9 $1 + ${NSIS_CHAR_SIZE}
  System::Call "kernel32::lstrcpyn(p R9, p r0, i R7) p.R4"
  ${If} $R4 = 0
    DetailPrint "RegAddPathToVar: kernel32::lstrcpyn (1) is failed"
    MessageBox MB_OK "RegAddPathToVar: kernel32::lstrcpyn (1) is failed" /SD IDOK
    Goto done
  ${EndIf}

  IntOp $R9 $R9 + $R7
  IntOp $R9 $R9 - ${NSIS_CHAR_SIZE} ; exclude last null character
  System::Call "*$R9(&t1 ';')"
  IntOp $R9 $R9 + ${NSIS_CHAR_SIZE}
  System::Call "*$R9(&t1 '')" ; null character

  ; buffer for the string to search
  IntOp $R5 0 + 4 ; 2 x ";" + "\" + length of null character
  IntOp $R5 $R5 + $R8 ; excluding null character
  IntOp $R5 $R5 * ${NSIS_CHAR_SIZE}

  System::Alloc $R5
  Pop $2
  ${If} $2 = 0
    DetailPrint "RegAddPathToVar: System::Alloc (3) is failed: size=$R5"
    MessageBox MB_OK "RegAddPathToVar: System::Alloc (3) is failed: size=$R5" /SD IDOK
    Goto done
  ${EndIf}

  ; convert R8 (length of R0) to bytes
  IntOp $R8 $R8 * ${NSIS_CHAR_SIZE}

  ; `<Separator><StringToSearch><Separator>'
  System::Call "*$2(&t1 ';')"

  IntOp $R9 $2 + ${NSIS_CHAR_SIZE}
  System::Call "kernel32::lstrcpy(p R9, t R0) p.R4"
  ${If} $R4 = 0
    DetailPrint "RegAddPathToVar: kernel32::lstrcpy (2) is failed"
    MessageBox MB_OK "RegAddPathToVar: kernel32::lstrcpy (2) is failed" /SD IDOK
    Goto done
  ${EndIf}

  IntOp $R9 $R9 + $R8 ; length does not include the last null character
  System::Call "*$R9(&t1 ';')"
  IntOp $R9 $R9 + ${NSIS_CHAR_SIZE}
  System::Call "*$R9(&t1 '')" ; null character

  System::Call "shlwapi::StrStrI(p r1, p r2) p.R4"
  ${GotoIf} done "$R4 <> 0"

  ; `<Separator><StringToSearch>\<Separator>'
  System::Call "*$2(&t1 ';')"

  IntOp $R9 $2 + ${NSIS_CHAR_SIZE}
  IntOp $R9 $R9 + $R8
  System::Call "*$R9(&t1 '\')"
  IntOp $R9 $R9 + ${NSIS_CHAR_SIZE}
  System::Call "*$R9(&t1 ';')"
  IntOp $R9 $R9 + ${NSIS_CHAR_SIZE}
  System::Call "*$R9(&t1 '')" ; null character

  System::Call "shlwapi::StrStrI(p r1, p r2) p.R4"
  ${GotoIf} done "$R4 <> 0"

  ; append to the first buffer
  IntOp $R9 0 + $0
  ${If} $R7 > ${NSIS_CHAR_SIZE}
    IntOp $R9 $R9 + $R7
    IntOp $R9 $R9 - ${NSIS_CHAR_SIZE} ; exclude last null character
    System::Call "*$R9(&t1 ';')"
    IntOp $R9 $R9 + ${NSIS_CHAR_SIZE}
  ${EndIf}

  System::Call "kernel32::lstrcpy(p R9, t R0) p.R4"
  ${If} $R4 = 0
    DetailPrint "RegAddPathToVar: kernel32::lstrcpy (3) is failed"
    MessageBox MB_OK "RegAddPathToVar: kernel32::lstrcpy (3) is failed" /SD IDOK
    Goto done
  ${EndIf}

  IntOp $R9 $R9 + $R8 ; length does not include the last null character
  System::Call "*$R9(&t1 '')" ; null character

  IntOp $R9 $R9 + ${NSIS_CHAR_SIZE}
  IntOp $R5 $R9 - $0

  System::Call "advapi32::RegSetValueEx(i R6, t R3, i 0, i r9, p r0, i R5) i.R4"
  ${If} $R4 <> 0
    DetailPrint "RegAddPathToVar: advapi32::RegSetValueEx (1) is failed"
    MessageBox MB_OK "RegAddPathToVar: advapi32::RegSetValueEx (1) is failed" /SD IDOK
    Goto done
  ${EndIf}

  ; broadcast global event
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000

done:
  System::Call "advapi32::RegCloseKey(i $R6)"

  ${If} $0 <> 0
    System::Free $0
  ${EndIf}
  ${If} $1 <> 0
    System::Free $1
  ${EndIf}
  ${If} $2 <> 0
    System::Free $2
  ${EndIf}

  ${PopStack15} $R0 $R1 $R2 $R3 $R4 $R5 $R6 $R7 $R8 $R9 $0 $1 $2 $8 $9
FunctionEnd
!endif
!macroend

!define Call_RegAddPathToVar "!insertmacro Call_RegAddPathToVar"
!macro Call_RegAddPathToVar prefix path hkey hkey_path env_var
Push `${path}`
Push `${hkey}`
Push `${hkey_path}`
Push `${env_var}`
Call ${prefix}RegAddPathToVar
!macroend

!define RegAddPathToVar "!insertmacro RegAddPathToVar"
!macro RegAddPathToVar
!insertmacro Func_RegAddPathToVar ""
!undef RegAddPathToVar
!define RegAddPathToVar "${Call_RegAddPathToVar} ''"
!macroend

!define un.RegAddPathToVar "!insertmacro un.RegAddPathToVar"
!macro un.RegAddPathToVar
!insertmacro Func_RegAddPathToVar "un."
!undef un.RegAddPathToVar
!define un.RegAddPathToVar "${Call_RegAddPathToVar} 'un.'"
!macroend

; include for install only
${RegAddPathToVar}

Function Show
  nsDialogs::Create 1018
  Pop $DialogID

  ${NSD_CreateText} 0 16u 80% 14u "C:\MyPath\bin"
  Pop $EditID

  ${NSD_OnChange} $EditID WndProc

  ${NSD_CreateButton} 80% 16u 20% 14u "Append"
  Pop $ButtonAppendID

  ${NSD_OnClick} $ButtonAppendID WndProc

  StrCpy $R0 -1
  Call Update

  nsDialogs::Show
FunctionEnd

Function Leave
FunctionEnd

Function WndProc
  System::Store SR0
  Call Update
  System::Store L
FunctionEnd

Function Update
  ; read values
  ${If} $R0 = $EditID
  ${OrIf} $R0 = -1
    ${NSD_GetText} $EditID $Edit
  ${EndIf}
  ${If} $R0 = $ButtonAppendID
    ${If} $Edit != ""
      #${RegAddPathToVar} "$Edit" HKCU "Environment" PATH ; for current user
      ${RegAddPathToVar} "$Edit" HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" PATH ; for all users
    ${EndIf}
  ${EndIf}
FunctionEnd

Section -Hidden
SectionEnd
Insufflate answered 20/3, 2017 at 16:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.