; 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