livetrace/installer/EnvVarUpdate.nsh
2026-09-09 17:23:01 +03:00

143 lines
3.3 KiB
NSIS

; EnvVarUpdate.nsh
; Adds/removes a value from a Windows environment variable (PATH-style, semicolon-delimited)
; Usage:
; ${EnvVarUpdate} $0 "PATH" "A" "HKLM" "$INSTDIR" ; append
; ${UnEnvVarUpdate} $0 "PATH" "HKLM" "$INSTDIR" ; remove
!ifndef ENVVARUPDATE_NSH
!define ENVVARUPDATE_NSH
!include "LogicLib.nsh"
!include "WinMessages.nsh"
; --------------------------------------------------------------------------
; Macro: _EnvVarUpdate
; Action: "A" = Append, "P" = Prepend, "R" = Remove
; --------------------------------------------------------------------------
!macro _EnvVarUpdate OUTVAR EnvVarName Action RegLoc PathString
Push $0
Push $1
Push $2
Push $3
Push $4
Push $5
; Read current value
ReadRegStr $1 ${RegLoc} \
"SYSTEM\CurrentControlSet\Control\Session Manager\Environment" \
"${EnvVarName}"
; Strip trailing semicolon
StrCpy $5 $1 1 -1
${If} $5 == ";"
StrCpy $1 $1 -1
${EndIf}
; Check if PathString already exists
Push "${PathString}"
Push $1
Call _EnvVarUpdateStrStr
Pop $2 ; $2 = position, or "" if not found
${If} "${Action}" == "A"
${If} $2 == ""
${If} $1 == ""
StrCpy $3 "${PathString}"
${Else}
StrCpy $3 "$1;${PathString}"
${EndIf}
WriteRegExpandStr ${RegLoc} \
"SYSTEM\CurrentControlSet\Control\Session Manager\Environment" \
"${EnvVarName}" "$3"
${EndIf}
${ElseIf} "${Action}" == "P"
${If} $2 == ""
${If} $1 == ""
StrCpy $3 "${PathString}"
${Else}
StrCpy $3 "${PathString};$1"
${EndIf}
WriteRegExpandStr ${RegLoc} \
"SYSTEM\CurrentControlSet\Control\Session Manager\Environment" \
"${EnvVarName}" "$3"
${EndIf}
${ElseIf} "${Action}" == "R"
${If} $2 != ""
; Remove entry
StrLen $4 "${PathString}"
StrCpy $0 $1 $2 ; everything before the match
IntOp $4 $2 + $4 ; position after the match
StrCpy $5 $1 "" $4 ; everything after the match
; Strip leading/trailing semicolons from join point
StrCpy $4 $5 1
${If} $4 == ";"
StrCpy $5 $5 "" 1
${EndIf}
StrCpy $4 $0 1 -1
${If} $4 == ";"
StrCpy $0 $0 -1
${EndIf}
${If} $0 == ""
StrCpy $3 $5
${ElseIf} $5 == ""
StrCpy $3 $0
${Else}
StrCpy $3 "$0;$5"
${EndIf}
WriteRegExpandStr ${RegLoc} \
"SYSTEM\CurrentControlSet\Control\Session Manager\Environment" \
"${EnvVarName}" "$3"
${EndIf}
${EndIf}
; Broadcast change to all windows
SendMessage ${HWND_BROADCAST} ${WM_SETTINGCHANGE} 0 "STR:Environment" /TIMEOUT=5000
Pop $5
Pop $4
Pop $3
Pop $2
Pop $1
Pop $0
!macroend
; Helper: find substring position (returns "" if not found)
Function _EnvVarUpdateStrStr
Exch $R0 ; haystack
Exch
Exch $R1 ; needle
Push $R2
Push $R3
Push $R4
Push $R5
StrLen $R3 $R1
StrLen $R4 $R0
IntOp $R4 $R4 - $R3
StrCpy $R2 0
loop:
IntCmp $R2 $R4 done done
StrCpy $R5 $R0 $R3 $R2
StrCmp $R5 $R1 found
IntOp $R2 $R2 + 1
Goto loop
found:
StrCpy $R0 $R2
Goto end
done:
StrCpy $R0 ""
end:
Pop $R5
Pop $R4
Pop $R3
Pop $R2
Pop $R1
Exch $R0
FunctionEnd
!define EnvVarUpdate `!insertmacro _EnvVarUpdate`
!define UnEnvVarUpdate `!insertmacro _EnvVarUpdate "" "${__LINE__}" "R"`
!endif ; ENVVARUPDATE_NSH