| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 | /** *  EnvVarUpdate.nsh *    : Environmental Variables: append, prepend, and remove entries * *     WARNING: If you use StrFunc.nsh header then include it before this file *              with all required definitions. This is to avoid conflicts * *  Usage: *    ${EnvVarUpdate} "ResultVar" "EnvVarName" "Action" "RegLoc" "PathString" * *  Credits: *  Version 1.0  *  * Cal Turney (turnec2) *  * Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this *    function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, *    WriteEnvStr, and un.DeleteEnvStr *  * Diego Pedroso (deguix) for StrTok *  * Kevin English (kenglish_hi) for StrContains *  * Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry   *    (dandaman32) for StrReplace * *  Version 1.1 (compatibility with StrFunc.nsh) *  * techtonik * *  http://nsis.sourceforge.net/Environmental_Variables:_append%2C_prepend%2C_and_remove_entries * */!ifndef ENVVARUPDATE_FUNCTION!define ENVVARUPDATE_FUNCTION!verbose push!verbose 3!include "LogicLib.nsh"!include "WinMessages.NSH"!include "StrFunc.nsh"; ---- Fix for conflict if StrFunc.nsh is already includes in main file -----------------------!macro _IncludeStrFunction StrFuncName  !ifndef ${StrFuncName}_INCLUDED    ${${StrFuncName}}  !endif  !ifndef Un${StrFuncName}_INCLUDED    ${Un${StrFuncName}}  !endif  !define un.${StrFuncName} "${Un${StrFuncName}}"!macroend!insertmacro _IncludeStrFunction StrTok!insertmacro _IncludeStrFunction StrStr!insertmacro _IncludeStrFunction StrRep; ---------------------------------- Macro Definitions ----------------------------------------!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString  Push "${EnvVarName}"  Push "${Action}"  Push "${RegLoc}"  Push "${PathString}"    Call EnvVarUpdate  Pop "${ResultVar}"!macroend!define EnvVarUpdate '!insertmacro "_EnvVarUpdateConstructor"' !macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString  Push "${EnvVarName}"  Push "${Action}"  Push "${RegLoc}"  Push "${PathString}"    Call un.EnvVarUpdate  Pop "${ResultVar}"!macroend!define un.EnvVarUpdate '!insertmacro "_unEnvVarUpdateConstructor"'; ---------------------------------- Macro Definitions end------------------------------------- ;----------------------------------- EnvVarUpdate start----------------------------------------!define hklm_all_users     'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'!define hkcu_current_user  'HKCU "Environment"' !macro EnvVarUpdate UN Function ${UN}EnvVarUpdate   Push $0  Exch 4  Exch $1  Exch 3  Exch $2  Exch 2  Exch $3  Exch  Exch $4  Push $5  Push $6  Push $7  Push $8  Push $9  Push $R0   /* After this point:  -------------------------     $0 = ResultVar     (returned)     $1 = EnvVarName    (input)     $2 = Action        (input)     $3 = RegLoc        (input)     $4 = PathString    (input)     $5 = Orig EnvVar   (read from registry)     $6 = Len of $0     (temp)     $7 = tempstr1      (temp)     $8 = Entry counter (temp)     $9 = tempstr2      (temp)     $R0 = tempChar     (temp)  */   ; Step 1:  Read contents of EnvVarName from RegLoc  ;  ; Check for empty EnvVarName  ${If} $1 == ""    SetErrors    DetailPrint "ERROR: EnvVarName is blank"    Goto EnvVarUpdate_Restore_Vars  ${EndIf}   ; Check for valid Action  ${If}    $2 != "A"  ${AndIf} $2 != "P"  ${AndIf} $2 != "R"    SetErrors    DetailPrint "ERROR: Invalid Action - must be A, P, or R"    Goto EnvVarUpdate_Restore_Vars  ${EndIf}   ${If} $3 == HKLM    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5  ${ElseIf} $3 == HKCU    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5  ${Else}    SetErrors    DetailPrint 'ERROR: Action is [$3] but must be "HKLM" or HKCU"'    Goto EnvVarUpdate_Restore_Vars  ${EndIf}   ; Check for empty PathString  ${If} $4 == ""    SetErrors    DetailPrint "ERROR: PathString is blank"    Goto EnvVarUpdate_Restore_Vars  ${EndIf}   ; Make sure we've got some work to do  ${If} $5 == ""  ${AndIf} $2 == "R"    SetErrors    DetailPrint "$1 is empty - Nothing to remove"    Goto EnvVarUpdate_Restore_Vars  ${EndIf}   ; Step 2: Scrub EnvVar  ;  StrCpy $0 $5                             ; Copy the contents to $0  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or  ; after the last one are not removed here but instead in Step 3)  ${If} $0 != ""                           ; If EnvVar is not empty ...    ${Do}      ${${UN}StrStr} $7 $0 " ;"      ${If} $7 == ""        ${ExitDo}      ${EndIf}      ${${UN}StrRep} $0  $0 " ;" ";"         ; Remove '<space>;'    ${Loop}    ${Do}      ${${UN}StrStr} $7 $0 "; "      ${If} $7 == ""        ${ExitDo}      ${EndIf}      ${${UN}StrRep} $0  $0 "; " ";"         ; Remove ';<space>'    ${Loop}    ${Do}      ${${UN}StrStr} $7 $0 ";;"       ${If} $7 == ""        ${ExitDo}      ${EndIf}      ${${UN}StrRep} $0  $0 ";;" ";"    ${Loop}     ; Remove a leading or trailing semicolon from EnvVar    StrCpy  $7  $0 1 0    ${If} $7 == ";"      StrCpy $0  $0 "" 1                   ; Change ';<EnvVar>' to '<EnvVar>'    ${EndIf}    StrLen $6 $0    IntOp $6 $6 - 1    StrCpy $7  $0 1 $6    ${If} $7 == ";"     StrCpy $0  $0 $6                      ; Change ';<EnvVar>' to '<EnvVar>'    ${EndIf}    ; DetailPrint "Scrubbed $1: [$0]"      ; Uncomment to debug  ${EndIf}   /* Step 3. Remove all instances of the target path/string (even if "A" or "P")     $6 = bool flag (1 = found and removed PathString)     $7 = a string (e.g. path) delimited by semicolon(s)     $8 = entry counter starting at 0     $9 = copy of $0     $R0 = tempChar      */   ${If} $5 != ""                           ; If EnvVar is not empty ...    StrCpy $9 $0    StrCpy $0 ""    StrCpy $8 0    StrCpy $6 0     ${Do}      ${${UN}StrTok} $7 $9 ";" $8 "0"      ; $7 = next entry, $8 = entry counter       ${If} $7 == ""                       ; If we've run out of entries,        ${ExitDo}                          ;    were done      ${EndIf}                             ;       ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)      ${Do}        StrCpy $R0  $7 1        ${If} $R0 != " "          ${ExitDo}        ${EndIf}        StrCpy $7   $7 "" 1                ;  Remove leading space      ${Loop}      ${Do}        StrCpy $R0  $7 1 -1        ${If} $R0 != " "          ${ExitDo}        ${EndIf}        StrCpy $7   $7 -1                  ;  Remove trailing space      ${Loop}      ${If} $7 == $4                       ; If string matches, remove it by not appending it        StrCpy $6 1                        ; Set 'found' flag      ${ElseIf} $7 != $4                   ; If string does NOT match      ${AndIf}  $0 == ""                   ;    and the 1st string being added to $0,        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon      ${ElseIf} $7 != $4                   ; If string does NOT match      ${AndIf}  $0 != ""                   ;    and this is NOT the 1st string to be added to $0,        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon      ${EndIf}                             ;       IntOp $8 $8 + 1                      ; Bump counter    ${Loop}                                ; Check for duplicates until we run out of paths  ${EndIf}   ; Step 4:  Perform the requested Action  ;  ${If} $2 != "R"                          ; If Append or Prepend    ${If} $6 == 1                          ; And if we found the target      DetailPrint "Target is already present in $1. It will be removed and"    ${EndIf}    ${If} $0 == ""                         ; If EnvVar is (now) empty      StrCpy $0 $4                         ;   just copy PathString to EnvVar      ${If} $6 == 0                        ; If found flag is either 0      ${OrIf} $6 == ""                     ; or blank (if EnvVarName is empty)        DetailPrint "$1 was empty and has been updated with the target"      ${EndIf}    ${ElseIf} $2 == "A"                    ;  If Append (and EnvVar is not empty),      StrCpy $0 $0;$4                      ;     append PathString      ${If} $6 == 1        DetailPrint "appended to $1"      ${Else}        DetailPrint "Target was appended to $1"      ${EndIf}    ${Else}                                ;  If Prepend (and EnvVar is not empty),      StrCpy $0 $4;$0                      ;     prepend PathString      ${If} $6 == 1        DetailPrint "prepended to $1"      ${Else}        DetailPrint "Target was prepended to $1"      ${EndIf}    ${EndIf}  ${Else}                                  ; If Action = Remove    ${If} $6 == 1                          ;   and we found the target      DetailPrint "Target was found and removed from $1"    ${Else}      DetailPrint "Target was NOT found in $1 (nothing to remove)"    ${EndIf}    ${If} $0 == ""      DetailPrint "$1 is now empty"    ${EndIf}  ${EndIf}   ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change  ;  ClearErrors  ${If} $3  == HKLM    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section  ${ElseIf} $3 == HKCU    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section  ${EndIf}   IfErrors 0 +4    MessageBox MB_OK|MB_ICONEXCLAMATION "Could not write updated $1 to $3"    DetailPrint "Could not write updated $1 to $3"    Goto EnvVarUpdate_Restore_Vars   ; "Export" our change  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000   EnvVarUpdate_Restore_Vars:  ;  ; Restore the user's variables and return ResultVar  Pop $R0  Pop $9  Pop $8  Pop $7  Pop $6  Pop $5  Pop $4  Pop $3  Pop $2  Pop $1  Push $0  ; Push my $0 (ResultVar)  Exch  Pop $0   ; Restore his $0 FunctionEnd !macroend   ; EnvVarUpdate UN!insertmacro EnvVarUpdate ""!insertmacro EnvVarUpdate "un.";----------------------------------- EnvVarUpdate end---------------------------------------- !verbose pop!endif
 |