<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://nsis.sourceforge.io/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Turnec2</id>
	<title>NSIS Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://nsis.sourceforge.io/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Turnec2"/>
	<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/Special:Contributions/Turnec2"/>
	<updated>2026-04-21T22:40:20Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.17</generator>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15651</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15651"/>
		<updated>2008-07-04T18:01:32Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Function Code */  Removed redundant definitions (HKLM/CU)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
;Function - EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
;Version 1.0&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. The variable can be updated in either the &amp;quot;all users&amp;quot; section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
Duplicates entries, leading and trailing spaces around each entry, and duplicate semicolons are permanently removed from the contents of the variable before performing the requested operation.  This step prevents the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). &lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for such things as removing&lt;br /&gt;
pathnames associated with earlier revisions in the event that the user &lt;br /&gt;
has failed to run the uninstaller. &lt;br /&gt;
&lt;br /&gt;
The updated contents of the variable returned in ResultVar might be useful for displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
;Design&lt;br /&gt;
&lt;br /&gt;
# Read the contents of EnvVarName from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# Remove all instances of the target path/string regardless of the operation because this not only eliminates duplicate entries, it also allows for the search order of the target entry to be changed from first to last and vice versa.&lt;br /&gt;
# If Action is &amp;quot;R&amp;quot; (remove), skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated variable to RegLoc even if the Action is &amp;quot;R&amp;quot; or the target is not found because this allows for the elimination of duplicate semicolons, spaces around semicolons, spaces preceding the first entry, and spaces following the last entry.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
=== Syntax ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
:; ResultVar&lt;br /&gt;
::Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
:; EnvVarName&lt;br /&gt;
:: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
:; Action&lt;br /&gt;
:: &amp;quot;A&amp;quot; = Append&lt;br /&gt;
:: &amp;quot;P&amp;quot; = Prepend&lt;br /&gt;
:: &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
:; RegLoc&lt;br /&gt;
:: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
:: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
:; PathString&lt;br /&gt;
:: A pathname or string to add to or remove from the contents of EnvVarName (e.g., &amp;quot;C:\MyApp&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
==== Installer Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\Windows Resource Kits\Tools&amp;quot; ; Append  &lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;%WinDir%\System32&amp;quot;                            ; Prepend     &lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;                                     ; Remove&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v1.0&amp;quot;  ; Remove path of old rev&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v2.0&amp;quot;  ; Append the new one&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Uninstaller Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;          &lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyApp-v2.0&amp;quot;      ; Remove path of latest rev &lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyApp-v1.0&amp;quot;      ; Restore path of previous rev&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
&lt;br /&gt;
* Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
* Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr  &lt;br /&gt;
* Diego Pedroso (deguix) for StrTok&lt;br /&gt;
* Kevin English (kenglish_hi)for StrContains&lt;br /&gt;
* Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry (dandaman32) for StrReplace&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Function Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call ${UN}StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   &lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
; NOTE: Do not substitute &#039;StrReplaceV4&#039; for this function. It will fail due to the way I call it.&lt;br /&gt;
;&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;br /&gt;
[[Category:System Related Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15650</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15650"/>
		<updated>2008-07-04T17:48:43Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Function Code */  Removed  _unStrTokConstructor (not needed)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
;Function - EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
;Version 1.0&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. The variable can be updated in either the &amp;quot;all users&amp;quot; section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
Duplicates entries, leading and trailing spaces around each entry, and duplicate semicolons are permanently removed from the contents of the variable before performing the requested operation.  This step prevents the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). &lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for such things as removing&lt;br /&gt;
pathnames associated with earlier revisions in the event that the user &lt;br /&gt;
has failed to run the uninstaller. &lt;br /&gt;
&lt;br /&gt;
The updated contents of the variable returned in ResultVar might be useful for displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
;Design&lt;br /&gt;
&lt;br /&gt;
# Read the contents of EnvVarName from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# Remove all instances of the target path/string regardless of the operation because this not only eliminates duplicate entries, it also allows for the search order of the target entry to be changed from first to last and vice versa.&lt;br /&gt;
# If Action is &amp;quot;R&amp;quot; (remove), skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated variable to RegLoc even if the Action is &amp;quot;R&amp;quot; or the target is not found because this allows for the elimination of duplicate semicolons, spaces around semicolons, spaces preceding the first entry, and spaces following the last entry.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
=== Syntax ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
:; ResultVar&lt;br /&gt;
::Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
:; EnvVarName&lt;br /&gt;
:: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
:; Action&lt;br /&gt;
:: &amp;quot;A&amp;quot; = Append&lt;br /&gt;
:: &amp;quot;P&amp;quot; = Prepend&lt;br /&gt;
:: &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
:; RegLoc&lt;br /&gt;
:: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
:: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
:; PathString&lt;br /&gt;
:: A pathname or string to add to or remove from the contents of EnvVarName (e.g., &amp;quot;C:\MyApp&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
==== Installer Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\Windows Resource Kits\Tools&amp;quot; ; Append  &lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;%WinDir%\System32&amp;quot;                            ; Prepend     &lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;                                     ; Remove&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v1.0&amp;quot;  ; Remove path of old rev&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v2.0&amp;quot;  ; Append the new one&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Uninstaller Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;          &lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyApp-v2.0&amp;quot;      ; Remove path of latest rev &lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyApp-v1.0&amp;quot;      ; Restore path of previous rev&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
&lt;br /&gt;
* Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
* Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr  &lt;br /&gt;
* Diego Pedroso (deguix) for StrTok&lt;br /&gt;
* Kevin English (kenglish_hi)for StrContains&lt;br /&gt;
* Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry (dandaman32) for StrReplace&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Function Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call ${UN}StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   &lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
; NOTE: Do not substitute &#039;StrReplaceV4&#039; for this function. It will fail due to the way I call it.&lt;br /&gt;
;&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;br /&gt;
[[Category:System Related Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15649</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15649"/>
		<updated>2008-07-04T16:35:55Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Uninstaller Examples */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
;Function - EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
;Version 1.0&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. The variable can be updated in either the &amp;quot;all users&amp;quot; section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
Duplicates entries, leading and trailing spaces around each entry, and duplicate semicolons are permanently removed from the contents of the variable before performing the requested operation.  This step prevents the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). &lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for such things as removing&lt;br /&gt;
pathnames associated with earlier revisions in the event that the user &lt;br /&gt;
has failed to run the uninstaller. &lt;br /&gt;
&lt;br /&gt;
The updated contents of the variable returned in ResultVar might be useful for displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
;Design&lt;br /&gt;
&lt;br /&gt;
# Read the contents of EnvVarName from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# Remove all instances of the target path/string regardless of the operation because this not only eliminates duplicate entries, it also allows for the search order of the target entry to be changed from first to last and vice versa.&lt;br /&gt;
# If Action is &amp;quot;R&amp;quot; (remove), skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated variable to RegLoc even if the Action is &amp;quot;R&amp;quot; or the target is not found because this allows for the elimination of duplicate semicolons, spaces around semicolons, spaces preceding the first entry, and spaces following the last entry.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
=== Syntax ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
:; ResultVar&lt;br /&gt;
::Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
:; EnvVarName&lt;br /&gt;
:: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
:; Action&lt;br /&gt;
:: &amp;quot;A&amp;quot; = Append&lt;br /&gt;
:: &amp;quot;P&amp;quot; = Prepend&lt;br /&gt;
:: &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
:; RegLoc&lt;br /&gt;
:: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
:: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
:; PathString&lt;br /&gt;
:: A pathname or string to add to or remove from the contents of EnvVarName (e.g., &amp;quot;C:\MyApp&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
==== Installer Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\Windows Resource Kits\Tools&amp;quot; ; Append  &lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;%WinDir%\System32&amp;quot;                            ; Prepend     &lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;                                     ; Remove&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v1.0&amp;quot;  ; Remove path of old rev&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v2.0&amp;quot;  ; Append the new one&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Uninstaller Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;          &lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyApp-v2.0&amp;quot;      ; Remove path of latest rev &lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyApp-v1.0&amp;quot;      ; Restore path of previous rev&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
&lt;br /&gt;
* Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
* Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr  &lt;br /&gt;
* Diego Pedroso (deguix) for StrTok&lt;br /&gt;
* Kevin English (kenglish_hi)for StrContains&lt;br /&gt;
* Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry (dandaman32) for StrReplace&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Function Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   &lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
; NOTE: Do not substitute &#039;StrReplaceV4&#039; for this function. It will fail due to the way I call it.&lt;br /&gt;
;&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;br /&gt;
[[Category:System Related Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15648</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15648"/>
		<updated>2008-07-04T16:33:57Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
;Function - EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
;Version 1.0&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. The variable can be updated in either the &amp;quot;all users&amp;quot; section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
Duplicates entries, leading and trailing spaces around each entry, and duplicate semicolons are permanently removed from the contents of the variable before performing the requested operation.  This step prevents the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). &lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for such things as removing&lt;br /&gt;
pathnames associated with earlier revisions in the event that the user &lt;br /&gt;
has failed to run the uninstaller. &lt;br /&gt;
&lt;br /&gt;
The updated contents of the variable returned in ResultVar might be useful for displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
;Design&lt;br /&gt;
&lt;br /&gt;
# Read the contents of EnvVarName from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# Remove all instances of the target path/string regardless of the operation because this not only eliminates duplicate entries, it also allows for the search order of the target entry to be changed from first to last and vice versa.&lt;br /&gt;
# If Action is &amp;quot;R&amp;quot; (remove), skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated variable to RegLoc even if the Action is &amp;quot;R&amp;quot; or the target is not found because this allows for the elimination of duplicate semicolons, spaces around semicolons, spaces preceding the first entry, and spaces following the last entry.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
=== Syntax ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
:; ResultVar&lt;br /&gt;
::Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
:; EnvVarName&lt;br /&gt;
:: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
:; Action&lt;br /&gt;
:: &amp;quot;A&amp;quot; = Append&lt;br /&gt;
:: &amp;quot;P&amp;quot; = Prepend&lt;br /&gt;
:: &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
:; RegLoc&lt;br /&gt;
:: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
:: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
:; PathString&lt;br /&gt;
:: A pathname or string to add to or remove from the contents of EnvVarName (e.g., &amp;quot;C:\MyApp&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
==== Installer Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\Windows Resource Kits\Tools&amp;quot; ; Append  &lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;%WinDir%\System32&amp;quot;                            ; Prepend     &lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;                                     ; Remove&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v1.0&amp;quot;  ; Remove path of old rev&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v2.0&amp;quot;  ; Append the new one&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Uninstaller Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;          &lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v2.0&amp;quot;      ; Remove path of latest rev &lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v1.0&amp;quot;      ; Restore path of previous rev&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
&lt;br /&gt;
* Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
* Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr  &lt;br /&gt;
* Diego Pedroso (deguix) for StrTok&lt;br /&gt;
* Kevin English (kenglish_hi)for StrContains&lt;br /&gt;
* Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry (dandaman32) for StrReplace&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Function Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   &lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
; NOTE: Do not substitute &#039;StrReplaceV4&#039; for this function. It will fail due to the way I call it.&lt;br /&gt;
;&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;br /&gt;
[[Category:System Related Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15647</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15647"/>
		<updated>2008-07-04T16:22:51Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
;Function - EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
;Version 1.0&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. The variable can be updated in either the &amp;quot;all users&amp;quot; section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
Duplicates entries, leading and trailing spaces around each entry, and duplicate semicolons are permanently removed from the contents of the variable before performing the requested operation.  This step prevents the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). &lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for such things as removing&lt;br /&gt;
pathnames associated with earlier revisions in the event that the user &lt;br /&gt;
has failed to run the uninstaller. &lt;br /&gt;
&lt;br /&gt;
The updated contents of the variable returned in ResultVar might be useful for displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
;Design&lt;br /&gt;
&lt;br /&gt;
# Read the contents of EnvVarName from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# Remove all instances of the target path/string regardless of the operation because this not only eliminates duplicate entries, it also allows for the search order of the target entry to be changed from first to last and vice versa.&lt;br /&gt;
# If Action is &amp;quot;R&amp;quot; (remove), skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated variable to RegLoc even if the Action is &amp;quot;R&amp;quot; or the target is not found because this allows for the elimination of duplicate semicolons, spaces around semicolons, spaces preceding the first entry, and spaces following the last entry.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
=== Syntax ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
:; ResultVar&lt;br /&gt;
::Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
:; EnvVarName&lt;br /&gt;
:: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
:; Action&lt;br /&gt;
:: &amp;quot;A&amp;quot; = Append&lt;br /&gt;
:: &amp;quot;P&amp;quot; = Prepend&lt;br /&gt;
:: &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
:; RegLoc&lt;br /&gt;
:: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
:: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
:; PathString&lt;br /&gt;
:: A pathname or string to add to or remove from the contents of EnvVarName (e.g., &amp;quot;C:\MyApp&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
==== Installer Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\Windows Resource Kits\Tools&amp;quot; ; Append  &lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;%WinDir%\System32&amp;quot;                            ; Prepend     &lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;                                     ; Remove&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v1.0&amp;quot;  ; Remove path of old rev&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v2.0&amp;quot;  ; Append the new one&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Uninstaller Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;          &lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v2.0&amp;quot;      ; Remove path of latest rev &lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v1.0&amp;quot;      ; Restore path of previous rev&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
&lt;br /&gt;
* Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
* Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr  &lt;br /&gt;
* Diego Pedroso (deguix) for StrTok&lt;br /&gt;
* Kevin English (kenglish_hi)for StrContains&lt;br /&gt;
* Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry (dandaman32) for StrReplace&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Function Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   &lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
; NOTE: Do not substitute &#039;StrReplaceV4&#039; for this function. It will fail due to the way I call it.&lt;br /&gt;
;&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Path_manipulation_with_all_users/current_user_selection_in_run-time&amp;diff=15646</id>
		<title>Path manipulation with all users/current user selection in run-time</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Path_manipulation_with_all_users/current_user_selection_in_run-time&amp;diff=15646"/>
		<updated>2008-07-04T16:19:44Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: Added a bit more explanation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}} &lt;br /&gt;
&lt;br /&gt;
== EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
The AddToPath and un.RemoveFromPath functions in this page have been obsoleted by EnvVarUpdate. &lt;br /&gt;
The un.RemoveFromPath routine can corrupt the contents of the PATH variable if the path being removed happens to be a subset of another. For example, if PATH contains &amp;quot;C:\Windows\system32\wbem&amp;quot; and you remove &amp;quot;C:\Windows\system32&amp;quot; the result is &amp;quot;\wbem&amp;quot;.  AddToPath does not prevent the duplication of entries if the user runs the installer multiple times (and the installer code does not otherwise check for duplicates).  Nevertheless, these routines have been retained for Windows 9x/ME users in the next section since EnvVarUpdate does not support the update of variables in the autoexec.bat file. &lt;br /&gt;
&lt;br /&gt;
See [[Environmental_Variables:_append%2C_prepend%2C_and_remove_entries]] for more information.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Function Code ==&lt;br /&gt;
&lt;br /&gt;
[[http://nsis.sourceforge.net/Environmental_Variables:_append%2C_prepend%2C_and_remove_entries#Function_Code EnvVarUpdate function code]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{PageAuthor|e-circ}}&lt;br /&gt;
== Functions for Windows 95, 98, and ME ==&lt;br /&gt;
&lt;br /&gt;
I adapted Path manipulation routines so you can select to change the path in the all users/current user profile in runtime.&lt;br /&gt;
&lt;br /&gt;
The original message:&lt;br /&gt;
&lt;br /&gt;
Here are two functions, one for adding directories to the search path of Windows and the other to remove them. These functions should work on every version of Windows including 95, 98, ME, NT, 2000, and XP.&lt;br /&gt;
&lt;br /&gt;
For Windows NT/2000/XP they will write to HKEY_CURRENT_USER\Environment\PATH. For 9x/ME they will write to the autoexec.bat file.&lt;br /&gt;
&lt;br /&gt;
Changes on 9x machines will take place after a reboot. These functions do not set the reboot flag so that should be done manually.&lt;br /&gt;
&lt;br /&gt;
These functions require NSIS 2.0b0 and above due to the usage of SendMessage with /TIMEOUT. It is possible to use it with earlier version of NSIS with a litte application I have created called RefreshEnv. It does exactly the same as SendMessage with /TIMEOUT. You can find it at this forum thread.&lt;br /&gt;
&lt;br /&gt;
Usage example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section &amp;quot;Add to path&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call AddToPath&lt;br /&gt;
SectionEnd&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
Section &amp;quot;uninstall&amp;quot;&lt;br /&gt;
  # ...&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call un.RemoveFromPath&lt;br /&gt;
  # ...&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The functions in the flesh:&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
;----------------------------------------&lt;br /&gt;
; based upon a script of &amp;quot;Written by KiCHiK 2003-01-18 05:57:02&amp;quot;&lt;br /&gt;
;----------------------------------------&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
!verbose 4&lt;br /&gt;
;====================================================&lt;br /&gt;
; get_NT_environment &lt;br /&gt;
;     Returns: the selected environment&lt;br /&gt;
;     Output : head of the stack&lt;br /&gt;
;====================================================&lt;br /&gt;
!macro select_NT_profile UN&lt;br /&gt;
Function ${UN}select_NT_profile&lt;br /&gt;
   MessageBox MB_YESNO|MB_ICONQUESTION &amp;quot;Change the environment for all users?$\r$\nSaying no here will change the envrironment for the current user only.$\r$\n(Administrator permissions required for all users)&amp;quot; \&lt;br /&gt;
      IDNO environment_single&lt;br /&gt;
      DetailPrint &amp;quot;Selected environment for all users&amp;quot;&lt;br /&gt;
      Push &amp;quot;all&amp;quot;&lt;br /&gt;
      Return&lt;br /&gt;
   environment_single:&lt;br /&gt;
      DetailPrint &amp;quot;Selected environment for current user only.&amp;quot;&lt;br /&gt;
      Push &amp;quot;current&amp;quot;&lt;br /&gt;
      Return&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro select_NT_profile &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro select_NT_profile &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------------------------&lt;br /&gt;
!define NT_current_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
!define NT_all_env     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
;====================================================&lt;br /&gt;
; IsNT - Returns 1 if the current system is NT, 0&lt;br /&gt;
;        otherwise.&lt;br /&gt;
;     Output: head of the stack&lt;br /&gt;
;====================================================&lt;br /&gt;
!macro IsNT UN&lt;br /&gt;
Function ${UN}IsNT&lt;br /&gt;
  Push $0&lt;br /&gt;
  ReadRegStr $0 HKLM &amp;quot;SOFTWARE\Microsoft\Windows NT\CurrentVersion&amp;quot; CurrentVersion&lt;br /&gt;
  StrCmp $0 &amp;quot;&amp;quot; 0 IsNT_yes&lt;br /&gt;
  ; we are not NT.&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Push 0&lt;br /&gt;
  Return&lt;br /&gt;
&lt;br /&gt;
  IsNT_yes:&lt;br /&gt;
    ; NT!!!&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Push 1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro IsNT &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro IsNT &amp;quot;un.&amp;quot;&lt;br /&gt;
;====================================================&lt;br /&gt;
; AddToPath - Adds the given dir to the search path.&lt;br /&gt;
;        Input - head of the stack&lt;br /&gt;
;        Note - Win9x systems requires reboot&lt;br /&gt;
;====================================================&lt;br /&gt;
Function AddToPath&lt;br /&gt;
   Exch $0&lt;br /&gt;
   Push $1&lt;br /&gt;
   Push $2&lt;br /&gt;
  &lt;br /&gt;
   Call IsNT&lt;br /&gt;
   Pop $1&lt;br /&gt;
   StrCmp $1 1 AddToPath_NT&lt;br /&gt;
      ; Not on NT&lt;br /&gt;
      StrCpy $1 $WINDIR 2&lt;br /&gt;
      FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; a&lt;br /&gt;
      FileSeek $1 0 END&lt;br /&gt;
      GetFullPathName /SHORT $0 $0&lt;br /&gt;
      FileWrite $1 &amp;quot;$\r$\nSET PATH=%PATH%;$0$\r$\n&amp;quot;&lt;br /&gt;
      FileClose $1&lt;br /&gt;
      Goto AddToPath_done&lt;br /&gt;
&lt;br /&gt;
   AddToPath_NT:&lt;br /&gt;
      Push $4&lt;br /&gt;
      Call select_NT_profile&lt;br /&gt;
      Pop  $4&lt;br /&gt;
&lt;br /&gt;
      AddToPath_NT_selection_done:&lt;br /&gt;
      StrCmp $4 &amp;quot;current&amp;quot; read_path_NT_current&lt;br /&gt;
         ReadRegStr $1 ${NT_all_env} &amp;quot;PATH&amp;quot;&lt;br /&gt;
         Goto read_path_NT_resume&lt;br /&gt;
      read_path_NT_current:&lt;br /&gt;
         ReadRegStr $1 ${NT_current_env} &amp;quot;PATH&amp;quot;&lt;br /&gt;
      read_path_NT_resume:&lt;br /&gt;
      StrCpy $2 $0&lt;br /&gt;
      StrCmp $1 &amp;quot;&amp;quot; AddToPath_NTdoIt&lt;br /&gt;
         StrCpy $2 &amp;quot;$1;$0&amp;quot;&lt;br /&gt;
      AddToPath_NTdoIt:&lt;br /&gt;
         StrCmp $4 &amp;quot;current&amp;quot; write_path_NT_current&lt;br /&gt;
            ClearErrors&lt;br /&gt;
            WriteRegExpandStr ${NT_all_env} &amp;quot;PATH&amp;quot; $2&lt;br /&gt;
            IfErrors 0 write_path_NT_resume&lt;br /&gt;
            MessageBox MB_YESNO|MB_ICONQUESTION &amp;quot;The path could not be set for all users$\r$\nShould I try for the current user?&amp;quot; \&lt;br /&gt;
               IDNO write_path_NT_failed&lt;br /&gt;
            ; change selection&lt;br /&gt;
            StrCpy $4 &amp;quot;current&amp;quot;&lt;br /&gt;
            Goto AddToPath_NT_selection_done&lt;br /&gt;
         write_path_NT_current:&lt;br /&gt;
            ClearErrors&lt;br /&gt;
            WriteRegExpandStr ${NT_current_env} &amp;quot;PATH&amp;quot; $2&lt;br /&gt;
            IfErrors 0 write_path_NT_resume&lt;br /&gt;
            MessageBox MB_OK|MB_ICONINFORMATION &amp;quot;The path could not be set for the current user.&amp;quot;&lt;br /&gt;
            Goto write_path_NT_failed&lt;br /&gt;
         write_path_NT_resume:&lt;br /&gt;
         SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
         DetailPrint &amp;quot;added path for user ($4), $0&amp;quot;&lt;br /&gt;
         write_path_NT_failed:&lt;br /&gt;
      &lt;br /&gt;
      Pop $4&lt;br /&gt;
   AddToPath_done:&lt;br /&gt;
   Pop $2&lt;br /&gt;
   Pop $1&lt;br /&gt;
   Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
;====================================================&lt;br /&gt;
; RemoveFromPath - Remove a given dir from the path&lt;br /&gt;
;     Input: head of the stack&lt;br /&gt;
;====================================================&lt;br /&gt;
Function un.RemoveFromPath&lt;br /&gt;
   Exch $0&lt;br /&gt;
   Push $1&lt;br /&gt;
   Push $2&lt;br /&gt;
   Push $3&lt;br /&gt;
   Push $4&lt;br /&gt;
   &lt;br /&gt;
   Call un.IsNT&lt;br /&gt;
   Pop $1&lt;br /&gt;
   StrCmp $1 1 unRemoveFromPath_NT&lt;br /&gt;
      ; Not on NT&lt;br /&gt;
      StrCpy $1 $WINDIR 2&lt;br /&gt;
      FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; r&lt;br /&gt;
      GetTempFileName $4&lt;br /&gt;
      FileOpen $2 $4 w&lt;br /&gt;
      GetFullPathName /SHORT $0 $0&lt;br /&gt;
      StrCpy $0 &amp;quot;SET PATH=%PATH%;$0&amp;quot;&lt;br /&gt;
      SetRebootFlag true&lt;br /&gt;
      Goto unRemoveFromPath_dosLoop&lt;br /&gt;
     &lt;br /&gt;
      unRemoveFromPath_dosLoop:&lt;br /&gt;
         FileRead $1 $3&lt;br /&gt;
         StrCmp $3 &amp;quot;$0$\r$\n&amp;quot; unRemoveFromPath_dosLoop&lt;br /&gt;
         StrCmp $3 &amp;quot;$0$\n&amp;quot; unRemoveFromPath_dosLoop&lt;br /&gt;
         StrCmp $3 &amp;quot;$0&amp;quot; unRemoveFromPath_dosLoop&lt;br /&gt;
         StrCmp $3 &amp;quot;&amp;quot; unRemoveFromPath_dosLoopEnd&lt;br /&gt;
         FileWrite $2 $3&lt;br /&gt;
         Goto unRemoveFromPath_dosLoop&lt;br /&gt;
&lt;br /&gt;
      unRemoveFromPath_dosLoopEnd:&lt;br /&gt;
         FileClose $2&lt;br /&gt;
         FileClose $1&lt;br /&gt;
         StrCpy $1 $WINDIR 2&lt;br /&gt;
         Delete &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
         CopyFiles /SILENT $4 &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
         Delete $4&lt;br /&gt;
         Goto unRemoveFromPath_done&lt;br /&gt;
 &lt;br /&gt;
   unRemoveFromPath_NT:&lt;br /&gt;
      StrLen $2 $0&lt;br /&gt;
      Call un.select_NT_profile&lt;br /&gt;
      Pop  $4&lt;br /&gt;
&lt;br /&gt;
      StrCmp $4 &amp;quot;current&amp;quot; un_read_path_NT_current&lt;br /&gt;
         ReadRegStr $1 ${NT_all_env} &amp;quot;PATH&amp;quot;&lt;br /&gt;
         Goto un_read_path_NT_resume&lt;br /&gt;
      un_read_path_NT_current:&lt;br /&gt;
         ReadRegStr $1 ${NT_current_env} &amp;quot;PATH&amp;quot;&lt;br /&gt;
      un_read_path_NT_resume:&lt;br /&gt;
&lt;br /&gt;
      Push $1&lt;br /&gt;
      Push $0&lt;br /&gt;
      Call un.StrStr ; Find $0 in $1&lt;br /&gt;
      Pop $0 ; pos of our dir&lt;br /&gt;
      IntCmp $0 -1 unRemoveFromPath_done&lt;br /&gt;
         ; else, it is in path&lt;br /&gt;
         StrCpy $3 $1 $0 ; $3 now has the part of the path before our dir&lt;br /&gt;
         IntOp $2 $2 + $0 ; $2 now contains the pos after our dir in the path (&#039;;&#039;)&lt;br /&gt;
         IntOp $2 $2 + 1 ; $2 now containts the pos after our dir and the semicolon.&lt;br /&gt;
         StrLen $0 $1&lt;br /&gt;
         StrCpy $1 $1 $0 $2&lt;br /&gt;
         StrCpy $3 &amp;quot;$3$1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
         StrCmp $4 &amp;quot;current&amp;quot; un_write_path_NT_current&lt;br /&gt;
            WriteRegExpandStr ${NT_all_env} &amp;quot;PATH&amp;quot; $3&lt;br /&gt;
            Goto un_write_path_NT_resume&lt;br /&gt;
         un_write_path_NT_current:&lt;br /&gt;
            WriteRegExpandStr ${NT_current_env} &amp;quot;PATH&amp;quot; $3&lt;br /&gt;
         un_write_path_NT_resume:&lt;br /&gt;
         SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
   unRemoveFromPath_done:&lt;br /&gt;
   Pop $4&lt;br /&gt;
   Pop $3&lt;br /&gt;
   Pop $2&lt;br /&gt;
   Pop $1&lt;br /&gt;
   Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&lt;br /&gt;
; Uninstall sutff&lt;br /&gt;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;====================================================&lt;br /&gt;
; StrStr - Finds a given string in another given string.&lt;br /&gt;
;               Returns -1 if not found and the pos if found.&lt;br /&gt;
;          Input: head of the stack - string to find&lt;br /&gt;
;                      second in the stack - string to find in&lt;br /&gt;
;          Output: head of the stack&lt;br /&gt;
;====================================================&lt;br /&gt;
Function un.StrStr&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0 ; $0 now have the string to find&lt;br /&gt;
  Push $1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Pop $1 ; $1 now have the string to find in&lt;br /&gt;
  Exch&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
&lt;br /&gt;
  StrCpy $2 -1&lt;br /&gt;
  StrLen $3 $0&lt;br /&gt;
  StrLen $4 $1&lt;br /&gt;
  IntOp $4 $4 - $3&lt;br /&gt;
&lt;br /&gt;
  unStrStr_loop:&lt;br /&gt;
    IntOp $2 $2 + 1&lt;br /&gt;
    IntCmp $2 $4 0 0 unStrStrReturn_notFound&lt;br /&gt;
    StrCpy $5 $1 $3 $2&lt;br /&gt;
    StrCmp $5 $0 unStrStr_done unStrStr_loop&lt;br /&gt;
&lt;br /&gt;
  unStrStrReturn_notFound:&lt;br /&gt;
    StrCpy $2 -1&lt;br /&gt;
&lt;br /&gt;
  unStrStr_done:&lt;br /&gt;
    Pop $5&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Exch $2&lt;br /&gt;
    Exch 2&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Pop $1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
;====================================================&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Setting_Environment_Variables&amp;diff=15645</id>
		<title>Setting Environment Variables</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Setting_Environment_Variables&amp;diff=15645"/>
		<updated>2008-07-04T16:09:11Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: Added EnvVarUpdate info and restructured the TOC&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|KiCHiK}}&lt;br /&gt;
== Setting Environmental Variables Temporarily ==&lt;br /&gt;
&lt;br /&gt;
If you want to set an environment variable only for the installer process and its sub-processes use:&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;System::Call &#039;Kernel32::SetEnvironmentVariableA(t, t) i(&amp;quot;name&amp;quot;, &amp;quot;value&amp;quot;).r0&#039;&lt;br /&gt;
StrCmp $0 0 error&lt;br /&gt;
  ExecWait ProgThatReadsEnv.exe&lt;br /&gt;
  Goto done&lt;br /&gt;
error:&lt;br /&gt;
  MessageBox MB_OK &amp;quot;Can&#039;t set environment variable&amp;quot;&lt;br /&gt;
done:&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{PageAuthor|turnec2}} &lt;br /&gt;
== Setting Environmental Variables Permanently ==&lt;br /&gt;
=== EnvVarUpdate ===&lt;br /&gt;
&lt;br /&gt;
The WriteEnvStr and un.DeleteEnvStr functions in this page have been obsoleted by EnvVarUpdate. &lt;br /&gt;
The un.DeleteEnvStr function can corrupt the contents of the PATH variable if the path being removed happens to be a subset of another path. For example, if PATH contains &amp;quot;C:\Windows\system32\wbem&amp;quot; and you remove &amp;quot;C:\Windows\system32&amp;quot; the result is &amp;quot;\wbem&amp;quot;.  WriteEnvStr does not prevent the duplication of entries if the user runs the installer multiple times (and the installer code does not otherwise check for duplicates). However, these routines are retained for Windows 9x and ME in the next section since EnvVarUpdate does not support the update of variables in the autoexec.bat file. &lt;br /&gt;
&lt;br /&gt;
See [[Environmental_Variables:_append%2C_prepend%2C_and_remove_entries]] for more information.&lt;br /&gt;
&lt;br /&gt;
==== Function Code ====&lt;br /&gt;
&lt;br /&gt;
[[http://nsis.sourceforge.net/Environmental_Variables:_append%2C_prepend%2C_and_remove_entries#Function_Code EnvVarUpdate function code]]&lt;br /&gt;
&lt;br /&gt;
{{PageAuthor|KiCHiK}}&lt;br /&gt;
=== Functions for Windows 95, 98, and ME ===&lt;br /&gt;
If you want to set an environment variable that will stick for every other process and after reboots too you should use the functions below. To use them either save them as a .NSH file and include them in your script, or just copy paste them in your script. If you choose to save them as a .NSH file use:&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;!include WriteEnvStr.nsh # or the name you chose&lt;br /&gt;
# ...&lt;br /&gt;
Section &amp;quot;Add Env Var&amp;quot;&lt;br /&gt;
  Push MyEnvVar&lt;br /&gt;
  Push MyEnvVarValue&lt;br /&gt;
  Call WriteEnvStr&lt;br /&gt;
SectionEnd&lt;br /&gt;
# ...&lt;br /&gt;
Section uninstall&lt;br /&gt;
  # remove the variable&lt;br /&gt;
  Push MyEnvVar&lt;br /&gt;
  Call un.DeleteEnvStr&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
If you want the environment variable to be available to all of the users using the computer define ALL_USERS before you include WriteEnvStr.nsh (or before the part of the script holding these functions if you didn&#039;t save it as a .NSH file). For example:&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;!define ALL_USERS&lt;br /&gt;
!include WriteEnvStr.nsh # or the name you chose&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Function Code ====&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; under Windows 9x a reboot is required for changes to take affect. The reboot flag will be set by these functions if a reboot is required.&lt;br /&gt;
&#039;&#039;&#039;Warning:&#039;&#039;&#039; this script will only work on NSIS 2.0b2 and above!&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;!ifndef _WriteEnvStr_nsh&lt;br /&gt;
!define _WriteEnvStr_nsh&lt;br /&gt;
&lt;br /&gt;
!include WinMessages.nsh&lt;br /&gt;
&lt;br /&gt;
!ifndef WriteEnvStr_RegKey&lt;br /&gt;
  !ifdef ALL_USERS&lt;br /&gt;
    !define WriteEnvStr_RegKey \&lt;br /&gt;
       &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
  !else&lt;br /&gt;
    !define WriteEnvStr_RegKey &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
  !endif&lt;br /&gt;
!endif&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# WriteEnvStr - Writes an environment variable&lt;br /&gt;
# Note: Win9x systems requires reboot&lt;br /&gt;
#&lt;br /&gt;
# Example:&lt;br /&gt;
#  Push &amp;quot;HOMEDIR&amp;quot;           # name&lt;br /&gt;
#  Push &amp;quot;C:\New Home Dir\&amp;quot;  # value&lt;br /&gt;
#  Call WriteEnvStr&lt;br /&gt;
#&lt;br /&gt;
Function WriteEnvStr&lt;br /&gt;
  Exch $1 ; $1 has environment variable value&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $0 ; $0 has environment variable name&lt;br /&gt;
  Push $2&lt;br /&gt;
&lt;br /&gt;
  Call IsNT&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 1 WriteEnvStr_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $2 $WINDIR 2 ; Copy drive of windows (c:)&lt;br /&gt;
    FileOpen $2 &amp;quot;$2\autoexec.bat&amp;quot; a&lt;br /&gt;
    FileSeek $2 0 END&lt;br /&gt;
    FileWrite $2 &amp;quot;$\r$\nSET $0=$1$\r$\n&amp;quot;&lt;br /&gt;
    FileClose $2&lt;br /&gt;
    SetRebootFlag true&lt;br /&gt;
    Goto WriteEnvStr_done&lt;br /&gt;
&lt;br /&gt;
  WriteEnvStr_NT:&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $1&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} \&lt;br /&gt;
        0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  WriteEnvStr_done:&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Pop $1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# un.DeleteEnvStr - Removes an environment variable&lt;br /&gt;
# Note: Win9x systems requires reboot&lt;br /&gt;
#&lt;br /&gt;
# Example:&lt;br /&gt;
#  Push &amp;quot;HOMEDIR&amp;quot;           # name&lt;br /&gt;
#  Call un.DeleteEnvStr&lt;br /&gt;
#&lt;br /&gt;
Function un.DeleteEnvStr&lt;br /&gt;
  Exch $0 ; $0 now has the name of the variable&lt;br /&gt;
  Push $1&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
&lt;br /&gt;
  Call un.IsNT&lt;br /&gt;
  Pop $1&lt;br /&gt;
  StrCmp $1 1 DeleteEnvStr_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $1 $WINDIR 2&lt;br /&gt;
    FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; r&lt;br /&gt;
    GetTempFileName $4&lt;br /&gt;
    FileOpen $2 $4 w&lt;br /&gt;
    StrCpy $0 &amp;quot;SET $0=&amp;quot;&lt;br /&gt;
    SetRebootFlag true&lt;br /&gt;
&lt;br /&gt;
    DeleteEnvStr_dosLoop:&lt;br /&gt;
      FileRead $1 $3&lt;br /&gt;
      StrLen $5 $0&lt;br /&gt;
      StrCpy $5 $3 $5&lt;br /&gt;
      StrCmp $5 $0 DeleteEnvStr_dosLoop&lt;br /&gt;
      StrCmp $5 &amp;quot;&amp;quot; DeleteEnvStr_dosLoopEnd&lt;br /&gt;
      FileWrite $2 $3&lt;br /&gt;
      Goto DeleteEnvStr_dosLoop&lt;br /&gt;
&lt;br /&gt;
    DeleteEnvStr_dosLoopEnd:&lt;br /&gt;
      FileClose $2&lt;br /&gt;
      FileClose $1&lt;br /&gt;
      StrCpy $1 $WINDIR 2&lt;br /&gt;
      Delete &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
      CopyFiles /SILENT $4 &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
      Delete $4&lt;br /&gt;
      Goto DeleteEnvStr_done&lt;br /&gt;
&lt;br /&gt;
  DeleteEnvStr_NT:&lt;br /&gt;
    DeleteRegValue ${WriteEnvStr_RegKey} $0&lt;br /&gt;
    SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} \&lt;br /&gt;
      0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  DeleteEnvStr_done:&lt;br /&gt;
    Pop $5&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!ifndef IsNT_KiCHiK&lt;br /&gt;
!define IsNT_KiCHiK&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# [un.]IsNT - Pushes 1 if running on NT, 0 if not&lt;br /&gt;
#&lt;br /&gt;
# Example:&lt;br /&gt;
#   Call IsNT&lt;br /&gt;
#   Pop $0&lt;br /&gt;
#   StrCmp $0 1 +3&lt;br /&gt;
#     MessageBox MB_OK &amp;quot;Not running on NT!&amp;quot;&lt;br /&gt;
#     Goto +2&lt;br /&gt;
#     MessageBox MB_OK &amp;quot;Running on NT!&amp;quot;&lt;br /&gt;
#&lt;br /&gt;
!macro IsNT UN&lt;br /&gt;
Function ${UN}IsNT&lt;br /&gt;
  Push $0&lt;br /&gt;
  ReadRegStr $0 HKLM \&lt;br /&gt;
    &amp;quot;SOFTWARE\Microsoft\Windows NT\CurrentVersion&amp;quot; CurrentVersion&lt;br /&gt;
  StrCmp $0 &amp;quot;&amp;quot; 0 IsNT_yes&lt;br /&gt;
  ; we are not NT.&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Push 0&lt;br /&gt;
  Return&lt;br /&gt;
&lt;br /&gt;
  IsNT_yes:&lt;br /&gt;
    ; NT!!!&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Push 1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro IsNT &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro IsNT &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!endif ; IsNT_KiCHiK&lt;br /&gt;
&lt;br /&gt;
!endif ; _WriteEnvStr_nsh&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Path_manipulation_with_all_users/current_user_selection_in_run-time&amp;diff=15644</id>
		<title>Path manipulation with all users/current user selection in run-time</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Path_manipulation_with_all_users/current_user_selection_in_run-time&amp;diff=15644"/>
		<updated>2008-07-04T15:30:40Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}} &lt;br /&gt;
&lt;br /&gt;
== EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
The AddToPath and un.RemoveFromPath functions in this page have been obsoleted by EnvVarUpdate. &lt;br /&gt;
These routines can corrupt the contents of the PATH variable if the path being removed happens to be a subset of another path. For example, if PATH contains &amp;quot;C:\Windows\system32\wbem&amp;quot; and you remove &amp;quot;C:\Windows\system32&amp;quot; the result is &amp;quot;\wbem&amp;quot;. They also do not prevent duplication of entries if the user runs the installer multiple times (and the installer code does not check for duplicates). &lt;br /&gt;
&lt;br /&gt;
See [[Environmental_Variables:_append%2C_prepend%2C_and_remove_entries]] for more information.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Function Code ==&lt;br /&gt;
&lt;br /&gt;
[[http://nsis.sourceforge.net/Environmental_Variables:_append%2C_prepend%2C_and_remove_entries#Function_Code EnvVarUpdate function code]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Functions for Windows 95, 98, and ME ==&lt;br /&gt;
&lt;br /&gt;
{{PageAuthor|e-circ}}&lt;br /&gt;
&lt;br /&gt;
I adapted Path manipulation routines so you can select to change the path in the all users/current user profile in runtime.&lt;br /&gt;
&lt;br /&gt;
The original message:&lt;br /&gt;
&lt;br /&gt;
Here are two functions, one for adding directories to the search path of Windows and the other to remove them. These functions should work on every version of Windows including 95, 98, ME, NT, 2000, and XP.&lt;br /&gt;
&lt;br /&gt;
For Windows NT/2000/XP they will write to HKEY_CURRENT_USER\Environment\PATH. For 9x/ME they will write to the autoexec.bat file.&lt;br /&gt;
&lt;br /&gt;
Changes on 9x machines will take place after a reboot. These functions do not set the reboot flag so that should be done manually.&lt;br /&gt;
&lt;br /&gt;
These functions require NSIS 2.0b0 and above due to the usage of SendMessage with /TIMEOUT. It is possible to use it with earlier version of NSIS with a litte application I have created called RefreshEnv. It does exactly the same as SendMessage with /TIMEOUT. You can find it at this forum thread.&lt;br /&gt;
&lt;br /&gt;
Usage example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section &amp;quot;Add to path&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call AddToPath&lt;br /&gt;
SectionEnd&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
Section &amp;quot;uninstall&amp;quot;&lt;br /&gt;
  # ...&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call un.RemoveFromPath&lt;br /&gt;
  # ...&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The functions in the flesh:&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
;----------------------------------------&lt;br /&gt;
; based upon a script of &amp;quot;Written by KiCHiK 2003-01-18 05:57:02&amp;quot;&lt;br /&gt;
;----------------------------------------&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
!verbose 4&lt;br /&gt;
;====================================================&lt;br /&gt;
; get_NT_environment &lt;br /&gt;
;     Returns: the selected environment&lt;br /&gt;
;     Output : head of the stack&lt;br /&gt;
;====================================================&lt;br /&gt;
!macro select_NT_profile UN&lt;br /&gt;
Function ${UN}select_NT_profile&lt;br /&gt;
   MessageBox MB_YESNO|MB_ICONQUESTION &amp;quot;Change the environment for all users?$\r$\nSaying no here will change the envrironment for the current user only.$\r$\n(Administrator permissions required for all users)&amp;quot; \&lt;br /&gt;
      IDNO environment_single&lt;br /&gt;
      DetailPrint &amp;quot;Selected environment for all users&amp;quot;&lt;br /&gt;
      Push &amp;quot;all&amp;quot;&lt;br /&gt;
      Return&lt;br /&gt;
   environment_single:&lt;br /&gt;
      DetailPrint &amp;quot;Selected environment for current user only.&amp;quot;&lt;br /&gt;
      Push &amp;quot;current&amp;quot;&lt;br /&gt;
      Return&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro select_NT_profile &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro select_NT_profile &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------------------------&lt;br /&gt;
!define NT_current_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
!define NT_all_env     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
;====================================================&lt;br /&gt;
; IsNT - Returns 1 if the current system is NT, 0&lt;br /&gt;
;        otherwise.&lt;br /&gt;
;     Output: head of the stack&lt;br /&gt;
;====================================================&lt;br /&gt;
!macro IsNT UN&lt;br /&gt;
Function ${UN}IsNT&lt;br /&gt;
  Push $0&lt;br /&gt;
  ReadRegStr $0 HKLM &amp;quot;SOFTWARE\Microsoft\Windows NT\CurrentVersion&amp;quot; CurrentVersion&lt;br /&gt;
  StrCmp $0 &amp;quot;&amp;quot; 0 IsNT_yes&lt;br /&gt;
  ; we are not NT.&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Push 0&lt;br /&gt;
  Return&lt;br /&gt;
&lt;br /&gt;
  IsNT_yes:&lt;br /&gt;
    ; NT!!!&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Push 1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro IsNT &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro IsNT &amp;quot;un.&amp;quot;&lt;br /&gt;
;====================================================&lt;br /&gt;
; AddToPath - Adds the given dir to the search path.&lt;br /&gt;
;        Input - head of the stack&lt;br /&gt;
;        Note - Win9x systems requires reboot&lt;br /&gt;
;====================================================&lt;br /&gt;
Function AddToPath&lt;br /&gt;
   Exch $0&lt;br /&gt;
   Push $1&lt;br /&gt;
   Push $2&lt;br /&gt;
  &lt;br /&gt;
   Call IsNT&lt;br /&gt;
   Pop $1&lt;br /&gt;
   StrCmp $1 1 AddToPath_NT&lt;br /&gt;
      ; Not on NT&lt;br /&gt;
      StrCpy $1 $WINDIR 2&lt;br /&gt;
      FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; a&lt;br /&gt;
      FileSeek $1 0 END&lt;br /&gt;
      GetFullPathName /SHORT $0 $0&lt;br /&gt;
      FileWrite $1 &amp;quot;$\r$\nSET PATH=%PATH%;$0$\r$\n&amp;quot;&lt;br /&gt;
      FileClose $1&lt;br /&gt;
      Goto AddToPath_done&lt;br /&gt;
&lt;br /&gt;
   AddToPath_NT:&lt;br /&gt;
      Push $4&lt;br /&gt;
      Call select_NT_profile&lt;br /&gt;
      Pop  $4&lt;br /&gt;
&lt;br /&gt;
      AddToPath_NT_selection_done:&lt;br /&gt;
      StrCmp $4 &amp;quot;current&amp;quot; read_path_NT_current&lt;br /&gt;
         ReadRegStr $1 ${NT_all_env} &amp;quot;PATH&amp;quot;&lt;br /&gt;
         Goto read_path_NT_resume&lt;br /&gt;
      read_path_NT_current:&lt;br /&gt;
         ReadRegStr $1 ${NT_current_env} &amp;quot;PATH&amp;quot;&lt;br /&gt;
      read_path_NT_resume:&lt;br /&gt;
      StrCpy $2 $0&lt;br /&gt;
      StrCmp $1 &amp;quot;&amp;quot; AddToPath_NTdoIt&lt;br /&gt;
         StrCpy $2 &amp;quot;$1;$0&amp;quot;&lt;br /&gt;
      AddToPath_NTdoIt:&lt;br /&gt;
         StrCmp $4 &amp;quot;current&amp;quot; write_path_NT_current&lt;br /&gt;
            ClearErrors&lt;br /&gt;
            WriteRegExpandStr ${NT_all_env} &amp;quot;PATH&amp;quot; $2&lt;br /&gt;
            IfErrors 0 write_path_NT_resume&lt;br /&gt;
            MessageBox MB_YESNO|MB_ICONQUESTION &amp;quot;The path could not be set for all users$\r$\nShould I try for the current user?&amp;quot; \&lt;br /&gt;
               IDNO write_path_NT_failed&lt;br /&gt;
            ; change selection&lt;br /&gt;
            StrCpy $4 &amp;quot;current&amp;quot;&lt;br /&gt;
            Goto AddToPath_NT_selection_done&lt;br /&gt;
         write_path_NT_current:&lt;br /&gt;
            ClearErrors&lt;br /&gt;
            WriteRegExpandStr ${NT_current_env} &amp;quot;PATH&amp;quot; $2&lt;br /&gt;
            IfErrors 0 write_path_NT_resume&lt;br /&gt;
            MessageBox MB_OK|MB_ICONINFORMATION &amp;quot;The path could not be set for the current user.&amp;quot;&lt;br /&gt;
            Goto write_path_NT_failed&lt;br /&gt;
         write_path_NT_resume:&lt;br /&gt;
         SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
         DetailPrint &amp;quot;added path for user ($4), $0&amp;quot;&lt;br /&gt;
         write_path_NT_failed:&lt;br /&gt;
      &lt;br /&gt;
      Pop $4&lt;br /&gt;
   AddToPath_done:&lt;br /&gt;
   Pop $2&lt;br /&gt;
   Pop $1&lt;br /&gt;
   Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
;====================================================&lt;br /&gt;
; RemoveFromPath - Remove a given dir from the path&lt;br /&gt;
;     Input: head of the stack&lt;br /&gt;
;====================================================&lt;br /&gt;
Function un.RemoveFromPath&lt;br /&gt;
   Exch $0&lt;br /&gt;
   Push $1&lt;br /&gt;
   Push $2&lt;br /&gt;
   Push $3&lt;br /&gt;
   Push $4&lt;br /&gt;
   &lt;br /&gt;
   Call un.IsNT&lt;br /&gt;
   Pop $1&lt;br /&gt;
   StrCmp $1 1 unRemoveFromPath_NT&lt;br /&gt;
      ; Not on NT&lt;br /&gt;
      StrCpy $1 $WINDIR 2&lt;br /&gt;
      FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; r&lt;br /&gt;
      GetTempFileName $4&lt;br /&gt;
      FileOpen $2 $4 w&lt;br /&gt;
      GetFullPathName /SHORT $0 $0&lt;br /&gt;
      StrCpy $0 &amp;quot;SET PATH=%PATH%;$0&amp;quot;&lt;br /&gt;
      SetRebootFlag true&lt;br /&gt;
      Goto unRemoveFromPath_dosLoop&lt;br /&gt;
     &lt;br /&gt;
      unRemoveFromPath_dosLoop:&lt;br /&gt;
         FileRead $1 $3&lt;br /&gt;
         StrCmp $3 &amp;quot;$0$\r$\n&amp;quot; unRemoveFromPath_dosLoop&lt;br /&gt;
         StrCmp $3 &amp;quot;$0$\n&amp;quot; unRemoveFromPath_dosLoop&lt;br /&gt;
         StrCmp $3 &amp;quot;$0&amp;quot; unRemoveFromPath_dosLoop&lt;br /&gt;
         StrCmp $3 &amp;quot;&amp;quot; unRemoveFromPath_dosLoopEnd&lt;br /&gt;
         FileWrite $2 $3&lt;br /&gt;
         Goto unRemoveFromPath_dosLoop&lt;br /&gt;
&lt;br /&gt;
      unRemoveFromPath_dosLoopEnd:&lt;br /&gt;
         FileClose $2&lt;br /&gt;
         FileClose $1&lt;br /&gt;
         StrCpy $1 $WINDIR 2&lt;br /&gt;
         Delete &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
         CopyFiles /SILENT $4 &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
         Delete $4&lt;br /&gt;
         Goto unRemoveFromPath_done&lt;br /&gt;
 &lt;br /&gt;
   unRemoveFromPath_NT:&lt;br /&gt;
      StrLen $2 $0&lt;br /&gt;
      Call un.select_NT_profile&lt;br /&gt;
      Pop  $4&lt;br /&gt;
&lt;br /&gt;
      StrCmp $4 &amp;quot;current&amp;quot; un_read_path_NT_current&lt;br /&gt;
         ReadRegStr $1 ${NT_all_env} &amp;quot;PATH&amp;quot;&lt;br /&gt;
         Goto un_read_path_NT_resume&lt;br /&gt;
      un_read_path_NT_current:&lt;br /&gt;
         ReadRegStr $1 ${NT_current_env} &amp;quot;PATH&amp;quot;&lt;br /&gt;
      un_read_path_NT_resume:&lt;br /&gt;
&lt;br /&gt;
      Push $1&lt;br /&gt;
      Push $0&lt;br /&gt;
      Call un.StrStr ; Find $0 in $1&lt;br /&gt;
      Pop $0 ; pos of our dir&lt;br /&gt;
      IntCmp $0 -1 unRemoveFromPath_done&lt;br /&gt;
         ; else, it is in path&lt;br /&gt;
         StrCpy $3 $1 $0 ; $3 now has the part of the path before our dir&lt;br /&gt;
         IntOp $2 $2 + $0 ; $2 now contains the pos after our dir in the path (&#039;;&#039;)&lt;br /&gt;
         IntOp $2 $2 + 1 ; $2 now containts the pos after our dir and the semicolon.&lt;br /&gt;
         StrLen $0 $1&lt;br /&gt;
         StrCpy $1 $1 $0 $2&lt;br /&gt;
         StrCpy $3 &amp;quot;$3$1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
         StrCmp $4 &amp;quot;current&amp;quot; un_write_path_NT_current&lt;br /&gt;
            WriteRegExpandStr ${NT_all_env} &amp;quot;PATH&amp;quot; $3&lt;br /&gt;
            Goto un_write_path_NT_resume&lt;br /&gt;
         un_write_path_NT_current:&lt;br /&gt;
            WriteRegExpandStr ${NT_current_env} &amp;quot;PATH&amp;quot; $3&lt;br /&gt;
         un_write_path_NT_resume:&lt;br /&gt;
         SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
   unRemoveFromPath_done:&lt;br /&gt;
   Pop $4&lt;br /&gt;
   Pop $3&lt;br /&gt;
   Pop $2&lt;br /&gt;
   Pop $1&lt;br /&gt;
   Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&lt;br /&gt;
; Uninstall sutff&lt;br /&gt;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;====================================================&lt;br /&gt;
; StrStr - Finds a given string in another given string.&lt;br /&gt;
;               Returns -1 if not found and the pos if found.&lt;br /&gt;
;          Input: head of the stack - string to find&lt;br /&gt;
;                      second in the stack - string to find in&lt;br /&gt;
;          Output: head of the stack&lt;br /&gt;
;====================================================&lt;br /&gt;
Function un.StrStr&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0 ; $0 now have the string to find&lt;br /&gt;
  Push $1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Pop $1 ; $1 now have the string to find in&lt;br /&gt;
  Exch&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
&lt;br /&gt;
  StrCpy $2 -1&lt;br /&gt;
  StrLen $3 $0&lt;br /&gt;
  StrLen $4 $1&lt;br /&gt;
  IntOp $4 $4 - $3&lt;br /&gt;
&lt;br /&gt;
  unStrStr_loop:&lt;br /&gt;
    IntOp $2 $2 + 1&lt;br /&gt;
    IntCmp $2 $4 0 0 unStrStrReturn_notFound&lt;br /&gt;
    StrCpy $5 $1 $3 $2&lt;br /&gt;
    StrCmp $5 $0 unStrStr_done unStrStr_loop&lt;br /&gt;
&lt;br /&gt;
  unStrStrReturn_notFound:&lt;br /&gt;
    StrCpy $2 -1&lt;br /&gt;
&lt;br /&gt;
  unStrStr_done:&lt;br /&gt;
    Pop $5&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Exch $2&lt;br /&gt;
    Exch 2&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Pop $1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
;====================================================&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Path_manipulation_with_all_users/current_user_selection_in_run-time&amp;diff=15643</id>
		<title>Path manipulation with all users/current user selection in run-time</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Path_manipulation_with_all_users/current_user_selection_in_run-time&amp;diff=15643"/>
		<updated>2008-07-04T15:29:55Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}} &lt;br /&gt;
&lt;br /&gt;
== EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
The AddToPath and un.RemoveFromPath functions in this page have been obsoleted by EnvVarUpdate. &lt;br /&gt;
These routines can corrupt the contents of the PATH variable if the path being removed happens to be a subset of another path. For example, if PATH contains &amp;quot;C:\Windows\system32\wbem&amp;quot; and you remove &amp;quot;C:\Windows\system32&amp;quot; the result is &amp;quot;\wbem&amp;quot;. They also do not prevent duplication of entries if the user runs the installer multiple times (and the installer code does not check for duplicates). &lt;br /&gt;
&lt;br /&gt;
See [[Environmental_Variables:_append%2C_prepend%2C_and_remove_entries]] for more information.&lt;br /&gt;
&lt;br /&gt;
== Function Code ==&lt;br /&gt;
&lt;br /&gt;
[[http://nsis.sourceforge.net/Environmental_Variables:_append%2C_prepend%2C_and_remove_entries#Function_Code EnvVarUpdate function code]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Functions for Windows 95, 98, and ME ==&lt;br /&gt;
&lt;br /&gt;
{{PageAuthor|e-circ}}&lt;br /&gt;
&lt;br /&gt;
I adapted Path manipulation routines so you can select to change the path in the all users/current user profile in runtime.&lt;br /&gt;
&lt;br /&gt;
The original message:&lt;br /&gt;
&lt;br /&gt;
Here are two functions, one for adding directories to the search path of Windows and the other to remove them. These functions should work on every version of Windows including 95, 98, ME, NT, 2000, and XP.&lt;br /&gt;
&lt;br /&gt;
For Windows NT/2000/XP they will write to HKEY_CURRENT_USER\Environment\PATH. For 9x/ME they will write to the autoexec.bat file.&lt;br /&gt;
&lt;br /&gt;
Changes on 9x machines will take place after a reboot. These functions do not set the reboot flag so that should be done manually.&lt;br /&gt;
&lt;br /&gt;
These functions require NSIS 2.0b0 and above due to the usage of SendMessage with /TIMEOUT. It is possible to use it with earlier version of NSIS with a litte application I have created called RefreshEnv. It does exactly the same as SendMessage with /TIMEOUT. You can find it at this forum thread.&lt;br /&gt;
&lt;br /&gt;
Usage example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section &amp;quot;Add to path&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call AddToPath&lt;br /&gt;
SectionEnd&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
Section &amp;quot;uninstall&amp;quot;&lt;br /&gt;
  # ...&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call un.RemoveFromPath&lt;br /&gt;
  # ...&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The functions in the flesh:&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
;----------------------------------------&lt;br /&gt;
; based upon a script of &amp;quot;Written by KiCHiK 2003-01-18 05:57:02&amp;quot;&lt;br /&gt;
;----------------------------------------&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
!verbose 4&lt;br /&gt;
;====================================================&lt;br /&gt;
; get_NT_environment &lt;br /&gt;
;     Returns: the selected environment&lt;br /&gt;
;     Output : head of the stack&lt;br /&gt;
;====================================================&lt;br /&gt;
!macro select_NT_profile UN&lt;br /&gt;
Function ${UN}select_NT_profile&lt;br /&gt;
   MessageBox MB_YESNO|MB_ICONQUESTION &amp;quot;Change the environment for all users?$\r$\nSaying no here will change the envrironment for the current user only.$\r$\n(Administrator permissions required for all users)&amp;quot; \&lt;br /&gt;
      IDNO environment_single&lt;br /&gt;
      DetailPrint &amp;quot;Selected environment for all users&amp;quot;&lt;br /&gt;
      Push &amp;quot;all&amp;quot;&lt;br /&gt;
      Return&lt;br /&gt;
   environment_single:&lt;br /&gt;
      DetailPrint &amp;quot;Selected environment for current user only.&amp;quot;&lt;br /&gt;
      Push &amp;quot;current&amp;quot;&lt;br /&gt;
      Return&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro select_NT_profile &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro select_NT_profile &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------------------------&lt;br /&gt;
!define NT_current_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
!define NT_all_env     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
;====================================================&lt;br /&gt;
; IsNT - Returns 1 if the current system is NT, 0&lt;br /&gt;
;        otherwise.&lt;br /&gt;
;     Output: head of the stack&lt;br /&gt;
;====================================================&lt;br /&gt;
!macro IsNT UN&lt;br /&gt;
Function ${UN}IsNT&lt;br /&gt;
  Push $0&lt;br /&gt;
  ReadRegStr $0 HKLM &amp;quot;SOFTWARE\Microsoft\Windows NT\CurrentVersion&amp;quot; CurrentVersion&lt;br /&gt;
  StrCmp $0 &amp;quot;&amp;quot; 0 IsNT_yes&lt;br /&gt;
  ; we are not NT.&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Push 0&lt;br /&gt;
  Return&lt;br /&gt;
&lt;br /&gt;
  IsNT_yes:&lt;br /&gt;
    ; NT!!!&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Push 1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro IsNT &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro IsNT &amp;quot;un.&amp;quot;&lt;br /&gt;
;====================================================&lt;br /&gt;
; AddToPath - Adds the given dir to the search path.&lt;br /&gt;
;        Input - head of the stack&lt;br /&gt;
;        Note - Win9x systems requires reboot&lt;br /&gt;
;====================================================&lt;br /&gt;
Function AddToPath&lt;br /&gt;
   Exch $0&lt;br /&gt;
   Push $1&lt;br /&gt;
   Push $2&lt;br /&gt;
  &lt;br /&gt;
   Call IsNT&lt;br /&gt;
   Pop $1&lt;br /&gt;
   StrCmp $1 1 AddToPath_NT&lt;br /&gt;
      ; Not on NT&lt;br /&gt;
      StrCpy $1 $WINDIR 2&lt;br /&gt;
      FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; a&lt;br /&gt;
      FileSeek $1 0 END&lt;br /&gt;
      GetFullPathName /SHORT $0 $0&lt;br /&gt;
      FileWrite $1 &amp;quot;$\r$\nSET PATH=%PATH%;$0$\r$\n&amp;quot;&lt;br /&gt;
      FileClose $1&lt;br /&gt;
      Goto AddToPath_done&lt;br /&gt;
&lt;br /&gt;
   AddToPath_NT:&lt;br /&gt;
      Push $4&lt;br /&gt;
      Call select_NT_profile&lt;br /&gt;
      Pop  $4&lt;br /&gt;
&lt;br /&gt;
      AddToPath_NT_selection_done:&lt;br /&gt;
      StrCmp $4 &amp;quot;current&amp;quot; read_path_NT_current&lt;br /&gt;
         ReadRegStr $1 ${NT_all_env} &amp;quot;PATH&amp;quot;&lt;br /&gt;
         Goto read_path_NT_resume&lt;br /&gt;
      read_path_NT_current:&lt;br /&gt;
         ReadRegStr $1 ${NT_current_env} &amp;quot;PATH&amp;quot;&lt;br /&gt;
      read_path_NT_resume:&lt;br /&gt;
      StrCpy $2 $0&lt;br /&gt;
      StrCmp $1 &amp;quot;&amp;quot; AddToPath_NTdoIt&lt;br /&gt;
         StrCpy $2 &amp;quot;$1;$0&amp;quot;&lt;br /&gt;
      AddToPath_NTdoIt:&lt;br /&gt;
         StrCmp $4 &amp;quot;current&amp;quot; write_path_NT_current&lt;br /&gt;
            ClearErrors&lt;br /&gt;
            WriteRegExpandStr ${NT_all_env} &amp;quot;PATH&amp;quot; $2&lt;br /&gt;
            IfErrors 0 write_path_NT_resume&lt;br /&gt;
            MessageBox MB_YESNO|MB_ICONQUESTION &amp;quot;The path could not be set for all users$\r$\nShould I try for the current user?&amp;quot; \&lt;br /&gt;
               IDNO write_path_NT_failed&lt;br /&gt;
            ; change selection&lt;br /&gt;
            StrCpy $4 &amp;quot;current&amp;quot;&lt;br /&gt;
            Goto AddToPath_NT_selection_done&lt;br /&gt;
         write_path_NT_current:&lt;br /&gt;
            ClearErrors&lt;br /&gt;
            WriteRegExpandStr ${NT_current_env} &amp;quot;PATH&amp;quot; $2&lt;br /&gt;
            IfErrors 0 write_path_NT_resume&lt;br /&gt;
            MessageBox MB_OK|MB_ICONINFORMATION &amp;quot;The path could not be set for the current user.&amp;quot;&lt;br /&gt;
            Goto write_path_NT_failed&lt;br /&gt;
         write_path_NT_resume:&lt;br /&gt;
         SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
         DetailPrint &amp;quot;added path for user ($4), $0&amp;quot;&lt;br /&gt;
         write_path_NT_failed:&lt;br /&gt;
      &lt;br /&gt;
      Pop $4&lt;br /&gt;
   AddToPath_done:&lt;br /&gt;
   Pop $2&lt;br /&gt;
   Pop $1&lt;br /&gt;
   Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
;====================================================&lt;br /&gt;
; RemoveFromPath - Remove a given dir from the path&lt;br /&gt;
;     Input: head of the stack&lt;br /&gt;
;====================================================&lt;br /&gt;
Function un.RemoveFromPath&lt;br /&gt;
   Exch $0&lt;br /&gt;
   Push $1&lt;br /&gt;
   Push $2&lt;br /&gt;
   Push $3&lt;br /&gt;
   Push $4&lt;br /&gt;
   &lt;br /&gt;
   Call un.IsNT&lt;br /&gt;
   Pop $1&lt;br /&gt;
   StrCmp $1 1 unRemoveFromPath_NT&lt;br /&gt;
      ; Not on NT&lt;br /&gt;
      StrCpy $1 $WINDIR 2&lt;br /&gt;
      FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; r&lt;br /&gt;
      GetTempFileName $4&lt;br /&gt;
      FileOpen $2 $4 w&lt;br /&gt;
      GetFullPathName /SHORT $0 $0&lt;br /&gt;
      StrCpy $0 &amp;quot;SET PATH=%PATH%;$0&amp;quot;&lt;br /&gt;
      SetRebootFlag true&lt;br /&gt;
      Goto unRemoveFromPath_dosLoop&lt;br /&gt;
     &lt;br /&gt;
      unRemoveFromPath_dosLoop:&lt;br /&gt;
         FileRead $1 $3&lt;br /&gt;
         StrCmp $3 &amp;quot;$0$\r$\n&amp;quot; unRemoveFromPath_dosLoop&lt;br /&gt;
         StrCmp $3 &amp;quot;$0$\n&amp;quot; unRemoveFromPath_dosLoop&lt;br /&gt;
         StrCmp $3 &amp;quot;$0&amp;quot; unRemoveFromPath_dosLoop&lt;br /&gt;
         StrCmp $3 &amp;quot;&amp;quot; unRemoveFromPath_dosLoopEnd&lt;br /&gt;
         FileWrite $2 $3&lt;br /&gt;
         Goto unRemoveFromPath_dosLoop&lt;br /&gt;
&lt;br /&gt;
      unRemoveFromPath_dosLoopEnd:&lt;br /&gt;
         FileClose $2&lt;br /&gt;
         FileClose $1&lt;br /&gt;
         StrCpy $1 $WINDIR 2&lt;br /&gt;
         Delete &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
         CopyFiles /SILENT $4 &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
         Delete $4&lt;br /&gt;
         Goto unRemoveFromPath_done&lt;br /&gt;
 &lt;br /&gt;
   unRemoveFromPath_NT:&lt;br /&gt;
      StrLen $2 $0&lt;br /&gt;
      Call un.select_NT_profile&lt;br /&gt;
      Pop  $4&lt;br /&gt;
&lt;br /&gt;
      StrCmp $4 &amp;quot;current&amp;quot; un_read_path_NT_current&lt;br /&gt;
         ReadRegStr $1 ${NT_all_env} &amp;quot;PATH&amp;quot;&lt;br /&gt;
         Goto un_read_path_NT_resume&lt;br /&gt;
      un_read_path_NT_current:&lt;br /&gt;
         ReadRegStr $1 ${NT_current_env} &amp;quot;PATH&amp;quot;&lt;br /&gt;
      un_read_path_NT_resume:&lt;br /&gt;
&lt;br /&gt;
      Push $1&lt;br /&gt;
      Push $0&lt;br /&gt;
      Call un.StrStr ; Find $0 in $1&lt;br /&gt;
      Pop $0 ; pos of our dir&lt;br /&gt;
      IntCmp $0 -1 unRemoveFromPath_done&lt;br /&gt;
         ; else, it is in path&lt;br /&gt;
         StrCpy $3 $1 $0 ; $3 now has the part of the path before our dir&lt;br /&gt;
         IntOp $2 $2 + $0 ; $2 now contains the pos after our dir in the path (&#039;;&#039;)&lt;br /&gt;
         IntOp $2 $2 + 1 ; $2 now containts the pos after our dir and the semicolon.&lt;br /&gt;
         StrLen $0 $1&lt;br /&gt;
         StrCpy $1 $1 $0 $2&lt;br /&gt;
         StrCpy $3 &amp;quot;$3$1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
         StrCmp $4 &amp;quot;current&amp;quot; un_write_path_NT_current&lt;br /&gt;
            WriteRegExpandStr ${NT_all_env} &amp;quot;PATH&amp;quot; $3&lt;br /&gt;
            Goto un_write_path_NT_resume&lt;br /&gt;
         un_write_path_NT_current:&lt;br /&gt;
            WriteRegExpandStr ${NT_current_env} &amp;quot;PATH&amp;quot; $3&lt;br /&gt;
         un_write_path_NT_resume:&lt;br /&gt;
         SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
   unRemoveFromPath_done:&lt;br /&gt;
   Pop $4&lt;br /&gt;
   Pop $3&lt;br /&gt;
   Pop $2&lt;br /&gt;
   Pop $1&lt;br /&gt;
   Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&lt;br /&gt;
; Uninstall sutff&lt;br /&gt;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;====================================================&lt;br /&gt;
; StrStr - Finds a given string in another given string.&lt;br /&gt;
;               Returns -1 if not found and the pos if found.&lt;br /&gt;
;          Input: head of the stack - string to find&lt;br /&gt;
;                      second in the stack - string to find in&lt;br /&gt;
;          Output: head of the stack&lt;br /&gt;
;====================================================&lt;br /&gt;
Function un.StrStr&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0 ; $0 now have the string to find&lt;br /&gt;
  Push $1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Pop $1 ; $1 now have the string to find in&lt;br /&gt;
  Exch&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
&lt;br /&gt;
  StrCpy $2 -1&lt;br /&gt;
  StrLen $3 $0&lt;br /&gt;
  StrLen $4 $1&lt;br /&gt;
  IntOp $4 $4 - $3&lt;br /&gt;
&lt;br /&gt;
  unStrStr_loop:&lt;br /&gt;
    IntOp $2 $2 + 1&lt;br /&gt;
    IntCmp $2 $4 0 0 unStrStrReturn_notFound&lt;br /&gt;
    StrCpy $5 $1 $3 $2&lt;br /&gt;
    StrCmp $5 $0 unStrStr_done unStrStr_loop&lt;br /&gt;
&lt;br /&gt;
  unStrStrReturn_notFound:&lt;br /&gt;
    StrCpy $2 -1&lt;br /&gt;
&lt;br /&gt;
  unStrStr_done:&lt;br /&gt;
    Pop $5&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Exch $2&lt;br /&gt;
    Exch 2&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Pop $1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
;====================================================&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Path_manipulation_with_all_users/current_user_selection_in_run-time&amp;diff=15642</id>
		<title>Path manipulation with all users/current user selection in run-time</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Path_manipulation_with_all_users/current_user_selection_in_run-time&amp;diff=15642"/>
		<updated>2008-07-04T15:27:39Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: Functions obsoleted by EnvVarUpdate except for Windows 95, 98, and ME&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}} &lt;br /&gt;
&lt;br /&gt;
== EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
The AddToPath and un.RemoveFromPath functions in this page have been obsoleted by EnvVarUpdate. &lt;br /&gt;
These routines can corrupt the contents of the PATH variable if the path being removed happens to be a subset of another path. For example, if PATH contains &amp;quot;C:\Windows\system32\wbem&amp;quot; and you remove &amp;quot;C:\Windows\system32&amp;quot; the result is &amp;quot;\wbem&amp;quot;. They also do not prevent duplication of entries if the user runs the installer multiple times (and the installer code does check for duplicates). &lt;br /&gt;
&lt;br /&gt;
See [[Environmental_Variables:_append%2C_prepend%2C_and_remove_entries]] for more information.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Function Code ==&lt;br /&gt;
&lt;br /&gt;
[[http://nsis.sourceforge.net/Environmental_Variables:_append%2C_prepend%2C_and_remove_entries#Function_Code EnvVarUpdate function code]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Functions for Windows 95, 98, and ME ==&lt;br /&gt;
&lt;br /&gt;
{{PageAuthor|e-circ}}&lt;br /&gt;
&lt;br /&gt;
I adapted Path manipulation routines so you can select to change the path in the all users/current user profile in runtime.&lt;br /&gt;
&lt;br /&gt;
The original message:&lt;br /&gt;
&lt;br /&gt;
Here are two functions, one for adding directories to the search path of Windows and the other to remove them. These functions should work on every version of Windows including 95, 98, ME, NT, 2000, and XP.&lt;br /&gt;
&lt;br /&gt;
For Windows NT/2000/XP they will write to HKEY_CURRENT_USER\Environment\PATH. For 9x/ME they will write to the autoexec.bat file.&lt;br /&gt;
&lt;br /&gt;
Changes on 9x machines will take place after a reboot. These functions do not set the reboot flag so that should be done manually.&lt;br /&gt;
&lt;br /&gt;
These functions require NSIS 2.0b0 and above due to the usage of SendMessage with /TIMEOUT. It is possible to use it with earlier version of NSIS with a litte application I have created called RefreshEnv. It does exactly the same as SendMessage with /TIMEOUT. You can find it at this forum thread.&lt;br /&gt;
&lt;br /&gt;
Usage example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
Section &amp;quot;Add to path&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call AddToPath&lt;br /&gt;
SectionEnd&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
Section &amp;quot;uninstall&amp;quot;&lt;br /&gt;
  # ...&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call un.RemoveFromPath&lt;br /&gt;
  # ...&lt;br /&gt;
SectionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The functions in the flesh:&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
;----------------------------------------&lt;br /&gt;
; based upon a script of &amp;quot;Written by KiCHiK 2003-01-18 05:57:02&amp;quot;&lt;br /&gt;
;----------------------------------------&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
!verbose 4&lt;br /&gt;
;====================================================&lt;br /&gt;
; get_NT_environment &lt;br /&gt;
;     Returns: the selected environment&lt;br /&gt;
;     Output : head of the stack&lt;br /&gt;
;====================================================&lt;br /&gt;
!macro select_NT_profile UN&lt;br /&gt;
Function ${UN}select_NT_profile&lt;br /&gt;
   MessageBox MB_YESNO|MB_ICONQUESTION &amp;quot;Change the environment for all users?$\r$\nSaying no here will change the envrironment for the current user only.$\r$\n(Administrator permissions required for all users)&amp;quot; \&lt;br /&gt;
      IDNO environment_single&lt;br /&gt;
      DetailPrint &amp;quot;Selected environment for all users&amp;quot;&lt;br /&gt;
      Push &amp;quot;all&amp;quot;&lt;br /&gt;
      Return&lt;br /&gt;
   environment_single:&lt;br /&gt;
      DetailPrint &amp;quot;Selected environment for current user only.&amp;quot;&lt;br /&gt;
      Push &amp;quot;current&amp;quot;&lt;br /&gt;
      Return&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro select_NT_profile &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro select_NT_profile &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------------------------&lt;br /&gt;
!define NT_current_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
!define NT_all_env     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
;====================================================&lt;br /&gt;
; IsNT - Returns 1 if the current system is NT, 0&lt;br /&gt;
;        otherwise.&lt;br /&gt;
;     Output: head of the stack&lt;br /&gt;
;====================================================&lt;br /&gt;
!macro IsNT UN&lt;br /&gt;
Function ${UN}IsNT&lt;br /&gt;
  Push $0&lt;br /&gt;
  ReadRegStr $0 HKLM &amp;quot;SOFTWARE\Microsoft\Windows NT\CurrentVersion&amp;quot; CurrentVersion&lt;br /&gt;
  StrCmp $0 &amp;quot;&amp;quot; 0 IsNT_yes&lt;br /&gt;
  ; we are not NT.&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Push 0&lt;br /&gt;
  Return&lt;br /&gt;
&lt;br /&gt;
  IsNT_yes:&lt;br /&gt;
    ; NT!!!&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Push 1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro IsNT &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro IsNT &amp;quot;un.&amp;quot;&lt;br /&gt;
;====================================================&lt;br /&gt;
; AddToPath - Adds the given dir to the search path.&lt;br /&gt;
;        Input - head of the stack&lt;br /&gt;
;        Note - Win9x systems requires reboot&lt;br /&gt;
;====================================================&lt;br /&gt;
Function AddToPath&lt;br /&gt;
   Exch $0&lt;br /&gt;
   Push $1&lt;br /&gt;
   Push $2&lt;br /&gt;
  &lt;br /&gt;
   Call IsNT&lt;br /&gt;
   Pop $1&lt;br /&gt;
   StrCmp $1 1 AddToPath_NT&lt;br /&gt;
      ; Not on NT&lt;br /&gt;
      StrCpy $1 $WINDIR 2&lt;br /&gt;
      FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; a&lt;br /&gt;
      FileSeek $1 0 END&lt;br /&gt;
      GetFullPathName /SHORT $0 $0&lt;br /&gt;
      FileWrite $1 &amp;quot;$\r$\nSET PATH=%PATH%;$0$\r$\n&amp;quot;&lt;br /&gt;
      FileClose $1&lt;br /&gt;
      Goto AddToPath_done&lt;br /&gt;
&lt;br /&gt;
   AddToPath_NT:&lt;br /&gt;
      Push $4&lt;br /&gt;
      Call select_NT_profile&lt;br /&gt;
      Pop  $4&lt;br /&gt;
&lt;br /&gt;
      AddToPath_NT_selection_done:&lt;br /&gt;
      StrCmp $4 &amp;quot;current&amp;quot; read_path_NT_current&lt;br /&gt;
         ReadRegStr $1 ${NT_all_env} &amp;quot;PATH&amp;quot;&lt;br /&gt;
         Goto read_path_NT_resume&lt;br /&gt;
      read_path_NT_current:&lt;br /&gt;
         ReadRegStr $1 ${NT_current_env} &amp;quot;PATH&amp;quot;&lt;br /&gt;
      read_path_NT_resume:&lt;br /&gt;
      StrCpy $2 $0&lt;br /&gt;
      StrCmp $1 &amp;quot;&amp;quot; AddToPath_NTdoIt&lt;br /&gt;
         StrCpy $2 &amp;quot;$1;$0&amp;quot;&lt;br /&gt;
      AddToPath_NTdoIt:&lt;br /&gt;
         StrCmp $4 &amp;quot;current&amp;quot; write_path_NT_current&lt;br /&gt;
            ClearErrors&lt;br /&gt;
            WriteRegExpandStr ${NT_all_env} &amp;quot;PATH&amp;quot; $2&lt;br /&gt;
            IfErrors 0 write_path_NT_resume&lt;br /&gt;
            MessageBox MB_YESNO|MB_ICONQUESTION &amp;quot;The path could not be set for all users$\r$\nShould I try for the current user?&amp;quot; \&lt;br /&gt;
               IDNO write_path_NT_failed&lt;br /&gt;
            ; change selection&lt;br /&gt;
            StrCpy $4 &amp;quot;current&amp;quot;&lt;br /&gt;
            Goto AddToPath_NT_selection_done&lt;br /&gt;
         write_path_NT_current:&lt;br /&gt;
            ClearErrors&lt;br /&gt;
            WriteRegExpandStr ${NT_current_env} &amp;quot;PATH&amp;quot; $2&lt;br /&gt;
            IfErrors 0 write_path_NT_resume&lt;br /&gt;
            MessageBox MB_OK|MB_ICONINFORMATION &amp;quot;The path could not be set for the current user.&amp;quot;&lt;br /&gt;
            Goto write_path_NT_failed&lt;br /&gt;
         write_path_NT_resume:&lt;br /&gt;
         SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
         DetailPrint &amp;quot;added path for user ($4), $0&amp;quot;&lt;br /&gt;
         write_path_NT_failed:&lt;br /&gt;
      &lt;br /&gt;
      Pop $4&lt;br /&gt;
   AddToPath_done:&lt;br /&gt;
   Pop $2&lt;br /&gt;
   Pop $1&lt;br /&gt;
   Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
;====================================================&lt;br /&gt;
; RemoveFromPath - Remove a given dir from the path&lt;br /&gt;
;     Input: head of the stack&lt;br /&gt;
;====================================================&lt;br /&gt;
Function un.RemoveFromPath&lt;br /&gt;
   Exch $0&lt;br /&gt;
   Push $1&lt;br /&gt;
   Push $2&lt;br /&gt;
   Push $3&lt;br /&gt;
   Push $4&lt;br /&gt;
   &lt;br /&gt;
   Call un.IsNT&lt;br /&gt;
   Pop $1&lt;br /&gt;
   StrCmp $1 1 unRemoveFromPath_NT&lt;br /&gt;
      ; Not on NT&lt;br /&gt;
      StrCpy $1 $WINDIR 2&lt;br /&gt;
      FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; r&lt;br /&gt;
      GetTempFileName $4&lt;br /&gt;
      FileOpen $2 $4 w&lt;br /&gt;
      GetFullPathName /SHORT $0 $0&lt;br /&gt;
      StrCpy $0 &amp;quot;SET PATH=%PATH%;$0&amp;quot;&lt;br /&gt;
      SetRebootFlag true&lt;br /&gt;
      Goto unRemoveFromPath_dosLoop&lt;br /&gt;
     &lt;br /&gt;
      unRemoveFromPath_dosLoop:&lt;br /&gt;
         FileRead $1 $3&lt;br /&gt;
         StrCmp $3 &amp;quot;$0$\r$\n&amp;quot; unRemoveFromPath_dosLoop&lt;br /&gt;
         StrCmp $3 &amp;quot;$0$\n&amp;quot; unRemoveFromPath_dosLoop&lt;br /&gt;
         StrCmp $3 &amp;quot;$0&amp;quot; unRemoveFromPath_dosLoop&lt;br /&gt;
         StrCmp $3 &amp;quot;&amp;quot; unRemoveFromPath_dosLoopEnd&lt;br /&gt;
         FileWrite $2 $3&lt;br /&gt;
         Goto unRemoveFromPath_dosLoop&lt;br /&gt;
&lt;br /&gt;
      unRemoveFromPath_dosLoopEnd:&lt;br /&gt;
         FileClose $2&lt;br /&gt;
         FileClose $1&lt;br /&gt;
         StrCpy $1 $WINDIR 2&lt;br /&gt;
         Delete &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
         CopyFiles /SILENT $4 &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
         Delete $4&lt;br /&gt;
         Goto unRemoveFromPath_done&lt;br /&gt;
 &lt;br /&gt;
   unRemoveFromPath_NT:&lt;br /&gt;
      StrLen $2 $0&lt;br /&gt;
      Call un.select_NT_profile&lt;br /&gt;
      Pop  $4&lt;br /&gt;
&lt;br /&gt;
      StrCmp $4 &amp;quot;current&amp;quot; un_read_path_NT_current&lt;br /&gt;
         ReadRegStr $1 ${NT_all_env} &amp;quot;PATH&amp;quot;&lt;br /&gt;
         Goto un_read_path_NT_resume&lt;br /&gt;
      un_read_path_NT_current:&lt;br /&gt;
         ReadRegStr $1 ${NT_current_env} &amp;quot;PATH&amp;quot;&lt;br /&gt;
      un_read_path_NT_resume:&lt;br /&gt;
&lt;br /&gt;
      Push $1&lt;br /&gt;
      Push $0&lt;br /&gt;
      Call un.StrStr ; Find $0 in $1&lt;br /&gt;
      Pop $0 ; pos of our dir&lt;br /&gt;
      IntCmp $0 -1 unRemoveFromPath_done&lt;br /&gt;
         ; else, it is in path&lt;br /&gt;
         StrCpy $3 $1 $0 ; $3 now has the part of the path before our dir&lt;br /&gt;
         IntOp $2 $2 + $0 ; $2 now contains the pos after our dir in the path (&#039;;&#039;)&lt;br /&gt;
         IntOp $2 $2 + 1 ; $2 now containts the pos after our dir and the semicolon.&lt;br /&gt;
         StrLen $0 $1&lt;br /&gt;
         StrCpy $1 $1 $0 $2&lt;br /&gt;
         StrCpy $3 &amp;quot;$3$1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
         StrCmp $4 &amp;quot;current&amp;quot; un_write_path_NT_current&lt;br /&gt;
            WriteRegExpandStr ${NT_all_env} &amp;quot;PATH&amp;quot; $3&lt;br /&gt;
            Goto un_write_path_NT_resume&lt;br /&gt;
         un_write_path_NT_current:&lt;br /&gt;
            WriteRegExpandStr ${NT_current_env} &amp;quot;PATH&amp;quot; $3&lt;br /&gt;
         un_write_path_NT_resume:&lt;br /&gt;
         SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
   unRemoveFromPath_done:&lt;br /&gt;
   Pop $4&lt;br /&gt;
   Pop $3&lt;br /&gt;
   Pop $2&lt;br /&gt;
   Pop $1&lt;br /&gt;
   Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&lt;br /&gt;
; Uninstall sutff&lt;br /&gt;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;====================================================&lt;br /&gt;
; StrStr - Finds a given string in another given string.&lt;br /&gt;
;               Returns -1 if not found and the pos if found.&lt;br /&gt;
;          Input: head of the stack - string to find&lt;br /&gt;
;                      second in the stack - string to find in&lt;br /&gt;
;          Output: head of the stack&lt;br /&gt;
;====================================================&lt;br /&gt;
Function un.StrStr&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0 ; $0 now have the string to find&lt;br /&gt;
  Push $1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Pop $1 ; $1 now have the string to find in&lt;br /&gt;
  Exch&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
&lt;br /&gt;
  StrCpy $2 -1&lt;br /&gt;
  StrLen $3 $0&lt;br /&gt;
  StrLen $4 $1&lt;br /&gt;
  IntOp $4 $4 - $3&lt;br /&gt;
&lt;br /&gt;
  unStrStr_loop:&lt;br /&gt;
    IntOp $2 $2 + 1&lt;br /&gt;
    IntCmp $2 $4 0 0 unStrStrReturn_notFound&lt;br /&gt;
    StrCpy $5 $1 $3 $2&lt;br /&gt;
    StrCmp $5 $0 unStrStr_done unStrStr_loop&lt;br /&gt;
&lt;br /&gt;
  unStrStrReturn_notFound:&lt;br /&gt;
    StrCpy $2 -1&lt;br /&gt;
&lt;br /&gt;
  unStrStr_done:&lt;br /&gt;
    Pop $5&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Exch $2&lt;br /&gt;
    Exch 2&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Pop $1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
;====================================================&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Path_Manipulation&amp;diff=15641</id>
		<title>Path Manipulation</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Path_Manipulation&amp;diff=15641"/>
		<updated>2008-07-04T15:04:26Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}} &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname from the PATH environmental variable in either the &amp;quot;all users&amp;quot; (HKLM) or the &amp;quot;current user&amp;quot; (HKCU) section of the registry. &lt;br /&gt;
&lt;br /&gt;
Duplicates entries, leading and trailing spaces around each entry, and duplicate semicolons are removed from the contents of PATH before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname).&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
=== Syntax ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;Pathname&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot; &lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;Pathname&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
:; ResultVar&lt;br /&gt;
:: Updated contents PATH returned by the function&lt;br /&gt;
&lt;br /&gt;
:; EnvVarName&lt;br /&gt;
:: &amp;quot;PATH&amp;quot; &lt;br /&gt;
&lt;br /&gt;
:; Action&lt;br /&gt;
:: &amp;quot;A&amp;quot; = Append&lt;br /&gt;
:: &amp;quot;P&amp;quot; = Prepend&lt;br /&gt;
:: &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
:; RegLoc&lt;br /&gt;
:: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
:: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
:; Pathname&lt;br /&gt;
:: Pathname to add to or remove from the contents of PATH (e.g., &amp;quot;C:\MyApp&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\Windows Resource Kits\Tools&amp;quot;  &lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;%WinDir%\System32&amp;quot;  &lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v1.0&amp;quot;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v2.0&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v1.0&amp;quot;   &lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v2.0&amp;quot;   &lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dependencies == &lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;EnvVarUpdate&#039;&#039;&#039; (available at  [[Environmental_Variables:_append%2C_prepend%2C_and_remove_entries]])&lt;br /&gt;
* &#039;&#039;&#039;StrTok, StrContains, and StrReplace:&#039;&#039;&#039;  Included in the EnvVarUpdate function code &lt;br /&gt;
* &#039;&#039;&#039;LogicLib header file:&#039;&#039;&#039; &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
&lt;br /&gt;
* Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
* Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr  &lt;br /&gt;
* Diego Pedroso (deguix) for StrTok&lt;br /&gt;
* Kevin English (kenglish_hi)for StrContains&lt;br /&gt;
* Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry (dandaman32) for StrReplace&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Function Code ==&lt;br /&gt;
&lt;br /&gt;
[[http://nsis.sourceforge.net/Environmental_Variables:_append%2C_prepend%2C_and_remove_entries#Function_Code EnvVarUpdate function code]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Functions for Windows 95, 98, and ME ==&lt;br /&gt;
{{PageAuthor|KiCHiK}}&lt;br /&gt;
The following routines, AddToPath, un.RemoveFromPath, AddToEnvVar, and un.RemoveFromEnvVar are provided for Windows 95, 98, or ME in that they support the update of the PATH variable within the autoexec.bat file.  &lt;br /&gt;
&lt;br /&gt;
NOTE: These routines can corrupt the contents of the PATH variable if the path being removed happens to be a subset of another path.   For example, if PATH contains &amp;quot;C:\Windows\system32\wbem&amp;quot; and you remove &amp;quot;C:\Windows\system32&amp;quot; the result is &amp;quot;\wbem&amp;quot;.  They also do not prevent duplication of entries if the user runs the installer multiple times.    &lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Here are four functions, two for adding to and removing directories from the search path (i.e. PATH environment variable) of Windows and two more for adding to and removing directories from a user defined environment variable such as INCLUDE or LIB etc. These functions should work on every version of Windows including 95, 98, ME, NT, 2000, and XP.&lt;br /&gt;
&lt;br /&gt;
For Windows NT/2000/XP they will write to HKEY_CURRENT_USER\Environment\PATH. For 9x/ME they will write to the autoexec.bat file.&lt;br /&gt;
&lt;br /&gt;
Changes on 9x machines will take place after a reboot. These functions set the reboot flag if the path variable was changed on 9x.&lt;br /&gt;
&lt;br /&gt;
These functions require NSIS 2.0b0 and above due to the usage of SendMessage with /TIMEOUT. It is possible to use it with earlier versions of NSIS with a little application I have created called RefreshEnv. It does exactly the same as SendMessage with /TIMEOUT. You can find it at [http://forums.winamp.com/showthread.php?s=&amp;amp;threadid=77904&amp;amp;highlight=refreshenv this forum thread].&lt;br /&gt;
&lt;br /&gt;
The directory added to the path must exist prior to calling this function.&lt;br /&gt;
&lt;br /&gt;
=== Usage Example ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;Section &amp;quot;Add to path&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call AddToPath&lt;br /&gt;
&lt;br /&gt;
  Push &amp;quot;LIB&amp;quot;&lt;br /&gt;
  Push &amp;quot;c:\Mylibrary\lib&amp;quot;&lt;br /&gt;
  Call AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
  ;likewise AddToPath could be&lt;br /&gt;
  Push &amp;quot;PATH&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
SectionEnd&lt;br /&gt;
&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Section &amp;quot;uninstall&amp;quot;&lt;br /&gt;
  # ...&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call un.RemoveFromPath&lt;br /&gt;
  # ...&lt;br /&gt;
  Push &amp;quot;LIB&amp;quot;&lt;br /&gt;
  Push &amp;quot;c:\Mylibrary\lib&amp;quot;&lt;br /&gt;
  Call un.RemoveFromEnvVar&lt;br /&gt;
&lt;br /&gt;
  ;Likewise RemoveFromPath could be&lt;br /&gt;
  Push &amp;quot;PATH&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call un.RemoveFromEnvVar&lt;br /&gt;
  &lt;br /&gt;
SectionEnd&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Functions ===&lt;br /&gt;
The functions in the flesh:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;!ifndef _AddToPath_nsh&lt;br /&gt;
!define _AddToPath_nsh&lt;br /&gt;
&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
!verbose 4&lt;br /&gt;
&lt;br /&gt;
!ifndef WriteEnvStr_RegKey&lt;br /&gt;
  !ifdef ALL_USERS&lt;br /&gt;
    !define WriteEnvStr_RegKey \&lt;br /&gt;
       &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
  !else&lt;br /&gt;
    !define WriteEnvStr_RegKey &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
  !endif&lt;br /&gt;
!endif&lt;br /&gt;
&lt;br /&gt;
; AddToPath - Adds the given dir to the search path.&lt;br /&gt;
;        Input - head of the stack&lt;br /&gt;
;        Note - Win9x systems requires reboot&lt;br /&gt;
&lt;br /&gt;
Function AddToPath&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Push $1&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
&lt;br /&gt;
  # don&#039;t add if the path doesn&#039;t exist&lt;br /&gt;
  IfFileExists &amp;quot;$0\*.*&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  ReadEnvStr $1 PATH&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$0;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$0\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  GetFullPathName /SHORT $3 $0&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$3;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$3\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  Call IsNT&lt;br /&gt;
  Pop $1&lt;br /&gt;
  StrCmp $1 1 AddToPath_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $1 $WINDIR 2&lt;br /&gt;
    FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; a&lt;br /&gt;
    FileSeek $1 -1 END&lt;br /&gt;
    FileReadByte $1 $2&lt;br /&gt;
    IntCmp $2 26 0 +2 +2 # DOS EOF&lt;br /&gt;
      FileSeek $1 -1 END # write over EOF&lt;br /&gt;
    FileWrite $1 &amp;quot;$\r$\nSET PATH=%PATH%;$3$\r$\n&amp;quot;&lt;br /&gt;
    FileClose $1&lt;br /&gt;
    SetRebootFlag true&lt;br /&gt;
    Goto AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  AddToPath_NT:&lt;br /&gt;
    ReadRegStr $1 ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot;&lt;br /&gt;
    StrCmp $1 &amp;quot;&amp;quot; AddToPath_NTdoIt&lt;br /&gt;
      Push $1&lt;br /&gt;
      Call Trim&lt;br /&gt;
      Pop $1&lt;br /&gt;
      StrCpy $0 &amp;quot;$1;$0&amp;quot;&lt;br /&gt;
    AddToPath_NTdoIt:&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot; $0&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  AddToPath_done:&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
; RemoveFromPath - Remove a given dir from the path&lt;br /&gt;
;     Input: head of the stack&lt;br /&gt;
&lt;br /&gt;
Function un.RemoveFromPath&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Push $1&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
&lt;br /&gt;
  IntFmt $6 &amp;quot;%c&amp;quot; 26 # DOS EOF&lt;br /&gt;
&lt;br /&gt;
  Call un.IsNT&lt;br /&gt;
  Pop $1&lt;br /&gt;
  StrCmp $1 1 unRemoveFromPath_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $1 $WINDIR 2&lt;br /&gt;
    FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; r&lt;br /&gt;
    GetTempFileName $4&lt;br /&gt;
    FileOpen $2 $4 w&lt;br /&gt;
    GetFullPathName /SHORT $0 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;SET PATH=%PATH%;$0&amp;quot;&lt;br /&gt;
    Goto unRemoveFromPath_dosLoop&lt;br /&gt;
&lt;br /&gt;
    unRemoveFromPath_dosLoop:&lt;br /&gt;
      FileRead $1 $3&lt;br /&gt;
      StrCpy $5 $3 1 -1 # read last char&lt;br /&gt;
      StrCmp $5 $6 0 +2 # if DOS EOF&lt;br /&gt;
        StrCpy $3 $3 -1 # remove DOS EOF so we can compare&lt;br /&gt;
      StrCmp $3 &amp;quot;$0$\r$\n&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;$0$\n&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;$0&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;&amp;quot; unRemoveFromPath_dosLoopEnd&lt;br /&gt;
      FileWrite $2 $3&lt;br /&gt;
      Goto unRemoveFromPath_dosLoop&lt;br /&gt;
      unRemoveFromPath_dosLoopRemoveLine:&lt;br /&gt;
        SetRebootFlag true&lt;br /&gt;
        Goto unRemoveFromPath_dosLoop&lt;br /&gt;
&lt;br /&gt;
    unRemoveFromPath_dosLoopEnd:&lt;br /&gt;
      FileClose $2&lt;br /&gt;
      FileClose $1&lt;br /&gt;
      StrCpy $1 $WINDIR 2&lt;br /&gt;
      Delete &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
      CopyFiles /SILENT $4 &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
      Delete $4&lt;br /&gt;
      Goto unRemoveFromPath_done&lt;br /&gt;
&lt;br /&gt;
  unRemoveFromPath_NT:&lt;br /&gt;
    ReadRegStr $1 ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot;&lt;br /&gt;
    StrCpy $5 $1 1 -1 # copy last char&lt;br /&gt;
    StrCmp $5 &amp;quot;;&amp;quot; +2 # if last char != ;&lt;br /&gt;
      StrCpy $1 &amp;quot;$1;&amp;quot; # append ;&lt;br /&gt;
    Push $1&lt;br /&gt;
    Push &amp;quot;$0;&amp;quot;&lt;br /&gt;
    Call un.StrStr ; Find `$0;` in $1&lt;br /&gt;
    Pop $2 ; pos of our dir&lt;br /&gt;
    StrCmp $2 &amp;quot;&amp;quot; unRemoveFromPath_done&lt;br /&gt;
      ; else, it is in path&lt;br /&gt;
      # $0 - path to add&lt;br /&gt;
      # $1 - path var&lt;br /&gt;
      StrLen $3 &amp;quot;$0;&amp;quot;&lt;br /&gt;
      StrLen $4 $2&lt;br /&gt;
      StrCpy $5 $1 -$4 # $5 is now the part before the path to remove&lt;br /&gt;
      StrCpy $6 $2 &amp;quot;&amp;quot; $3 # $6 is now the part after the path to remove&lt;br /&gt;
      StrCpy $3 $5$6&lt;br /&gt;
&lt;br /&gt;
      StrCpy $5 $3 1 -1 # copy last char&lt;br /&gt;
      StrCmp $5 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
        StrCpy $3 $3 -1 # remove last char&lt;br /&gt;
&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot; $3&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  unRemoveFromPath_done:&lt;br /&gt;
    Pop $6&lt;br /&gt;
    Pop $5&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; AddToEnvVar - Adds the given value to the given environment var&lt;br /&gt;
;        Input - head of the stack $0 environement variable $1=value to add&lt;br /&gt;
;        Note - Win9x systems requires reboot&lt;br /&gt;
 &lt;br /&gt;
Function AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
  Exch $1 ; $1 has environment variable value&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $0 ; $0 has environment variable name&lt;br /&gt;
&lt;br /&gt;
  DetailPrint &amp;quot;Adding $1 to $0&amp;quot;&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
  ReadEnvStr $2 $0&lt;br /&gt;
  Push &amp;quot;$2;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $3&lt;br /&gt;
  StrCmp $3 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToEnvVar_done&lt;br /&gt;
&lt;br /&gt;
  Push &amp;quot;$2;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$1\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $3&lt;br /&gt;
  StrCmp $3 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToEnvVar_done&lt;br /&gt;
  &lt;br /&gt;
 &lt;br /&gt;
  Call IsNT&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 1 AddToEnvVar_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $2 $WINDIR 2&lt;br /&gt;
    FileOpen $2 &amp;quot;$2\autoexec.bat&amp;quot; a&lt;br /&gt;
    FileSeek $2 -1 END&lt;br /&gt;
    FileReadByte $2 $3&lt;br /&gt;
    IntCmp $3 26 0 +2 +2 # DOS EOF&lt;br /&gt;
      FileSeek $2 -1 END # write over EOF&lt;br /&gt;
    FileWrite $2 &amp;quot;$\r$\nSET $0=%$0%;$4$\r$\n&amp;quot;&lt;br /&gt;
    FileClose $2&lt;br /&gt;
    SetRebootFlag true&lt;br /&gt;
    Goto AddToEnvVar_done&lt;br /&gt;
 &lt;br /&gt;
  AddToEnvVar_NT:&lt;br /&gt;
    ReadRegStr $2 ${WriteEnvStr_RegKey} $0&lt;br /&gt;
    StrCpy $3 $2 1 -1 # copy last char&lt;br /&gt;
    StrCmp $3 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
      StrCpy $2 $2 -1 # remove last char&lt;br /&gt;
    StrCmp $2 &amp;quot;&amp;quot; AddToEnvVar_NTdoIt&lt;br /&gt;
      StrCpy $1 &amp;quot;$2;$1&amp;quot;&lt;br /&gt;
    AddToEnvVar_NTdoIt:&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $1&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  AddToEnvVar_done:&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Pop $1&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
 &lt;br /&gt;
; RemoveFromEnvVar - Remove a given value from a environment var&lt;br /&gt;
;     Input: head of the stack&lt;br /&gt;
 &lt;br /&gt;
Function un.RemoveFromEnvVar&lt;br /&gt;
&lt;br /&gt;
  Exch $1 ; $1 has environment variable value&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $0 ; $0 has environment variable name&lt;br /&gt;
&lt;br /&gt;
  DetailPrint &amp;quot;Removing $1 from $0&amp;quot;&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
 &lt;br /&gt;
  IntFmt $7 &amp;quot;%c&amp;quot; 26 # DOS EOF&lt;br /&gt;
 &lt;br /&gt;
  Call un.IsNT&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 1 unRemoveFromEnvVar_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $2 $WINDIR 2&lt;br /&gt;
    FileOpen $2 &amp;quot;$2\autoexec.bat&amp;quot; r&lt;br /&gt;
    GetTempFileName $5&lt;br /&gt;
    FileOpen $3 $5 w&lt;br /&gt;
    GetFullPathName /SHORT $1 $1&lt;br /&gt;
    StrCpy $1 &amp;quot;SET $0=%$0%;$1&amp;quot;&lt;br /&gt;
    Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
 &lt;br /&gt;
    unRemoveFromEnvVar_dosLoop:&lt;br /&gt;
      FileRead $2 $4&lt;br /&gt;
      StrCpy $6 $4 1 -1 # read last char&lt;br /&gt;
      StrCmp $6 $7 0 +2 # if DOS EOF&lt;br /&gt;
        StrCpy $4 $4 -1 # remove DOS EOF so we can compare&lt;br /&gt;
      StrCmp $4 &amp;quot;$1$\r$\n&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;$1$\n&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;$1&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;&amp;quot; unRemoveFromEnvVar_dosLoopEnd&lt;br /&gt;
      FileWrite $3 $4&lt;br /&gt;
      Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
      unRemoveFromEnvVar_dosLoopRemoveLine:&lt;br /&gt;
        SetRebootFlag true&lt;br /&gt;
        Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
 &lt;br /&gt;
    unRemoveFromEnvVar_dosLoopEnd:&lt;br /&gt;
      FileClose $3&lt;br /&gt;
      FileClose $2&lt;br /&gt;
      StrCpy $2 $WINDIR 2&lt;br /&gt;
      Delete &amp;quot;$2\autoexec.bat&amp;quot;&lt;br /&gt;
      CopyFiles /SILENT $5 &amp;quot;$2\autoexec.bat&amp;quot;&lt;br /&gt;
      Delete $5&lt;br /&gt;
      Goto unRemoveFromEnvVar_done&lt;br /&gt;
 &lt;br /&gt;
  unRemoveFromEnvVar_NT:&lt;br /&gt;
    ReadRegStr $2 ${WriteEnvStr_RegKey} $0&lt;br /&gt;
    StrCpy $6 $2 1 -1 # copy last char&lt;br /&gt;
    StrCmp $6 &amp;quot;;&amp;quot; +2 # if last char != ;&lt;br /&gt;
      StrCpy $2 &amp;quot;$2;&amp;quot; # append ;&lt;br /&gt;
    Push $2&lt;br /&gt;
    Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
    Call un.StrStr ; Find `$1;` in $2&lt;br /&gt;
    Pop $3 ; pos of our dir&lt;br /&gt;
    StrCmp $3 &amp;quot;&amp;quot; unRemoveFromEnvVar_done&lt;br /&gt;
      ; else, it is in path&lt;br /&gt;
      # $1 - path to add&lt;br /&gt;
      # $2 - path var&lt;br /&gt;
      StrLen $4 &amp;quot;$1;&amp;quot;&lt;br /&gt;
      StrLen $5 $3&lt;br /&gt;
      StrCpy $6 $2 -$5 # $6 is now the part before the path to remove&lt;br /&gt;
      StrCpy $7 $3 &amp;quot;&amp;quot; $4 # $7 is now the part after the path to remove&lt;br /&gt;
      StrCpy $4 $6$7&lt;br /&gt;
 &lt;br /&gt;
      StrCpy $6 $4 1 -1 # copy last char&lt;br /&gt;
      StrCmp $6 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
      StrCpy $4 $4 -1 # remove last char&lt;br /&gt;
 &lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $4&lt;br /&gt;
&lt;br /&gt;
      ; delete reg value if null&lt;br /&gt;
      StrCmp $4 &amp;quot;&amp;quot; 0 +2 # if null delete reg&lt;br /&gt;
      DeleteRegValue ${WriteEnvStr_RegKey} $0&lt;br /&gt;
&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
 &lt;br /&gt;
  unRemoveFromEnvVar_done:&lt;br /&gt;
    Pop $7&lt;br /&gt;
    Pop $6&lt;br /&gt;
    Pop $5&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
!ifndef IsNT_KiCHiK&lt;br /&gt;
!define IsNT_KiCHiK&lt;br /&gt;
&lt;br /&gt;
###########################################&lt;br /&gt;
#            Utility Functions            #&lt;br /&gt;
###########################################&lt;br /&gt;
&lt;br /&gt;
; IsNT&lt;br /&gt;
; no input&lt;br /&gt;
; output, top of the stack = 1 if NT or 0 if not&lt;br /&gt;
;&lt;br /&gt;
; Usage:&lt;br /&gt;
;   Call IsNT&lt;br /&gt;
;   Pop $R0&lt;br /&gt;
;  ($R0 at this point is 1 or 0)&lt;br /&gt;
&lt;br /&gt;
!macro IsNT un&lt;br /&gt;
Function ${un}IsNT&lt;br /&gt;
  Push $0&lt;br /&gt;
  ReadRegStr $0 HKLM &amp;quot;SOFTWARE\Microsoft\Windows NT\CurrentVersion&amp;quot; CurrentVersion&lt;br /&gt;
  StrCmp $0 &amp;quot;&amp;quot; 0 IsNT_yes&lt;br /&gt;
  ; we are not NT.&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Push 0&lt;br /&gt;
  Return&lt;br /&gt;
&lt;br /&gt;
  IsNT_yes:&lt;br /&gt;
    ; NT!!!&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Push 1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro IsNT &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro IsNT &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!endif ; IsNT_KiCHiK&lt;br /&gt;
&lt;br /&gt;
; StrStr&lt;br /&gt;
; input, top of stack = string to search for&lt;br /&gt;
;        top of stack-1 = string to search in&lt;br /&gt;
; output, top of stack (replaces with the portion of the string remaining)&lt;br /&gt;
; modifies no other variables.&lt;br /&gt;
;&lt;br /&gt;
; Usage:&lt;br /&gt;
;   Push &amp;quot;this is a long ass string&amp;quot;&lt;br /&gt;
;   Push &amp;quot;ass&amp;quot;&lt;br /&gt;
;   Call StrStr&lt;br /&gt;
;   Pop $R0&lt;br /&gt;
;  ($R0 at this point is &amp;quot;ass string&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
!macro StrStr un&lt;br /&gt;
Function ${un}StrStr&lt;br /&gt;
Exch $R1 ; st=haystack,old$R1, $R1=needle&lt;br /&gt;
  Exch    ; st=old$R1,haystack&lt;br /&gt;
  Exch $R2 ; st=old$R1,old$R2, $R2=haystack&lt;br /&gt;
  Push $R3&lt;br /&gt;
  Push $R4&lt;br /&gt;
  Push $R5&lt;br /&gt;
  StrLen $R3 $R1&lt;br /&gt;
  StrCpy $R4 0&lt;br /&gt;
  ; $R1=needle&lt;br /&gt;
  ; $R2=haystack&lt;br /&gt;
  ; $R3=len(needle)&lt;br /&gt;
  ; $R4=cnt&lt;br /&gt;
  ; $R5=tmp&lt;br /&gt;
  loop:&lt;br /&gt;
    StrCpy $R5 $R2 $R3 $R4&lt;br /&gt;
    StrCmp $R5 $R1 done&lt;br /&gt;
    StrCmp $R5 &amp;quot;&amp;quot; done&lt;br /&gt;
    IntOp $R4 $R4 + 1&lt;br /&gt;
    Goto loop&lt;br /&gt;
done:&lt;br /&gt;
  StrCpy $R1 $R2 &amp;quot;&amp;quot; $R4&lt;br /&gt;
  Pop $R5&lt;br /&gt;
  Pop $R4&lt;br /&gt;
  Pop $R3&lt;br /&gt;
  Pop $R2&lt;br /&gt;
  Exch $R1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrStr &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrStr &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!endif ; _AddToPath_nsh&lt;br /&gt;
&lt;br /&gt;
Function Trim ; Added by Pelaca&lt;br /&gt;
	Exch $R1&lt;br /&gt;
	Push $R2&lt;br /&gt;
Loop:&lt;br /&gt;
	StrCpy $R2 &amp;quot;$R1&amp;quot; 1 -1&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot; &amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;$\n&amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;$\r&amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;;&amp;quot; RTrim&lt;br /&gt;
	GoTo Done&lt;br /&gt;
RTrim:	&lt;br /&gt;
	StrCpy $R1 &amp;quot;$R1&amp;quot; -1&lt;br /&gt;
	Goto Loop&lt;br /&gt;
Done:&lt;br /&gt;
	Pop $R2&lt;br /&gt;
	Exch $R1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15640</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15640"/>
		<updated>2008-07-03T16:13:22Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
;Function - EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
;Version 1.0&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. The variable can be updated in either the &amp;quot;all users&amp;quot; section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
Duplicates entries, leading and trailing spaces around each entry, and duplicate semicolons are permanently removed from the contents of the variable before performing the requested operation.  This step prevents the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). &lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. &lt;br /&gt;
&lt;br /&gt;
The updated contents of the variable returned in ResultVar might be useful for displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
;Design&lt;br /&gt;
&lt;br /&gt;
# Read the contents of EnvVarName from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# Remove all instances of the target path/string regardless of the operation because this not only eliminates duplicate entries, it also allows for the search order of the target entry to be changed from first to last and vice versa.&lt;br /&gt;
# If Action is &amp;quot;R&amp;quot; (remove), skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated variable to RegLoc even if the Action is &amp;quot;R&amp;quot; or the target is not found because this allows for the elimination of duplicate semicolons, spaces around semicolons, spaces preceding the first entry, and spaces following the last entry.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
=== Syntax ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
:; ResultVar&lt;br /&gt;
::Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
:; EnvVarName&lt;br /&gt;
:: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
:; Action&lt;br /&gt;
:: &amp;quot;A&amp;quot; = Append&lt;br /&gt;
:: &amp;quot;P&amp;quot; = Prepend&lt;br /&gt;
:: &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
:; RegLoc&lt;br /&gt;
:: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
:: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
:; PathString&lt;br /&gt;
:: A pathname or string to add to or remove from the contents of EnvVarName (e.g., &amp;quot;C:\MyApp&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
==== Installer Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\Windows Resource Kits\Tools&amp;quot; ; Append  &lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;%WinDir%\System32&amp;quot;                            ; Prepend     &lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;                                     ; Remove&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v1.0&amp;quot;  ; Remove path of old rev&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v2.0&amp;quot;  ; Append the new one&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Uninstaller Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;          &lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v2.0&amp;quot;      ; Remove path of latest rev &lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v1.0&amp;quot;      ; Restore path of previous rev&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
&lt;br /&gt;
* Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
* Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr  &lt;br /&gt;
* Diego Pedroso (deguix) for StrTok&lt;br /&gt;
* Kevin English (kenglish_hi)for StrContains&lt;br /&gt;
* Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry (dandaman32) for StrReplace&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Function Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   &lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
; NOTE: Do not substitute &#039;StrReplaceV4&#039; for this function. It will fail due to the way I call it.&lt;br /&gt;
;&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15639</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15639"/>
		<updated>2008-07-03T16:00:39Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Credits */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. The variable can be updated in either the &amp;quot;all users&amp;quot; section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
Duplicates entries, leading and trailing spaces around each entry, and duplicate semicolons are permanently removed from the contents of the variable before performing the requested operation.  This step prevents the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). &lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. &lt;br /&gt;
&lt;br /&gt;
The updated contents of the variable returned in ResultVar might be useful for displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read the contents of EnvVarName from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# Remove all instances of the target path/string regardless of the operation because this not only eliminates duplicate entries, it also allows for the search order of the target entry to be changed from first to last and vice versa.&lt;br /&gt;
# If Action is &amp;quot;R&amp;quot; (remove), skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated variable to RegLoc even if the Action is &amp;quot;R&amp;quot; or the target is not found because this allows for the elimination of duplicate semicolons, spaces around semicolons, spaces preceding the first entry, and spaces following the last entry.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
==== Syntax ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
:; ResultVar&lt;br /&gt;
::Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
:; EnvVarName&lt;br /&gt;
:: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
:; Action&lt;br /&gt;
:: &amp;quot;A&amp;quot; = Append&lt;br /&gt;
:: &amp;quot;P&amp;quot; = Prepend&lt;br /&gt;
:: &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
:; RegLoc&lt;br /&gt;
:: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
:: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
:; PathString&lt;br /&gt;
:: A pathname or string to add to or remove from the contents of EnvVarName (e.g., &amp;quot;C:\MyApp&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
===== Installer Examples =====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\Windows Resource Kits\Tools&amp;quot; ; Append  &lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;%WinDir%\System32&amp;quot;                            ; Prepend     &lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;                                     ; Remove&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v1.0&amp;quot;  ; Remove path of old rev&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v2.0&amp;quot;  ; Append the new one&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Uninstaller Examples =====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;          &lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v2.0&amp;quot;      ; Remove path of latest rev &lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v1.0&amp;quot;      ; Restore path of previous rev&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
* Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
* Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr  &lt;br /&gt;
* Diego Pedroso (deguix) for StrTok&lt;br /&gt;
* Kevin English (kenglish_hi)for StrContains&lt;br /&gt;
* Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry (dandaman32) for StrReplace&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   &lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
; NOTE: Do not substitute &#039;StrReplaceV4&#039; for this function. It will fail due to the way I call it.&lt;br /&gt;
;&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15638</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15638"/>
		<updated>2008-07-03T15:52:32Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Examples */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. The variable can be updated in either the &amp;quot;all users&amp;quot; section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
Duplicates entries, leading and trailing spaces around each entry, and duplicate semicolons are permanently removed from the contents of the variable before performing the requested operation.  This step prevents the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). &lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. &lt;br /&gt;
&lt;br /&gt;
The updated contents of the variable returned in ResultVar might be useful for displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read the contents of EnvVarName from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# Remove all instances of the target path/string regardless of the operation because this not only eliminates duplicate entries, it also allows for the search order of the target entry to be changed from first to last and vice versa.&lt;br /&gt;
# If Action is &amp;quot;R&amp;quot; (remove), skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated variable to RegLoc even if the Action is &amp;quot;R&amp;quot; or the target is not found because this allows for the elimination of duplicate semicolons, spaces around semicolons, spaces preceding the first entry, and spaces following the last entry.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
==== Syntax ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
:; ResultVar&lt;br /&gt;
::Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
:; EnvVarName&lt;br /&gt;
:: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
:; Action&lt;br /&gt;
:: &amp;quot;A&amp;quot; = Append&lt;br /&gt;
:: &amp;quot;P&amp;quot; = Prepend&lt;br /&gt;
:: &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
:; RegLoc&lt;br /&gt;
:: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
:: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
:; PathString&lt;br /&gt;
:: A pathname or string to add to or remove from the contents of EnvVarName (e.g., &amp;quot;C:\MyApp&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
===== Installer Examples =====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\Windows Resource Kits\Tools&amp;quot; ; Append  &lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;%WinDir%\System32&amp;quot;                            ; Prepend     &lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;                                     ; Remove&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v1.0&amp;quot;  ; Remove path of old rev&lt;br /&gt;
${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v2.0&amp;quot;  ; Append the new one&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Uninstaller Examples =====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;          &lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v2.0&amp;quot;      ; Remove path of latest rev &lt;br /&gt;
${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v1.0&amp;quot;      ; Restore path of previous rev&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   &lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
; NOTE: Do not substitute &#039;StrReplaceV4&#039; for this function. It will fail due to the way I call it.&lt;br /&gt;
;&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15637</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15637"/>
		<updated>2008-07-03T15:41:22Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Parameters */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. The variable can be updated in either the &amp;quot;all users&amp;quot; section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
Duplicates entries, leading and trailing spaces around each entry, and duplicate semicolons are permanently removed from the contents of the variable before performing the requested operation.  This step prevents the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). &lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. &lt;br /&gt;
&lt;br /&gt;
The updated contents of the variable returned in ResultVar might be useful for displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read the contents of EnvVarName from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# Remove all instances of the target path/string regardless of the operation because this not only eliminates duplicate entries, it also allows for the search order of the target entry to be changed from first to last and vice versa.&lt;br /&gt;
# If Action is &amp;quot;R&amp;quot; (remove), skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated variable to RegLoc even if the Action is &amp;quot;R&amp;quot; or the target is not found because this allows for the elimination of duplicate semicolons, spaces around semicolons, spaces preceding the first entry, and spaces following the last entry.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
==== Syntax ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
:; ResultVar&lt;br /&gt;
::Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
:; EnvVarName&lt;br /&gt;
:: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
:; Action&lt;br /&gt;
:: &amp;quot;A&amp;quot; = Append&lt;br /&gt;
:: &amp;quot;P&amp;quot; = Prepend&lt;br /&gt;
:: &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
:; RegLoc&lt;br /&gt;
:: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
:: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
:; PathString&lt;br /&gt;
:: A pathname or string to add to or remove from the contents of EnvVarName (e.g., &amp;quot;C:\MyApp&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   &lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
; NOTE: Do not substitute &#039;StrReplaceV4&#039; for this function. It will fail due to the way I call it.&lt;br /&gt;
;&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15636</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15636"/>
		<updated>2008-07-03T15:37:39Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. The variable can be updated in either the &amp;quot;all users&amp;quot; section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
Duplicates entries, leading and trailing spaces around each entry, and duplicate semicolons are permanently removed from the contents of the variable before performing the requested operation.  This step prevents the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). &lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. &lt;br /&gt;
&lt;br /&gt;
The updated contents of the variable returned in ResultVar might be useful for displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read the contents of EnvVarName from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# Remove all instances of the target path/string regardless of the operation because this not only eliminates duplicate entries, it also allows for the search order of the target entry to be changed from first to last and vice versa.&lt;br /&gt;
# If Action is &amp;quot;R&amp;quot; (remove), skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated variable to RegLoc even if the Action is &amp;quot;R&amp;quot; or the target is not found because this allows for the elimination of duplicate semicolons, spaces around semicolons, spaces preceding the first entry, and spaces following the last entry.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
==== Syntax ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
:; ResultVar&lt;br /&gt;
::Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
:; EnvVarName&lt;br /&gt;
:: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
:; Action&lt;br /&gt;
:: &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
:; RegLoc&lt;br /&gt;
:: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
:: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
:; PathString&lt;br /&gt;
:: A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   &lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
; NOTE: Do not substitute &#039;StrReplaceV4&#039; for this function. It will fail due to the way I call it.&lt;br /&gt;
;&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15635</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15635"/>
		<updated>2008-07-03T15:35:24Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. The variable can be updated in either the &amp;quot;all users&amp;quot; section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
Duplicates entries, leading and trailing spaces around each entry, and duplicate semicolons are removed from the contents of the variable before performing the requested operation.  This step prevents the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). &lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. &lt;br /&gt;
&lt;br /&gt;
The updated contents of the variable returned in ResultVar might be useful for displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read the contents of EnvVarName from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# Remove all instances of the target path/string regardless of the operation because this not only eliminates duplicate entries, it also allows for the search order of the target entry to be changed from first to last and vice versa.&lt;br /&gt;
# If Action is &amp;quot;R&amp;quot; (remove), skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated variable to RegLoc even if the Action is &amp;quot;R&amp;quot; or the target is not found because this allows for the elimination of duplicate semicolons, spaces around semicolons, spaces preceding the first entry, and spaces following the last entry.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
==== Syntax ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
:; ResultVar&lt;br /&gt;
::Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
:; EnvVarName&lt;br /&gt;
:: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
:; Action&lt;br /&gt;
:: &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
:; RegLoc&lt;br /&gt;
:: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
:: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
:; PathString&lt;br /&gt;
:: A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   &lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
; NOTE: Do not substitute &#039;StrReplaceV4&#039; for this function. It will fail due to the way I call it.&lt;br /&gt;
;&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15634</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15634"/>
		<updated>2008-07-03T15:34:09Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. The variable can be updated in either the &amp;quot;all users&amp;quot; section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
Duplicates entries, leading and trailing spaces around each entry, and duplicate semicolons are removed from the contents of the variable before performing the requested operation.  This step prevents the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). &lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. &lt;br /&gt;
&lt;br /&gt;
The string returned in ResultVar (the updated contents of the variable) might be useful for displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read the contents of EnvVarName from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# Remove all instances of the target path/string regardless of the operation because this not only eliminates duplicate entries, it also allows for the search order of the target entry to be changed from first to last and vice versa.&lt;br /&gt;
# If Action is &amp;quot;R&amp;quot; (remove), skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated variable to RegLoc even if the Action is &amp;quot;R&amp;quot; or the target is not found because this allows for the elimination of duplicate semicolons, spaces around semicolons, spaces preceding the first entry, and spaces following the last entry.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
==== Syntax ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
:; ResultVar&lt;br /&gt;
::Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
:; EnvVarName&lt;br /&gt;
:: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
:; Action&lt;br /&gt;
:: &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
:; RegLoc&lt;br /&gt;
:: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
:: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
:; PathString&lt;br /&gt;
:: A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   &lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
; NOTE: Do not substitute &#039;StrReplaceV4&#039; for this function. It will fail due to the way I call it.&lt;br /&gt;
;&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Path_Manipulation&amp;diff=15633</id>
		<title>Path Manipulation</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Path_Manipulation&amp;diff=15633"/>
		<updated>2008-07-03T15:11:49Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Syntax */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}} &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname from the PATH environmental variable in either the &amp;quot;all users&amp;quot; (HKLM) or the &amp;quot;current user&amp;quot; (HKCU) section of the registry. &lt;br /&gt;
&lt;br /&gt;
Duplicates entries, leading and trailing spaces around each entry, and duplicate semicolons are removed from the contents of PATH before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname).&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
=== Syntax ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;Pathname&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot; &lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;Pathname&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
:; ResultVar&lt;br /&gt;
:: Updated contents PATH returned by the function&lt;br /&gt;
&lt;br /&gt;
:; EnvVarName&lt;br /&gt;
:: &amp;quot;PATH&amp;quot; &lt;br /&gt;
&lt;br /&gt;
:; Action&lt;br /&gt;
:: &amp;quot;A&amp;quot; = Append&lt;br /&gt;
:: &amp;quot;P&amp;quot; = Prepend&lt;br /&gt;
:: &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
:; RegLoc&lt;br /&gt;
:: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
:: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
:; Pathname&lt;br /&gt;
:: Pathname to add to or remove from the contents of PATH (e.g., &amp;quot;C:\MyApp&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\Windows Resource Kits\Tools&amp;quot;  &lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;%WinDir%\System32&amp;quot;  &lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v1.0&amp;quot;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v2.0&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v1.0&amp;quot;   &lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v2.0&amp;quot;   &lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dependencies == &lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;EnvVarUpdate&#039;&#039;&#039; (available at  [[Environmental_Variables:_append%2C_prepend%2C_and_remove_entries]])&lt;br /&gt;
* &#039;&#039;&#039;StrTok, StrContains, and StrReplace:&#039;&#039;&#039;  Included in the EnvVarUpdate function code &lt;br /&gt;
* &#039;&#039;&#039;LogicLib header file:&#039;&#039;&#039; &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
&lt;br /&gt;
* Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
* Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr  &lt;br /&gt;
* Diego Pedroso (deguix) for StrTok&lt;br /&gt;
* Kevin English (kenglish_hi)for StrContains&lt;br /&gt;
* Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry (dandaman32) for StrReplace&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Functions for Windows 95, 98, and ME ==&lt;br /&gt;
{{PageAuthor|KiCHiK}}&lt;br /&gt;
The following routines, AddToPath, un.RemoveFromPath, AddToEnvVar, and un.RemoveFromEnvVar are provided for Windows 95, 98, or ME in that they support the update of the autoexec.bat file.  Note that they can cause corruption of the PATH if the path being removed happens to be a subset of another path.   For example, if PATH contains &amp;quot;C:\Windows\system32\wbem&amp;quot; and you remove&lt;br /&gt;
&amp;quot;C:\Windows\system32&amp;quot; the result is &amp;quot;\wbem&amp;quot;.  They also do not prevent duplication of entries if ,for example, the user runs the installer multiple times.    &lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Here are four functions, two for adding to and removing directories from the search path (i.e. PATH environment variable) of Windows and two more for adding to and removing directories from a user defined environment variable such as INCLUDE or LIB etc. These functions should work on every version of Windows including 95, 98, ME, NT, 2000, and XP.&lt;br /&gt;
&lt;br /&gt;
For Windows NT/2000/XP they will write to HKEY_CURRENT_USER\Environment\PATH. For 9x/ME they will write to the autoexec.bat file.&lt;br /&gt;
&lt;br /&gt;
Changes on 9x machines will take place after a reboot. These functions set the reboot flag if the path variable was changed on 9x.&lt;br /&gt;
&lt;br /&gt;
These functions require NSIS 2.0b0 and above due to the usage of SendMessage with /TIMEOUT. It is possible to use it with earlier versions of NSIS with a little application I have created called RefreshEnv. It does exactly the same as SendMessage with /TIMEOUT. You can find it at [http://forums.winamp.com/showthread.php?s=&amp;amp;threadid=77904&amp;amp;highlight=refreshenv this forum thread].&lt;br /&gt;
&lt;br /&gt;
The directory added to the path must exist prior to calling this function.&lt;br /&gt;
&lt;br /&gt;
=== Usage Example ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;Section &amp;quot;Add to path&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call AddToPath&lt;br /&gt;
&lt;br /&gt;
  Push &amp;quot;LIB&amp;quot;&lt;br /&gt;
  Push &amp;quot;c:\Mylibrary\lib&amp;quot;&lt;br /&gt;
  Call AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
  ;likewise AddToPath could be&lt;br /&gt;
  Push &amp;quot;PATH&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
SectionEnd&lt;br /&gt;
&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Section &amp;quot;uninstall&amp;quot;&lt;br /&gt;
  # ...&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call un.RemoveFromPath&lt;br /&gt;
  # ...&lt;br /&gt;
  Push &amp;quot;LIB&amp;quot;&lt;br /&gt;
  Push &amp;quot;c:\Mylibrary\lib&amp;quot;&lt;br /&gt;
  Call un.RemoveFromEnvVar&lt;br /&gt;
&lt;br /&gt;
  ;Likewise RemoveFromPath could be&lt;br /&gt;
  Push &amp;quot;PATH&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call un.RemoveFromEnvVar&lt;br /&gt;
  &lt;br /&gt;
SectionEnd&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Functions ===&lt;br /&gt;
The functions in the flesh:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;!ifndef _AddToPath_nsh&lt;br /&gt;
!define _AddToPath_nsh&lt;br /&gt;
&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
!verbose 4&lt;br /&gt;
&lt;br /&gt;
!ifndef WriteEnvStr_RegKey&lt;br /&gt;
  !ifdef ALL_USERS&lt;br /&gt;
    !define WriteEnvStr_RegKey \&lt;br /&gt;
       &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
  !else&lt;br /&gt;
    !define WriteEnvStr_RegKey &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
  !endif&lt;br /&gt;
!endif&lt;br /&gt;
&lt;br /&gt;
; AddToPath - Adds the given dir to the search path.&lt;br /&gt;
;        Input - head of the stack&lt;br /&gt;
;        Note - Win9x systems requires reboot&lt;br /&gt;
&lt;br /&gt;
Function AddToPath&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Push $1&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
&lt;br /&gt;
  # don&#039;t add if the path doesn&#039;t exist&lt;br /&gt;
  IfFileExists &amp;quot;$0\*.*&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  ReadEnvStr $1 PATH&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$0;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$0\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  GetFullPathName /SHORT $3 $0&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$3;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$3\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  Call IsNT&lt;br /&gt;
  Pop $1&lt;br /&gt;
  StrCmp $1 1 AddToPath_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $1 $WINDIR 2&lt;br /&gt;
    FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; a&lt;br /&gt;
    FileSeek $1 -1 END&lt;br /&gt;
    FileReadByte $1 $2&lt;br /&gt;
    IntCmp $2 26 0 +2 +2 # DOS EOF&lt;br /&gt;
      FileSeek $1 -1 END # write over EOF&lt;br /&gt;
    FileWrite $1 &amp;quot;$\r$\nSET PATH=%PATH%;$3$\r$\n&amp;quot;&lt;br /&gt;
    FileClose $1&lt;br /&gt;
    SetRebootFlag true&lt;br /&gt;
    Goto AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  AddToPath_NT:&lt;br /&gt;
    ReadRegStr $1 ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot;&lt;br /&gt;
    StrCmp $1 &amp;quot;&amp;quot; AddToPath_NTdoIt&lt;br /&gt;
      Push $1&lt;br /&gt;
      Call Trim&lt;br /&gt;
      Pop $1&lt;br /&gt;
      StrCpy $0 &amp;quot;$1;$0&amp;quot;&lt;br /&gt;
    AddToPath_NTdoIt:&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot; $0&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  AddToPath_done:&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
; RemoveFromPath - Remove a given dir from the path&lt;br /&gt;
;     Input: head of the stack&lt;br /&gt;
&lt;br /&gt;
Function un.RemoveFromPath&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Push $1&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
&lt;br /&gt;
  IntFmt $6 &amp;quot;%c&amp;quot; 26 # DOS EOF&lt;br /&gt;
&lt;br /&gt;
  Call un.IsNT&lt;br /&gt;
  Pop $1&lt;br /&gt;
  StrCmp $1 1 unRemoveFromPath_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $1 $WINDIR 2&lt;br /&gt;
    FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; r&lt;br /&gt;
    GetTempFileName $4&lt;br /&gt;
    FileOpen $2 $4 w&lt;br /&gt;
    GetFullPathName /SHORT $0 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;SET PATH=%PATH%;$0&amp;quot;&lt;br /&gt;
    Goto unRemoveFromPath_dosLoop&lt;br /&gt;
&lt;br /&gt;
    unRemoveFromPath_dosLoop:&lt;br /&gt;
      FileRead $1 $3&lt;br /&gt;
      StrCpy $5 $3 1 -1 # read last char&lt;br /&gt;
      StrCmp $5 $6 0 +2 # if DOS EOF&lt;br /&gt;
        StrCpy $3 $3 -1 # remove DOS EOF so we can compare&lt;br /&gt;
      StrCmp $3 &amp;quot;$0$\r$\n&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;$0$\n&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;$0&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;&amp;quot; unRemoveFromPath_dosLoopEnd&lt;br /&gt;
      FileWrite $2 $3&lt;br /&gt;
      Goto unRemoveFromPath_dosLoop&lt;br /&gt;
      unRemoveFromPath_dosLoopRemoveLine:&lt;br /&gt;
        SetRebootFlag true&lt;br /&gt;
        Goto unRemoveFromPath_dosLoop&lt;br /&gt;
&lt;br /&gt;
    unRemoveFromPath_dosLoopEnd:&lt;br /&gt;
      FileClose $2&lt;br /&gt;
      FileClose $1&lt;br /&gt;
      StrCpy $1 $WINDIR 2&lt;br /&gt;
      Delete &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
      CopyFiles /SILENT $4 &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
      Delete $4&lt;br /&gt;
      Goto unRemoveFromPath_done&lt;br /&gt;
&lt;br /&gt;
  unRemoveFromPath_NT:&lt;br /&gt;
    ReadRegStr $1 ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot;&lt;br /&gt;
    StrCpy $5 $1 1 -1 # copy last char&lt;br /&gt;
    StrCmp $5 &amp;quot;;&amp;quot; +2 # if last char != ;&lt;br /&gt;
      StrCpy $1 &amp;quot;$1;&amp;quot; # append ;&lt;br /&gt;
    Push $1&lt;br /&gt;
    Push &amp;quot;$0;&amp;quot;&lt;br /&gt;
    Call un.StrStr ; Find `$0;` in $1&lt;br /&gt;
    Pop $2 ; pos of our dir&lt;br /&gt;
    StrCmp $2 &amp;quot;&amp;quot; unRemoveFromPath_done&lt;br /&gt;
      ; else, it is in path&lt;br /&gt;
      # $0 - path to add&lt;br /&gt;
      # $1 - path var&lt;br /&gt;
      StrLen $3 &amp;quot;$0;&amp;quot;&lt;br /&gt;
      StrLen $4 $2&lt;br /&gt;
      StrCpy $5 $1 -$4 # $5 is now the part before the path to remove&lt;br /&gt;
      StrCpy $6 $2 &amp;quot;&amp;quot; $3 # $6 is now the part after the path to remove&lt;br /&gt;
      StrCpy $3 $5$6&lt;br /&gt;
&lt;br /&gt;
      StrCpy $5 $3 1 -1 # copy last char&lt;br /&gt;
      StrCmp $5 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
        StrCpy $3 $3 -1 # remove last char&lt;br /&gt;
&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot; $3&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  unRemoveFromPath_done:&lt;br /&gt;
    Pop $6&lt;br /&gt;
    Pop $5&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; AddToEnvVar - Adds the given value to the given environment var&lt;br /&gt;
;        Input - head of the stack $0 environement variable $1=value to add&lt;br /&gt;
;        Note - Win9x systems requires reboot&lt;br /&gt;
 &lt;br /&gt;
Function AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
  Exch $1 ; $1 has environment variable value&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $0 ; $0 has environment variable name&lt;br /&gt;
&lt;br /&gt;
  DetailPrint &amp;quot;Adding $1 to $0&amp;quot;&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
  ReadEnvStr $2 $0&lt;br /&gt;
  Push &amp;quot;$2;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $3&lt;br /&gt;
  StrCmp $3 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToEnvVar_done&lt;br /&gt;
&lt;br /&gt;
  Push &amp;quot;$2;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$1\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $3&lt;br /&gt;
  StrCmp $3 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToEnvVar_done&lt;br /&gt;
  &lt;br /&gt;
 &lt;br /&gt;
  Call IsNT&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 1 AddToEnvVar_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $2 $WINDIR 2&lt;br /&gt;
    FileOpen $2 &amp;quot;$2\autoexec.bat&amp;quot; a&lt;br /&gt;
    FileSeek $2 -1 END&lt;br /&gt;
    FileReadByte $2 $3&lt;br /&gt;
    IntCmp $3 26 0 +2 +2 # DOS EOF&lt;br /&gt;
      FileSeek $2 -1 END # write over EOF&lt;br /&gt;
    FileWrite $2 &amp;quot;$\r$\nSET $0=%$0%;$4$\r$\n&amp;quot;&lt;br /&gt;
    FileClose $2&lt;br /&gt;
    SetRebootFlag true&lt;br /&gt;
    Goto AddToEnvVar_done&lt;br /&gt;
 &lt;br /&gt;
  AddToEnvVar_NT:&lt;br /&gt;
    ReadRegStr $2 ${WriteEnvStr_RegKey} $0&lt;br /&gt;
    StrCpy $3 $2 1 -1 # copy last char&lt;br /&gt;
    StrCmp $3 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
      StrCpy $2 $2 -1 # remove last char&lt;br /&gt;
    StrCmp $2 &amp;quot;&amp;quot; AddToEnvVar_NTdoIt&lt;br /&gt;
      StrCpy $1 &amp;quot;$2;$1&amp;quot;&lt;br /&gt;
    AddToEnvVar_NTdoIt:&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $1&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  AddToEnvVar_done:&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Pop $1&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
 &lt;br /&gt;
; RemoveFromEnvVar - Remove a given value from a environment var&lt;br /&gt;
;     Input: head of the stack&lt;br /&gt;
 &lt;br /&gt;
Function un.RemoveFromEnvVar&lt;br /&gt;
&lt;br /&gt;
  Exch $1 ; $1 has environment variable value&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $0 ; $0 has environment variable name&lt;br /&gt;
&lt;br /&gt;
  DetailPrint &amp;quot;Removing $1 from $0&amp;quot;&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
 &lt;br /&gt;
  IntFmt $7 &amp;quot;%c&amp;quot; 26 # DOS EOF&lt;br /&gt;
 &lt;br /&gt;
  Call un.IsNT&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 1 unRemoveFromEnvVar_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $2 $WINDIR 2&lt;br /&gt;
    FileOpen $2 &amp;quot;$2\autoexec.bat&amp;quot; r&lt;br /&gt;
    GetTempFileName $5&lt;br /&gt;
    FileOpen $3 $5 w&lt;br /&gt;
    GetFullPathName /SHORT $1 $1&lt;br /&gt;
    StrCpy $1 &amp;quot;SET $0=%$0%;$1&amp;quot;&lt;br /&gt;
    Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
 &lt;br /&gt;
    unRemoveFromEnvVar_dosLoop:&lt;br /&gt;
      FileRead $2 $4&lt;br /&gt;
      StrCpy $6 $4 1 -1 # read last char&lt;br /&gt;
      StrCmp $6 $7 0 +2 # if DOS EOF&lt;br /&gt;
        StrCpy $4 $4 -1 # remove DOS EOF so we can compare&lt;br /&gt;
      StrCmp $4 &amp;quot;$1$\r$\n&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;$1$\n&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;$1&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;&amp;quot; unRemoveFromEnvVar_dosLoopEnd&lt;br /&gt;
      FileWrite $3 $4&lt;br /&gt;
      Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
      unRemoveFromEnvVar_dosLoopRemoveLine:&lt;br /&gt;
        SetRebootFlag true&lt;br /&gt;
        Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
 &lt;br /&gt;
    unRemoveFromEnvVar_dosLoopEnd:&lt;br /&gt;
      FileClose $3&lt;br /&gt;
      FileClose $2&lt;br /&gt;
      StrCpy $2 $WINDIR 2&lt;br /&gt;
      Delete &amp;quot;$2\autoexec.bat&amp;quot;&lt;br /&gt;
      CopyFiles /SILENT $5 &amp;quot;$2\autoexec.bat&amp;quot;&lt;br /&gt;
      Delete $5&lt;br /&gt;
      Goto unRemoveFromEnvVar_done&lt;br /&gt;
 &lt;br /&gt;
  unRemoveFromEnvVar_NT:&lt;br /&gt;
    ReadRegStr $2 ${WriteEnvStr_RegKey} $0&lt;br /&gt;
    StrCpy $6 $2 1 -1 # copy last char&lt;br /&gt;
    StrCmp $6 &amp;quot;;&amp;quot; +2 # if last char != ;&lt;br /&gt;
      StrCpy $2 &amp;quot;$2;&amp;quot; # append ;&lt;br /&gt;
    Push $2&lt;br /&gt;
    Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
    Call un.StrStr ; Find `$1;` in $2&lt;br /&gt;
    Pop $3 ; pos of our dir&lt;br /&gt;
    StrCmp $3 &amp;quot;&amp;quot; unRemoveFromEnvVar_done&lt;br /&gt;
      ; else, it is in path&lt;br /&gt;
      # $1 - path to add&lt;br /&gt;
      # $2 - path var&lt;br /&gt;
      StrLen $4 &amp;quot;$1;&amp;quot;&lt;br /&gt;
      StrLen $5 $3&lt;br /&gt;
      StrCpy $6 $2 -$5 # $6 is now the part before the path to remove&lt;br /&gt;
      StrCpy $7 $3 &amp;quot;&amp;quot; $4 # $7 is now the part after the path to remove&lt;br /&gt;
      StrCpy $4 $6$7&lt;br /&gt;
 &lt;br /&gt;
      StrCpy $6 $4 1 -1 # copy last char&lt;br /&gt;
      StrCmp $6 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
      StrCpy $4 $4 -1 # remove last char&lt;br /&gt;
 &lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $4&lt;br /&gt;
&lt;br /&gt;
      ; delete reg value if null&lt;br /&gt;
      StrCmp $4 &amp;quot;&amp;quot; 0 +2 # if null delete reg&lt;br /&gt;
      DeleteRegValue ${WriteEnvStr_RegKey} $0&lt;br /&gt;
&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
 &lt;br /&gt;
  unRemoveFromEnvVar_done:&lt;br /&gt;
    Pop $7&lt;br /&gt;
    Pop $6&lt;br /&gt;
    Pop $5&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
!ifndef IsNT_KiCHiK&lt;br /&gt;
!define IsNT_KiCHiK&lt;br /&gt;
&lt;br /&gt;
###########################################&lt;br /&gt;
#            Utility Functions            #&lt;br /&gt;
###########################################&lt;br /&gt;
&lt;br /&gt;
; IsNT&lt;br /&gt;
; no input&lt;br /&gt;
; output, top of the stack = 1 if NT or 0 if not&lt;br /&gt;
;&lt;br /&gt;
; Usage:&lt;br /&gt;
;   Call IsNT&lt;br /&gt;
;   Pop $R0&lt;br /&gt;
;  ($R0 at this point is 1 or 0)&lt;br /&gt;
&lt;br /&gt;
!macro IsNT un&lt;br /&gt;
Function ${un}IsNT&lt;br /&gt;
  Push $0&lt;br /&gt;
  ReadRegStr $0 HKLM &amp;quot;SOFTWARE\Microsoft\Windows NT\CurrentVersion&amp;quot; CurrentVersion&lt;br /&gt;
  StrCmp $0 &amp;quot;&amp;quot; 0 IsNT_yes&lt;br /&gt;
  ; we are not NT.&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Push 0&lt;br /&gt;
  Return&lt;br /&gt;
&lt;br /&gt;
  IsNT_yes:&lt;br /&gt;
    ; NT!!!&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Push 1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro IsNT &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro IsNT &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!endif ; IsNT_KiCHiK&lt;br /&gt;
&lt;br /&gt;
; StrStr&lt;br /&gt;
; input, top of stack = string to search for&lt;br /&gt;
;        top of stack-1 = string to search in&lt;br /&gt;
; output, top of stack (replaces with the portion of the string remaining)&lt;br /&gt;
; modifies no other variables.&lt;br /&gt;
;&lt;br /&gt;
; Usage:&lt;br /&gt;
;   Push &amp;quot;this is a long ass string&amp;quot;&lt;br /&gt;
;   Push &amp;quot;ass&amp;quot;&lt;br /&gt;
;   Call StrStr&lt;br /&gt;
;   Pop $R0&lt;br /&gt;
;  ($R0 at this point is &amp;quot;ass string&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
!macro StrStr un&lt;br /&gt;
Function ${un}StrStr&lt;br /&gt;
Exch $R1 ; st=haystack,old$R1, $R1=needle&lt;br /&gt;
  Exch    ; st=old$R1,haystack&lt;br /&gt;
  Exch $R2 ; st=old$R1,old$R2, $R2=haystack&lt;br /&gt;
  Push $R3&lt;br /&gt;
  Push $R4&lt;br /&gt;
  Push $R5&lt;br /&gt;
  StrLen $R3 $R1&lt;br /&gt;
  StrCpy $R4 0&lt;br /&gt;
  ; $R1=needle&lt;br /&gt;
  ; $R2=haystack&lt;br /&gt;
  ; $R3=len(needle)&lt;br /&gt;
  ; $R4=cnt&lt;br /&gt;
  ; $R5=tmp&lt;br /&gt;
  loop:&lt;br /&gt;
    StrCpy $R5 $R2 $R3 $R4&lt;br /&gt;
    StrCmp $R5 $R1 done&lt;br /&gt;
    StrCmp $R5 &amp;quot;&amp;quot; done&lt;br /&gt;
    IntOp $R4 $R4 + 1&lt;br /&gt;
    Goto loop&lt;br /&gt;
done:&lt;br /&gt;
  StrCpy $R1 $R2 &amp;quot;&amp;quot; $R4&lt;br /&gt;
  Pop $R5&lt;br /&gt;
  Pop $R4&lt;br /&gt;
  Pop $R3&lt;br /&gt;
  Pop $R2&lt;br /&gt;
  Exch $R1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrStr &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrStr &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!endif ; _AddToPath_nsh&lt;br /&gt;
&lt;br /&gt;
Function Trim ; Added by Pelaca&lt;br /&gt;
	Exch $R1&lt;br /&gt;
	Push $R2&lt;br /&gt;
Loop:&lt;br /&gt;
	StrCpy $R2 &amp;quot;$R1&amp;quot; 1 -1&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot; &amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;$\n&amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;$\r&amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;;&amp;quot; RTrim&lt;br /&gt;
	GoTo Done&lt;br /&gt;
RTrim:	&lt;br /&gt;
	StrCpy $R1 &amp;quot;$R1&amp;quot; -1&lt;br /&gt;
	Goto Loop&lt;br /&gt;
Done:&lt;br /&gt;
	Pop $R2&lt;br /&gt;
	Exch $R1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Path_Manipulation&amp;diff=15632</id>
		<title>Path Manipulation</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Path_Manipulation&amp;diff=15632"/>
		<updated>2008-07-03T15:08:23Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Syntax */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}} &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname from the PATH environmental variable in either the &amp;quot;all users&amp;quot; (HKLM) or the &amp;quot;current user&amp;quot; (HKCU) section of the registry. &lt;br /&gt;
&lt;br /&gt;
Duplicates entries, leading and trailing spaces around each entry, and duplicate semicolons are removed from the contents of PATH before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname).&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
=== Syntax ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;PATH&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;Pathname&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 Push &amp;quot;PATH&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;Pathname&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
:; ResultVar&lt;br /&gt;
:: Updated contents PATH returned by the function&lt;br /&gt;
&lt;br /&gt;
:; EnvVarName&lt;br /&gt;
:: &amp;quot;PATH&amp;quot; &lt;br /&gt;
&lt;br /&gt;
:; Action&lt;br /&gt;
:: &amp;quot;A&amp;quot; = Append&lt;br /&gt;
:: &amp;quot;P&amp;quot; = Prepend&lt;br /&gt;
:: &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
:; RegLoc&lt;br /&gt;
:: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
:: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
:; Pathname&lt;br /&gt;
:: Pathname to add to or remove from the contents of PATH (e.g., &amp;quot;C:\MyApp&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\Windows Resource Kits\Tools&amp;quot;  &lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;%WinDir%\System32&amp;quot;  &lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v1.0&amp;quot;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v2.0&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v1.0&amp;quot;   &lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v2.0&amp;quot;   &lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dependencies == &lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;EnvVarUpdate&#039;&#039;&#039; (available at  [[Environmental_Variables:_append%2C_prepend%2C_and_remove_entries]])&lt;br /&gt;
* &#039;&#039;&#039;StrTok, StrContains, and StrReplace:&#039;&#039;&#039;  Included in the EnvVarUpdate function code &lt;br /&gt;
* &#039;&#039;&#039;LogicLib header file:&#039;&#039;&#039; &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
&lt;br /&gt;
* Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
* Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr  &lt;br /&gt;
* Diego Pedroso (deguix) for StrTok&lt;br /&gt;
* Kevin English (kenglish_hi)for StrContains&lt;br /&gt;
* Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry (dandaman32) for StrReplace&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Functions for Windows 95, 98, and ME ==&lt;br /&gt;
{{PageAuthor|KiCHiK}}&lt;br /&gt;
The following routines, AddToPath, un.RemoveFromPath, AddToEnvVar, and un.RemoveFromEnvVar are provided for Windows 95, 98, or ME in that they support the update of the autoexec.bat file.  Note that they can cause corruption of the PATH if the path being removed happens to be a subset of another path.   For example, if PATH contains &amp;quot;C:\Windows\system32\wbem&amp;quot; and you remove&lt;br /&gt;
&amp;quot;C:\Windows\system32&amp;quot; the result is &amp;quot;\wbem&amp;quot;.  They also do not prevent duplication of entries if ,for example, the user runs the installer multiple times.    &lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Here are four functions, two for adding to and removing directories from the search path (i.e. PATH environment variable) of Windows and two more for adding to and removing directories from a user defined environment variable such as INCLUDE or LIB etc. These functions should work on every version of Windows including 95, 98, ME, NT, 2000, and XP.&lt;br /&gt;
&lt;br /&gt;
For Windows NT/2000/XP they will write to HKEY_CURRENT_USER\Environment\PATH. For 9x/ME they will write to the autoexec.bat file.&lt;br /&gt;
&lt;br /&gt;
Changes on 9x machines will take place after a reboot. These functions set the reboot flag if the path variable was changed on 9x.&lt;br /&gt;
&lt;br /&gt;
These functions require NSIS 2.0b0 and above due to the usage of SendMessage with /TIMEOUT. It is possible to use it with earlier versions of NSIS with a little application I have created called RefreshEnv. It does exactly the same as SendMessage with /TIMEOUT. You can find it at [http://forums.winamp.com/showthread.php?s=&amp;amp;threadid=77904&amp;amp;highlight=refreshenv this forum thread].&lt;br /&gt;
&lt;br /&gt;
The directory added to the path must exist prior to calling this function.&lt;br /&gt;
&lt;br /&gt;
=== Usage Example ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;Section &amp;quot;Add to path&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call AddToPath&lt;br /&gt;
&lt;br /&gt;
  Push &amp;quot;LIB&amp;quot;&lt;br /&gt;
  Push &amp;quot;c:\Mylibrary\lib&amp;quot;&lt;br /&gt;
  Call AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
  ;likewise AddToPath could be&lt;br /&gt;
  Push &amp;quot;PATH&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
SectionEnd&lt;br /&gt;
&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Section &amp;quot;uninstall&amp;quot;&lt;br /&gt;
  # ...&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call un.RemoveFromPath&lt;br /&gt;
  # ...&lt;br /&gt;
  Push &amp;quot;LIB&amp;quot;&lt;br /&gt;
  Push &amp;quot;c:\Mylibrary\lib&amp;quot;&lt;br /&gt;
  Call un.RemoveFromEnvVar&lt;br /&gt;
&lt;br /&gt;
  ;Likewise RemoveFromPath could be&lt;br /&gt;
  Push &amp;quot;PATH&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call un.RemoveFromEnvVar&lt;br /&gt;
  &lt;br /&gt;
SectionEnd&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Functions ===&lt;br /&gt;
The functions in the flesh:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;!ifndef _AddToPath_nsh&lt;br /&gt;
!define _AddToPath_nsh&lt;br /&gt;
&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
!verbose 4&lt;br /&gt;
&lt;br /&gt;
!ifndef WriteEnvStr_RegKey&lt;br /&gt;
  !ifdef ALL_USERS&lt;br /&gt;
    !define WriteEnvStr_RegKey \&lt;br /&gt;
       &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
  !else&lt;br /&gt;
    !define WriteEnvStr_RegKey &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
  !endif&lt;br /&gt;
!endif&lt;br /&gt;
&lt;br /&gt;
; AddToPath - Adds the given dir to the search path.&lt;br /&gt;
;        Input - head of the stack&lt;br /&gt;
;        Note - Win9x systems requires reboot&lt;br /&gt;
&lt;br /&gt;
Function AddToPath&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Push $1&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
&lt;br /&gt;
  # don&#039;t add if the path doesn&#039;t exist&lt;br /&gt;
  IfFileExists &amp;quot;$0\*.*&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  ReadEnvStr $1 PATH&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$0;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$0\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  GetFullPathName /SHORT $3 $0&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$3;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$3\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  Call IsNT&lt;br /&gt;
  Pop $1&lt;br /&gt;
  StrCmp $1 1 AddToPath_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $1 $WINDIR 2&lt;br /&gt;
    FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; a&lt;br /&gt;
    FileSeek $1 -1 END&lt;br /&gt;
    FileReadByte $1 $2&lt;br /&gt;
    IntCmp $2 26 0 +2 +2 # DOS EOF&lt;br /&gt;
      FileSeek $1 -1 END # write over EOF&lt;br /&gt;
    FileWrite $1 &amp;quot;$\r$\nSET PATH=%PATH%;$3$\r$\n&amp;quot;&lt;br /&gt;
    FileClose $1&lt;br /&gt;
    SetRebootFlag true&lt;br /&gt;
    Goto AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  AddToPath_NT:&lt;br /&gt;
    ReadRegStr $1 ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot;&lt;br /&gt;
    StrCmp $1 &amp;quot;&amp;quot; AddToPath_NTdoIt&lt;br /&gt;
      Push $1&lt;br /&gt;
      Call Trim&lt;br /&gt;
      Pop $1&lt;br /&gt;
      StrCpy $0 &amp;quot;$1;$0&amp;quot;&lt;br /&gt;
    AddToPath_NTdoIt:&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot; $0&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  AddToPath_done:&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
; RemoveFromPath - Remove a given dir from the path&lt;br /&gt;
;     Input: head of the stack&lt;br /&gt;
&lt;br /&gt;
Function un.RemoveFromPath&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Push $1&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
&lt;br /&gt;
  IntFmt $6 &amp;quot;%c&amp;quot; 26 # DOS EOF&lt;br /&gt;
&lt;br /&gt;
  Call un.IsNT&lt;br /&gt;
  Pop $1&lt;br /&gt;
  StrCmp $1 1 unRemoveFromPath_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $1 $WINDIR 2&lt;br /&gt;
    FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; r&lt;br /&gt;
    GetTempFileName $4&lt;br /&gt;
    FileOpen $2 $4 w&lt;br /&gt;
    GetFullPathName /SHORT $0 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;SET PATH=%PATH%;$0&amp;quot;&lt;br /&gt;
    Goto unRemoveFromPath_dosLoop&lt;br /&gt;
&lt;br /&gt;
    unRemoveFromPath_dosLoop:&lt;br /&gt;
      FileRead $1 $3&lt;br /&gt;
      StrCpy $5 $3 1 -1 # read last char&lt;br /&gt;
      StrCmp $5 $6 0 +2 # if DOS EOF&lt;br /&gt;
        StrCpy $3 $3 -1 # remove DOS EOF so we can compare&lt;br /&gt;
      StrCmp $3 &amp;quot;$0$\r$\n&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;$0$\n&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;$0&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;&amp;quot; unRemoveFromPath_dosLoopEnd&lt;br /&gt;
      FileWrite $2 $3&lt;br /&gt;
      Goto unRemoveFromPath_dosLoop&lt;br /&gt;
      unRemoveFromPath_dosLoopRemoveLine:&lt;br /&gt;
        SetRebootFlag true&lt;br /&gt;
        Goto unRemoveFromPath_dosLoop&lt;br /&gt;
&lt;br /&gt;
    unRemoveFromPath_dosLoopEnd:&lt;br /&gt;
      FileClose $2&lt;br /&gt;
      FileClose $1&lt;br /&gt;
      StrCpy $1 $WINDIR 2&lt;br /&gt;
      Delete &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
      CopyFiles /SILENT $4 &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
      Delete $4&lt;br /&gt;
      Goto unRemoveFromPath_done&lt;br /&gt;
&lt;br /&gt;
  unRemoveFromPath_NT:&lt;br /&gt;
    ReadRegStr $1 ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot;&lt;br /&gt;
    StrCpy $5 $1 1 -1 # copy last char&lt;br /&gt;
    StrCmp $5 &amp;quot;;&amp;quot; +2 # if last char != ;&lt;br /&gt;
      StrCpy $1 &amp;quot;$1;&amp;quot; # append ;&lt;br /&gt;
    Push $1&lt;br /&gt;
    Push &amp;quot;$0;&amp;quot;&lt;br /&gt;
    Call un.StrStr ; Find `$0;` in $1&lt;br /&gt;
    Pop $2 ; pos of our dir&lt;br /&gt;
    StrCmp $2 &amp;quot;&amp;quot; unRemoveFromPath_done&lt;br /&gt;
      ; else, it is in path&lt;br /&gt;
      # $0 - path to add&lt;br /&gt;
      # $1 - path var&lt;br /&gt;
      StrLen $3 &amp;quot;$0;&amp;quot;&lt;br /&gt;
      StrLen $4 $2&lt;br /&gt;
      StrCpy $5 $1 -$4 # $5 is now the part before the path to remove&lt;br /&gt;
      StrCpy $6 $2 &amp;quot;&amp;quot; $3 # $6 is now the part after the path to remove&lt;br /&gt;
      StrCpy $3 $5$6&lt;br /&gt;
&lt;br /&gt;
      StrCpy $5 $3 1 -1 # copy last char&lt;br /&gt;
      StrCmp $5 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
        StrCpy $3 $3 -1 # remove last char&lt;br /&gt;
&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot; $3&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  unRemoveFromPath_done:&lt;br /&gt;
    Pop $6&lt;br /&gt;
    Pop $5&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; AddToEnvVar - Adds the given value to the given environment var&lt;br /&gt;
;        Input - head of the stack $0 environement variable $1=value to add&lt;br /&gt;
;        Note - Win9x systems requires reboot&lt;br /&gt;
 &lt;br /&gt;
Function AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
  Exch $1 ; $1 has environment variable value&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $0 ; $0 has environment variable name&lt;br /&gt;
&lt;br /&gt;
  DetailPrint &amp;quot;Adding $1 to $0&amp;quot;&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
  ReadEnvStr $2 $0&lt;br /&gt;
  Push &amp;quot;$2;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $3&lt;br /&gt;
  StrCmp $3 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToEnvVar_done&lt;br /&gt;
&lt;br /&gt;
  Push &amp;quot;$2;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$1\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $3&lt;br /&gt;
  StrCmp $3 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToEnvVar_done&lt;br /&gt;
  &lt;br /&gt;
 &lt;br /&gt;
  Call IsNT&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 1 AddToEnvVar_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $2 $WINDIR 2&lt;br /&gt;
    FileOpen $2 &amp;quot;$2\autoexec.bat&amp;quot; a&lt;br /&gt;
    FileSeek $2 -1 END&lt;br /&gt;
    FileReadByte $2 $3&lt;br /&gt;
    IntCmp $3 26 0 +2 +2 # DOS EOF&lt;br /&gt;
      FileSeek $2 -1 END # write over EOF&lt;br /&gt;
    FileWrite $2 &amp;quot;$\r$\nSET $0=%$0%;$4$\r$\n&amp;quot;&lt;br /&gt;
    FileClose $2&lt;br /&gt;
    SetRebootFlag true&lt;br /&gt;
    Goto AddToEnvVar_done&lt;br /&gt;
 &lt;br /&gt;
  AddToEnvVar_NT:&lt;br /&gt;
    ReadRegStr $2 ${WriteEnvStr_RegKey} $0&lt;br /&gt;
    StrCpy $3 $2 1 -1 # copy last char&lt;br /&gt;
    StrCmp $3 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
      StrCpy $2 $2 -1 # remove last char&lt;br /&gt;
    StrCmp $2 &amp;quot;&amp;quot; AddToEnvVar_NTdoIt&lt;br /&gt;
      StrCpy $1 &amp;quot;$2;$1&amp;quot;&lt;br /&gt;
    AddToEnvVar_NTdoIt:&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $1&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  AddToEnvVar_done:&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Pop $1&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
 &lt;br /&gt;
; RemoveFromEnvVar - Remove a given value from a environment var&lt;br /&gt;
;     Input: head of the stack&lt;br /&gt;
 &lt;br /&gt;
Function un.RemoveFromEnvVar&lt;br /&gt;
&lt;br /&gt;
  Exch $1 ; $1 has environment variable value&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $0 ; $0 has environment variable name&lt;br /&gt;
&lt;br /&gt;
  DetailPrint &amp;quot;Removing $1 from $0&amp;quot;&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
 &lt;br /&gt;
  IntFmt $7 &amp;quot;%c&amp;quot; 26 # DOS EOF&lt;br /&gt;
 &lt;br /&gt;
  Call un.IsNT&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 1 unRemoveFromEnvVar_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $2 $WINDIR 2&lt;br /&gt;
    FileOpen $2 &amp;quot;$2\autoexec.bat&amp;quot; r&lt;br /&gt;
    GetTempFileName $5&lt;br /&gt;
    FileOpen $3 $5 w&lt;br /&gt;
    GetFullPathName /SHORT $1 $1&lt;br /&gt;
    StrCpy $1 &amp;quot;SET $0=%$0%;$1&amp;quot;&lt;br /&gt;
    Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
 &lt;br /&gt;
    unRemoveFromEnvVar_dosLoop:&lt;br /&gt;
      FileRead $2 $4&lt;br /&gt;
      StrCpy $6 $4 1 -1 # read last char&lt;br /&gt;
      StrCmp $6 $7 0 +2 # if DOS EOF&lt;br /&gt;
        StrCpy $4 $4 -1 # remove DOS EOF so we can compare&lt;br /&gt;
      StrCmp $4 &amp;quot;$1$\r$\n&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;$1$\n&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;$1&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;&amp;quot; unRemoveFromEnvVar_dosLoopEnd&lt;br /&gt;
      FileWrite $3 $4&lt;br /&gt;
      Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
      unRemoveFromEnvVar_dosLoopRemoveLine:&lt;br /&gt;
        SetRebootFlag true&lt;br /&gt;
        Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
 &lt;br /&gt;
    unRemoveFromEnvVar_dosLoopEnd:&lt;br /&gt;
      FileClose $3&lt;br /&gt;
      FileClose $2&lt;br /&gt;
      StrCpy $2 $WINDIR 2&lt;br /&gt;
      Delete &amp;quot;$2\autoexec.bat&amp;quot;&lt;br /&gt;
      CopyFiles /SILENT $5 &amp;quot;$2\autoexec.bat&amp;quot;&lt;br /&gt;
      Delete $5&lt;br /&gt;
      Goto unRemoveFromEnvVar_done&lt;br /&gt;
 &lt;br /&gt;
  unRemoveFromEnvVar_NT:&lt;br /&gt;
    ReadRegStr $2 ${WriteEnvStr_RegKey} $0&lt;br /&gt;
    StrCpy $6 $2 1 -1 # copy last char&lt;br /&gt;
    StrCmp $6 &amp;quot;;&amp;quot; +2 # if last char != ;&lt;br /&gt;
      StrCpy $2 &amp;quot;$2;&amp;quot; # append ;&lt;br /&gt;
    Push $2&lt;br /&gt;
    Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
    Call un.StrStr ; Find `$1;` in $2&lt;br /&gt;
    Pop $3 ; pos of our dir&lt;br /&gt;
    StrCmp $3 &amp;quot;&amp;quot; unRemoveFromEnvVar_done&lt;br /&gt;
      ; else, it is in path&lt;br /&gt;
      # $1 - path to add&lt;br /&gt;
      # $2 - path var&lt;br /&gt;
      StrLen $4 &amp;quot;$1;&amp;quot;&lt;br /&gt;
      StrLen $5 $3&lt;br /&gt;
      StrCpy $6 $2 -$5 # $6 is now the part before the path to remove&lt;br /&gt;
      StrCpy $7 $3 &amp;quot;&amp;quot; $4 # $7 is now the part after the path to remove&lt;br /&gt;
      StrCpy $4 $6$7&lt;br /&gt;
 &lt;br /&gt;
      StrCpy $6 $4 1 -1 # copy last char&lt;br /&gt;
      StrCmp $6 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
      StrCpy $4 $4 -1 # remove last char&lt;br /&gt;
 &lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $4&lt;br /&gt;
&lt;br /&gt;
      ; delete reg value if null&lt;br /&gt;
      StrCmp $4 &amp;quot;&amp;quot; 0 +2 # if null delete reg&lt;br /&gt;
      DeleteRegValue ${WriteEnvStr_RegKey} $0&lt;br /&gt;
&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
 &lt;br /&gt;
  unRemoveFromEnvVar_done:&lt;br /&gt;
    Pop $7&lt;br /&gt;
    Pop $6&lt;br /&gt;
    Pop $5&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
!ifndef IsNT_KiCHiK&lt;br /&gt;
!define IsNT_KiCHiK&lt;br /&gt;
&lt;br /&gt;
###########################################&lt;br /&gt;
#            Utility Functions            #&lt;br /&gt;
###########################################&lt;br /&gt;
&lt;br /&gt;
; IsNT&lt;br /&gt;
; no input&lt;br /&gt;
; output, top of the stack = 1 if NT or 0 if not&lt;br /&gt;
;&lt;br /&gt;
; Usage:&lt;br /&gt;
;   Call IsNT&lt;br /&gt;
;   Pop $R0&lt;br /&gt;
;  ($R0 at this point is 1 or 0)&lt;br /&gt;
&lt;br /&gt;
!macro IsNT un&lt;br /&gt;
Function ${un}IsNT&lt;br /&gt;
  Push $0&lt;br /&gt;
  ReadRegStr $0 HKLM &amp;quot;SOFTWARE\Microsoft\Windows NT\CurrentVersion&amp;quot; CurrentVersion&lt;br /&gt;
  StrCmp $0 &amp;quot;&amp;quot; 0 IsNT_yes&lt;br /&gt;
  ; we are not NT.&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Push 0&lt;br /&gt;
  Return&lt;br /&gt;
&lt;br /&gt;
  IsNT_yes:&lt;br /&gt;
    ; NT!!!&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Push 1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro IsNT &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro IsNT &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!endif ; IsNT_KiCHiK&lt;br /&gt;
&lt;br /&gt;
; StrStr&lt;br /&gt;
; input, top of stack = string to search for&lt;br /&gt;
;        top of stack-1 = string to search in&lt;br /&gt;
; output, top of stack (replaces with the portion of the string remaining)&lt;br /&gt;
; modifies no other variables.&lt;br /&gt;
;&lt;br /&gt;
; Usage:&lt;br /&gt;
;   Push &amp;quot;this is a long ass string&amp;quot;&lt;br /&gt;
;   Push &amp;quot;ass&amp;quot;&lt;br /&gt;
;   Call StrStr&lt;br /&gt;
;   Pop $R0&lt;br /&gt;
;  ($R0 at this point is &amp;quot;ass string&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
!macro StrStr un&lt;br /&gt;
Function ${un}StrStr&lt;br /&gt;
Exch $R1 ; st=haystack,old$R1, $R1=needle&lt;br /&gt;
  Exch    ; st=old$R1,haystack&lt;br /&gt;
  Exch $R2 ; st=old$R1,old$R2, $R2=haystack&lt;br /&gt;
  Push $R3&lt;br /&gt;
  Push $R4&lt;br /&gt;
  Push $R5&lt;br /&gt;
  StrLen $R3 $R1&lt;br /&gt;
  StrCpy $R4 0&lt;br /&gt;
  ; $R1=needle&lt;br /&gt;
  ; $R2=haystack&lt;br /&gt;
  ; $R3=len(needle)&lt;br /&gt;
  ; $R4=cnt&lt;br /&gt;
  ; $R5=tmp&lt;br /&gt;
  loop:&lt;br /&gt;
    StrCpy $R5 $R2 $R3 $R4&lt;br /&gt;
    StrCmp $R5 $R1 done&lt;br /&gt;
    StrCmp $R5 &amp;quot;&amp;quot; done&lt;br /&gt;
    IntOp $R4 $R4 + 1&lt;br /&gt;
    Goto loop&lt;br /&gt;
done:&lt;br /&gt;
  StrCpy $R1 $R2 &amp;quot;&amp;quot; $R4&lt;br /&gt;
  Pop $R5&lt;br /&gt;
  Pop $R4&lt;br /&gt;
  Pop $R3&lt;br /&gt;
  Pop $R2&lt;br /&gt;
  Exch $R1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrStr &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrStr &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!endif ; _AddToPath_nsh&lt;br /&gt;
&lt;br /&gt;
Function Trim ; Added by Pelaca&lt;br /&gt;
	Exch $R1&lt;br /&gt;
	Push $R2&lt;br /&gt;
Loop:&lt;br /&gt;
	StrCpy $R2 &amp;quot;$R1&amp;quot; 1 -1&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot; &amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;$\n&amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;$\r&amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;;&amp;quot; RTrim&lt;br /&gt;
	GoTo Done&lt;br /&gt;
RTrim:	&lt;br /&gt;
	StrCpy $R1 &amp;quot;$R1&amp;quot; -1&lt;br /&gt;
	Goto Loop&lt;br /&gt;
Done:&lt;br /&gt;
	Pop $R2&lt;br /&gt;
	Exch $R1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Path_Manipulation&amp;diff=15631</id>
		<title>Path Manipulation</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Path_Manipulation&amp;diff=15631"/>
		<updated>2008-07-03T15:05:40Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Syntax */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}} &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname from the PATH environmental variable in either the &amp;quot;all users&amp;quot; (HKLM) or the &amp;quot;current user&amp;quot; (HKCU) section of the registry. &lt;br /&gt;
&lt;br /&gt;
Duplicates entries, leading and trailing spaces around each entry, and duplicate semicolons are removed from the contents of PATH before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname).&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
=== Syntax ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;PATH&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;Pathname&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;PATH&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;Pathname&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
:; ResultVar&lt;br /&gt;
:: Updated contents PATH returned by the function&lt;br /&gt;
&lt;br /&gt;
:; EnvVarName&lt;br /&gt;
:: &amp;quot;PATH&amp;quot; &lt;br /&gt;
&lt;br /&gt;
:; Action&lt;br /&gt;
:: &amp;quot;A&amp;quot; = Append&lt;br /&gt;
:: &amp;quot;P&amp;quot; = Prepend&lt;br /&gt;
:: &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
:; RegLoc&lt;br /&gt;
:: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
:: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
:; Pathname&lt;br /&gt;
:: Pathname to add to or remove from the contents of PATH (e.g., &amp;quot;C:\MyApp&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\Windows Resource Kits\Tools&amp;quot;  &lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;%WinDir%\System32&amp;quot;  &lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v1.0&amp;quot;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v2.0&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v1.0&amp;quot;   &lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v2.0&amp;quot;   &lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dependencies == &lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;EnvVarUpdate&#039;&#039;&#039; (available at  [[Environmental_Variables:_append%2C_prepend%2C_and_remove_entries]])&lt;br /&gt;
* &#039;&#039;&#039;StrTok, StrContains, and StrReplace:&#039;&#039;&#039;  Included in the EnvVarUpdate function code &lt;br /&gt;
* &#039;&#039;&#039;LogicLib header file:&#039;&#039;&#039; &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
&lt;br /&gt;
* Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
* Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr  &lt;br /&gt;
* Diego Pedroso (deguix) for StrTok&lt;br /&gt;
* Kevin English (kenglish_hi)for StrContains&lt;br /&gt;
* Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry (dandaman32) for StrReplace&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Functions for Windows 95, 98, and ME ==&lt;br /&gt;
{{PageAuthor|KiCHiK}}&lt;br /&gt;
The following routines, AddToPath, un.RemoveFromPath, AddToEnvVar, and un.RemoveFromEnvVar are provided for Windows 95, 98, or ME in that they support the update of the autoexec.bat file.  Note that they can cause corruption of the PATH if the path being removed happens to be a subset of another path.   For example, if PATH contains &amp;quot;C:\Windows\system32\wbem&amp;quot; and you remove&lt;br /&gt;
&amp;quot;C:\Windows\system32&amp;quot; the result is &amp;quot;\wbem&amp;quot;.  They also do not prevent duplication of entries if ,for example, the user runs the installer multiple times.    &lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Here are four functions, two for adding to and removing directories from the search path (i.e. PATH environment variable) of Windows and two more for adding to and removing directories from a user defined environment variable such as INCLUDE or LIB etc. These functions should work on every version of Windows including 95, 98, ME, NT, 2000, and XP.&lt;br /&gt;
&lt;br /&gt;
For Windows NT/2000/XP they will write to HKEY_CURRENT_USER\Environment\PATH. For 9x/ME they will write to the autoexec.bat file.&lt;br /&gt;
&lt;br /&gt;
Changes on 9x machines will take place after a reboot. These functions set the reboot flag if the path variable was changed on 9x.&lt;br /&gt;
&lt;br /&gt;
These functions require NSIS 2.0b0 and above due to the usage of SendMessage with /TIMEOUT. It is possible to use it with earlier versions of NSIS with a little application I have created called RefreshEnv. It does exactly the same as SendMessage with /TIMEOUT. You can find it at [http://forums.winamp.com/showthread.php?s=&amp;amp;threadid=77904&amp;amp;highlight=refreshenv this forum thread].&lt;br /&gt;
&lt;br /&gt;
The directory added to the path must exist prior to calling this function.&lt;br /&gt;
&lt;br /&gt;
=== Usage Example ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;Section &amp;quot;Add to path&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call AddToPath&lt;br /&gt;
&lt;br /&gt;
  Push &amp;quot;LIB&amp;quot;&lt;br /&gt;
  Push &amp;quot;c:\Mylibrary\lib&amp;quot;&lt;br /&gt;
  Call AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
  ;likewise AddToPath could be&lt;br /&gt;
  Push &amp;quot;PATH&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
SectionEnd&lt;br /&gt;
&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Section &amp;quot;uninstall&amp;quot;&lt;br /&gt;
  # ...&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call un.RemoveFromPath&lt;br /&gt;
  # ...&lt;br /&gt;
  Push &amp;quot;LIB&amp;quot;&lt;br /&gt;
  Push &amp;quot;c:\Mylibrary\lib&amp;quot;&lt;br /&gt;
  Call un.RemoveFromEnvVar&lt;br /&gt;
&lt;br /&gt;
  ;Likewise RemoveFromPath could be&lt;br /&gt;
  Push &amp;quot;PATH&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call un.RemoveFromEnvVar&lt;br /&gt;
  &lt;br /&gt;
SectionEnd&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Functions ===&lt;br /&gt;
The functions in the flesh:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;!ifndef _AddToPath_nsh&lt;br /&gt;
!define _AddToPath_nsh&lt;br /&gt;
&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
!verbose 4&lt;br /&gt;
&lt;br /&gt;
!ifndef WriteEnvStr_RegKey&lt;br /&gt;
  !ifdef ALL_USERS&lt;br /&gt;
    !define WriteEnvStr_RegKey \&lt;br /&gt;
       &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
  !else&lt;br /&gt;
    !define WriteEnvStr_RegKey &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
  !endif&lt;br /&gt;
!endif&lt;br /&gt;
&lt;br /&gt;
; AddToPath - Adds the given dir to the search path.&lt;br /&gt;
;        Input - head of the stack&lt;br /&gt;
;        Note - Win9x systems requires reboot&lt;br /&gt;
&lt;br /&gt;
Function AddToPath&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Push $1&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
&lt;br /&gt;
  # don&#039;t add if the path doesn&#039;t exist&lt;br /&gt;
  IfFileExists &amp;quot;$0\*.*&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  ReadEnvStr $1 PATH&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$0;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$0\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  GetFullPathName /SHORT $3 $0&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$3;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$3\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  Call IsNT&lt;br /&gt;
  Pop $1&lt;br /&gt;
  StrCmp $1 1 AddToPath_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $1 $WINDIR 2&lt;br /&gt;
    FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; a&lt;br /&gt;
    FileSeek $1 -1 END&lt;br /&gt;
    FileReadByte $1 $2&lt;br /&gt;
    IntCmp $2 26 0 +2 +2 # DOS EOF&lt;br /&gt;
      FileSeek $1 -1 END # write over EOF&lt;br /&gt;
    FileWrite $1 &amp;quot;$\r$\nSET PATH=%PATH%;$3$\r$\n&amp;quot;&lt;br /&gt;
    FileClose $1&lt;br /&gt;
    SetRebootFlag true&lt;br /&gt;
    Goto AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  AddToPath_NT:&lt;br /&gt;
    ReadRegStr $1 ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot;&lt;br /&gt;
    StrCmp $1 &amp;quot;&amp;quot; AddToPath_NTdoIt&lt;br /&gt;
      Push $1&lt;br /&gt;
      Call Trim&lt;br /&gt;
      Pop $1&lt;br /&gt;
      StrCpy $0 &amp;quot;$1;$0&amp;quot;&lt;br /&gt;
    AddToPath_NTdoIt:&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot; $0&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  AddToPath_done:&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
; RemoveFromPath - Remove a given dir from the path&lt;br /&gt;
;     Input: head of the stack&lt;br /&gt;
&lt;br /&gt;
Function un.RemoveFromPath&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Push $1&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
&lt;br /&gt;
  IntFmt $6 &amp;quot;%c&amp;quot; 26 # DOS EOF&lt;br /&gt;
&lt;br /&gt;
  Call un.IsNT&lt;br /&gt;
  Pop $1&lt;br /&gt;
  StrCmp $1 1 unRemoveFromPath_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $1 $WINDIR 2&lt;br /&gt;
    FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; r&lt;br /&gt;
    GetTempFileName $4&lt;br /&gt;
    FileOpen $2 $4 w&lt;br /&gt;
    GetFullPathName /SHORT $0 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;SET PATH=%PATH%;$0&amp;quot;&lt;br /&gt;
    Goto unRemoveFromPath_dosLoop&lt;br /&gt;
&lt;br /&gt;
    unRemoveFromPath_dosLoop:&lt;br /&gt;
      FileRead $1 $3&lt;br /&gt;
      StrCpy $5 $3 1 -1 # read last char&lt;br /&gt;
      StrCmp $5 $6 0 +2 # if DOS EOF&lt;br /&gt;
        StrCpy $3 $3 -1 # remove DOS EOF so we can compare&lt;br /&gt;
      StrCmp $3 &amp;quot;$0$\r$\n&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;$0$\n&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;$0&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;&amp;quot; unRemoveFromPath_dosLoopEnd&lt;br /&gt;
      FileWrite $2 $3&lt;br /&gt;
      Goto unRemoveFromPath_dosLoop&lt;br /&gt;
      unRemoveFromPath_dosLoopRemoveLine:&lt;br /&gt;
        SetRebootFlag true&lt;br /&gt;
        Goto unRemoveFromPath_dosLoop&lt;br /&gt;
&lt;br /&gt;
    unRemoveFromPath_dosLoopEnd:&lt;br /&gt;
      FileClose $2&lt;br /&gt;
      FileClose $1&lt;br /&gt;
      StrCpy $1 $WINDIR 2&lt;br /&gt;
      Delete &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
      CopyFiles /SILENT $4 &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
      Delete $4&lt;br /&gt;
      Goto unRemoveFromPath_done&lt;br /&gt;
&lt;br /&gt;
  unRemoveFromPath_NT:&lt;br /&gt;
    ReadRegStr $1 ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot;&lt;br /&gt;
    StrCpy $5 $1 1 -1 # copy last char&lt;br /&gt;
    StrCmp $5 &amp;quot;;&amp;quot; +2 # if last char != ;&lt;br /&gt;
      StrCpy $1 &amp;quot;$1;&amp;quot; # append ;&lt;br /&gt;
    Push $1&lt;br /&gt;
    Push &amp;quot;$0;&amp;quot;&lt;br /&gt;
    Call un.StrStr ; Find `$0;` in $1&lt;br /&gt;
    Pop $2 ; pos of our dir&lt;br /&gt;
    StrCmp $2 &amp;quot;&amp;quot; unRemoveFromPath_done&lt;br /&gt;
      ; else, it is in path&lt;br /&gt;
      # $0 - path to add&lt;br /&gt;
      # $1 - path var&lt;br /&gt;
      StrLen $3 &amp;quot;$0;&amp;quot;&lt;br /&gt;
      StrLen $4 $2&lt;br /&gt;
      StrCpy $5 $1 -$4 # $5 is now the part before the path to remove&lt;br /&gt;
      StrCpy $6 $2 &amp;quot;&amp;quot; $3 # $6 is now the part after the path to remove&lt;br /&gt;
      StrCpy $3 $5$6&lt;br /&gt;
&lt;br /&gt;
      StrCpy $5 $3 1 -1 # copy last char&lt;br /&gt;
      StrCmp $5 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
        StrCpy $3 $3 -1 # remove last char&lt;br /&gt;
&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot; $3&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  unRemoveFromPath_done:&lt;br /&gt;
    Pop $6&lt;br /&gt;
    Pop $5&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; AddToEnvVar - Adds the given value to the given environment var&lt;br /&gt;
;        Input - head of the stack $0 environement variable $1=value to add&lt;br /&gt;
;        Note - Win9x systems requires reboot&lt;br /&gt;
 &lt;br /&gt;
Function AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
  Exch $1 ; $1 has environment variable value&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $0 ; $0 has environment variable name&lt;br /&gt;
&lt;br /&gt;
  DetailPrint &amp;quot;Adding $1 to $0&amp;quot;&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
  ReadEnvStr $2 $0&lt;br /&gt;
  Push &amp;quot;$2;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $3&lt;br /&gt;
  StrCmp $3 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToEnvVar_done&lt;br /&gt;
&lt;br /&gt;
  Push &amp;quot;$2;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$1\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $3&lt;br /&gt;
  StrCmp $3 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToEnvVar_done&lt;br /&gt;
  &lt;br /&gt;
 &lt;br /&gt;
  Call IsNT&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 1 AddToEnvVar_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $2 $WINDIR 2&lt;br /&gt;
    FileOpen $2 &amp;quot;$2\autoexec.bat&amp;quot; a&lt;br /&gt;
    FileSeek $2 -1 END&lt;br /&gt;
    FileReadByte $2 $3&lt;br /&gt;
    IntCmp $3 26 0 +2 +2 # DOS EOF&lt;br /&gt;
      FileSeek $2 -1 END # write over EOF&lt;br /&gt;
    FileWrite $2 &amp;quot;$\r$\nSET $0=%$0%;$4$\r$\n&amp;quot;&lt;br /&gt;
    FileClose $2&lt;br /&gt;
    SetRebootFlag true&lt;br /&gt;
    Goto AddToEnvVar_done&lt;br /&gt;
 &lt;br /&gt;
  AddToEnvVar_NT:&lt;br /&gt;
    ReadRegStr $2 ${WriteEnvStr_RegKey} $0&lt;br /&gt;
    StrCpy $3 $2 1 -1 # copy last char&lt;br /&gt;
    StrCmp $3 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
      StrCpy $2 $2 -1 # remove last char&lt;br /&gt;
    StrCmp $2 &amp;quot;&amp;quot; AddToEnvVar_NTdoIt&lt;br /&gt;
      StrCpy $1 &amp;quot;$2;$1&amp;quot;&lt;br /&gt;
    AddToEnvVar_NTdoIt:&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $1&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  AddToEnvVar_done:&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Pop $1&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
 &lt;br /&gt;
; RemoveFromEnvVar - Remove a given value from a environment var&lt;br /&gt;
;     Input: head of the stack&lt;br /&gt;
 &lt;br /&gt;
Function un.RemoveFromEnvVar&lt;br /&gt;
&lt;br /&gt;
  Exch $1 ; $1 has environment variable value&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $0 ; $0 has environment variable name&lt;br /&gt;
&lt;br /&gt;
  DetailPrint &amp;quot;Removing $1 from $0&amp;quot;&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
 &lt;br /&gt;
  IntFmt $7 &amp;quot;%c&amp;quot; 26 # DOS EOF&lt;br /&gt;
 &lt;br /&gt;
  Call un.IsNT&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 1 unRemoveFromEnvVar_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $2 $WINDIR 2&lt;br /&gt;
    FileOpen $2 &amp;quot;$2\autoexec.bat&amp;quot; r&lt;br /&gt;
    GetTempFileName $5&lt;br /&gt;
    FileOpen $3 $5 w&lt;br /&gt;
    GetFullPathName /SHORT $1 $1&lt;br /&gt;
    StrCpy $1 &amp;quot;SET $0=%$0%;$1&amp;quot;&lt;br /&gt;
    Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
 &lt;br /&gt;
    unRemoveFromEnvVar_dosLoop:&lt;br /&gt;
      FileRead $2 $4&lt;br /&gt;
      StrCpy $6 $4 1 -1 # read last char&lt;br /&gt;
      StrCmp $6 $7 0 +2 # if DOS EOF&lt;br /&gt;
        StrCpy $4 $4 -1 # remove DOS EOF so we can compare&lt;br /&gt;
      StrCmp $4 &amp;quot;$1$\r$\n&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;$1$\n&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;$1&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;&amp;quot; unRemoveFromEnvVar_dosLoopEnd&lt;br /&gt;
      FileWrite $3 $4&lt;br /&gt;
      Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
      unRemoveFromEnvVar_dosLoopRemoveLine:&lt;br /&gt;
        SetRebootFlag true&lt;br /&gt;
        Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
 &lt;br /&gt;
    unRemoveFromEnvVar_dosLoopEnd:&lt;br /&gt;
      FileClose $3&lt;br /&gt;
      FileClose $2&lt;br /&gt;
      StrCpy $2 $WINDIR 2&lt;br /&gt;
      Delete &amp;quot;$2\autoexec.bat&amp;quot;&lt;br /&gt;
      CopyFiles /SILENT $5 &amp;quot;$2\autoexec.bat&amp;quot;&lt;br /&gt;
      Delete $5&lt;br /&gt;
      Goto unRemoveFromEnvVar_done&lt;br /&gt;
 &lt;br /&gt;
  unRemoveFromEnvVar_NT:&lt;br /&gt;
    ReadRegStr $2 ${WriteEnvStr_RegKey} $0&lt;br /&gt;
    StrCpy $6 $2 1 -1 # copy last char&lt;br /&gt;
    StrCmp $6 &amp;quot;;&amp;quot; +2 # if last char != ;&lt;br /&gt;
      StrCpy $2 &amp;quot;$2;&amp;quot; # append ;&lt;br /&gt;
    Push $2&lt;br /&gt;
    Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
    Call un.StrStr ; Find `$1;` in $2&lt;br /&gt;
    Pop $3 ; pos of our dir&lt;br /&gt;
    StrCmp $3 &amp;quot;&amp;quot; unRemoveFromEnvVar_done&lt;br /&gt;
      ; else, it is in path&lt;br /&gt;
      # $1 - path to add&lt;br /&gt;
      # $2 - path var&lt;br /&gt;
      StrLen $4 &amp;quot;$1;&amp;quot;&lt;br /&gt;
      StrLen $5 $3&lt;br /&gt;
      StrCpy $6 $2 -$5 # $6 is now the part before the path to remove&lt;br /&gt;
      StrCpy $7 $3 &amp;quot;&amp;quot; $4 # $7 is now the part after the path to remove&lt;br /&gt;
      StrCpy $4 $6$7&lt;br /&gt;
 &lt;br /&gt;
      StrCpy $6 $4 1 -1 # copy last char&lt;br /&gt;
      StrCmp $6 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
      StrCpy $4 $4 -1 # remove last char&lt;br /&gt;
 &lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $4&lt;br /&gt;
&lt;br /&gt;
      ; delete reg value if null&lt;br /&gt;
      StrCmp $4 &amp;quot;&amp;quot; 0 +2 # if null delete reg&lt;br /&gt;
      DeleteRegValue ${WriteEnvStr_RegKey} $0&lt;br /&gt;
&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
 &lt;br /&gt;
  unRemoveFromEnvVar_done:&lt;br /&gt;
    Pop $7&lt;br /&gt;
    Pop $6&lt;br /&gt;
    Pop $5&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
!ifndef IsNT_KiCHiK&lt;br /&gt;
!define IsNT_KiCHiK&lt;br /&gt;
&lt;br /&gt;
###########################################&lt;br /&gt;
#            Utility Functions            #&lt;br /&gt;
###########################################&lt;br /&gt;
&lt;br /&gt;
; IsNT&lt;br /&gt;
; no input&lt;br /&gt;
; output, top of the stack = 1 if NT or 0 if not&lt;br /&gt;
;&lt;br /&gt;
; Usage:&lt;br /&gt;
;   Call IsNT&lt;br /&gt;
;   Pop $R0&lt;br /&gt;
;  ($R0 at this point is 1 or 0)&lt;br /&gt;
&lt;br /&gt;
!macro IsNT un&lt;br /&gt;
Function ${un}IsNT&lt;br /&gt;
  Push $0&lt;br /&gt;
  ReadRegStr $0 HKLM &amp;quot;SOFTWARE\Microsoft\Windows NT\CurrentVersion&amp;quot; CurrentVersion&lt;br /&gt;
  StrCmp $0 &amp;quot;&amp;quot; 0 IsNT_yes&lt;br /&gt;
  ; we are not NT.&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Push 0&lt;br /&gt;
  Return&lt;br /&gt;
&lt;br /&gt;
  IsNT_yes:&lt;br /&gt;
    ; NT!!!&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Push 1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro IsNT &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro IsNT &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!endif ; IsNT_KiCHiK&lt;br /&gt;
&lt;br /&gt;
; StrStr&lt;br /&gt;
; input, top of stack = string to search for&lt;br /&gt;
;        top of stack-1 = string to search in&lt;br /&gt;
; output, top of stack (replaces with the portion of the string remaining)&lt;br /&gt;
; modifies no other variables.&lt;br /&gt;
;&lt;br /&gt;
; Usage:&lt;br /&gt;
;   Push &amp;quot;this is a long ass string&amp;quot;&lt;br /&gt;
;   Push &amp;quot;ass&amp;quot;&lt;br /&gt;
;   Call StrStr&lt;br /&gt;
;   Pop $R0&lt;br /&gt;
;  ($R0 at this point is &amp;quot;ass string&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
!macro StrStr un&lt;br /&gt;
Function ${un}StrStr&lt;br /&gt;
Exch $R1 ; st=haystack,old$R1, $R1=needle&lt;br /&gt;
  Exch    ; st=old$R1,haystack&lt;br /&gt;
  Exch $R2 ; st=old$R1,old$R2, $R2=haystack&lt;br /&gt;
  Push $R3&lt;br /&gt;
  Push $R4&lt;br /&gt;
  Push $R5&lt;br /&gt;
  StrLen $R3 $R1&lt;br /&gt;
  StrCpy $R4 0&lt;br /&gt;
  ; $R1=needle&lt;br /&gt;
  ; $R2=haystack&lt;br /&gt;
  ; $R3=len(needle)&lt;br /&gt;
  ; $R4=cnt&lt;br /&gt;
  ; $R5=tmp&lt;br /&gt;
  loop:&lt;br /&gt;
    StrCpy $R5 $R2 $R3 $R4&lt;br /&gt;
    StrCmp $R5 $R1 done&lt;br /&gt;
    StrCmp $R5 &amp;quot;&amp;quot; done&lt;br /&gt;
    IntOp $R4 $R4 + 1&lt;br /&gt;
    Goto loop&lt;br /&gt;
done:&lt;br /&gt;
  StrCpy $R1 $R2 &amp;quot;&amp;quot; $R4&lt;br /&gt;
  Pop $R5&lt;br /&gt;
  Pop $R4&lt;br /&gt;
  Pop $R3&lt;br /&gt;
  Pop $R2&lt;br /&gt;
  Exch $R1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrStr &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrStr &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!endif ; _AddToPath_nsh&lt;br /&gt;
&lt;br /&gt;
Function Trim ; Added by Pelaca&lt;br /&gt;
	Exch $R1&lt;br /&gt;
	Push $R2&lt;br /&gt;
Loop:&lt;br /&gt;
	StrCpy $R2 &amp;quot;$R1&amp;quot; 1 -1&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot; &amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;$\n&amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;$\r&amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;;&amp;quot; RTrim&lt;br /&gt;
	GoTo Done&lt;br /&gt;
RTrim:	&lt;br /&gt;
	StrCpy $R1 &amp;quot;$R1&amp;quot; -1&lt;br /&gt;
	Goto Loop&lt;br /&gt;
Done:&lt;br /&gt;
	Pop $R2&lt;br /&gt;
	Exch $R1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Path_Manipulation&amp;diff=15630</id>
		<title>Path Manipulation</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Path_Manipulation&amp;diff=15630"/>
		<updated>2008-07-03T15:03:59Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}} &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname from the PATH environmental variable in either the &amp;quot;all users&amp;quot; (HKLM) or the &amp;quot;current user&amp;quot; (HKCU) section of the registry. &lt;br /&gt;
&lt;br /&gt;
Duplicates entries, leading and trailing spaces around each entry, and duplicate semicolons are removed from the contents of PATH before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname).&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
=== Syntax ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;Pathname&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;Pathname&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
:; ResultVar&lt;br /&gt;
:: Updated contents PATH returned by the function&lt;br /&gt;
&lt;br /&gt;
:; EnvVarName&lt;br /&gt;
:: &amp;quot;PATH&amp;quot; &lt;br /&gt;
&lt;br /&gt;
:; Action&lt;br /&gt;
:: &amp;quot;A&amp;quot; = Append&lt;br /&gt;
:: &amp;quot;P&amp;quot; = Prepend&lt;br /&gt;
:: &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
:; RegLoc&lt;br /&gt;
:: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
:: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
:; Pathname&lt;br /&gt;
:: Pathname to add to or remove from the contents of PATH (e.g., &amp;quot;C:\MyApp&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\Windows Resource Kits\Tools&amp;quot;  &lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;%WinDir%\System32&amp;quot;  &lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v1.0&amp;quot;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v2.0&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v1.0&amp;quot;   &lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v2.0&amp;quot;   &lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dependencies == &lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;EnvVarUpdate&#039;&#039;&#039; (available at  [[Environmental_Variables:_append%2C_prepend%2C_and_remove_entries]])&lt;br /&gt;
* &#039;&#039;&#039;StrTok, StrContains, and StrReplace:&#039;&#039;&#039;  Included in the EnvVarUpdate function code &lt;br /&gt;
* &#039;&#039;&#039;LogicLib header file:&#039;&#039;&#039; &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
&lt;br /&gt;
* Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
* Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr  &lt;br /&gt;
* Diego Pedroso (deguix) for StrTok&lt;br /&gt;
* Kevin English (kenglish_hi)for StrContains&lt;br /&gt;
* Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry (dandaman32) for StrReplace&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Functions for Windows 95, 98, and ME ==&lt;br /&gt;
{{PageAuthor|KiCHiK}}&lt;br /&gt;
The following routines, AddToPath, un.RemoveFromPath, AddToEnvVar, and un.RemoveFromEnvVar are provided for Windows 95, 98, or ME in that they support the update of the autoexec.bat file.  Note that they can cause corruption of the PATH if the path being removed happens to be a subset of another path.   For example, if PATH contains &amp;quot;C:\Windows\system32\wbem&amp;quot; and you remove&lt;br /&gt;
&amp;quot;C:\Windows\system32&amp;quot; the result is &amp;quot;\wbem&amp;quot;.  They also do not prevent duplication of entries if ,for example, the user runs the installer multiple times.    &lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Here are four functions, two for adding to and removing directories from the search path (i.e. PATH environment variable) of Windows and two more for adding to and removing directories from a user defined environment variable such as INCLUDE or LIB etc. These functions should work on every version of Windows including 95, 98, ME, NT, 2000, and XP.&lt;br /&gt;
&lt;br /&gt;
For Windows NT/2000/XP they will write to HKEY_CURRENT_USER\Environment\PATH. For 9x/ME they will write to the autoexec.bat file.&lt;br /&gt;
&lt;br /&gt;
Changes on 9x machines will take place after a reboot. These functions set the reboot flag if the path variable was changed on 9x.&lt;br /&gt;
&lt;br /&gt;
These functions require NSIS 2.0b0 and above due to the usage of SendMessage with /TIMEOUT. It is possible to use it with earlier versions of NSIS with a little application I have created called RefreshEnv. It does exactly the same as SendMessage with /TIMEOUT. You can find it at [http://forums.winamp.com/showthread.php?s=&amp;amp;threadid=77904&amp;amp;highlight=refreshenv this forum thread].&lt;br /&gt;
&lt;br /&gt;
The directory added to the path must exist prior to calling this function.&lt;br /&gt;
&lt;br /&gt;
=== Usage Example ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;Section &amp;quot;Add to path&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call AddToPath&lt;br /&gt;
&lt;br /&gt;
  Push &amp;quot;LIB&amp;quot;&lt;br /&gt;
  Push &amp;quot;c:\Mylibrary\lib&amp;quot;&lt;br /&gt;
  Call AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
  ;likewise AddToPath could be&lt;br /&gt;
  Push &amp;quot;PATH&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
SectionEnd&lt;br /&gt;
&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Section &amp;quot;uninstall&amp;quot;&lt;br /&gt;
  # ...&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call un.RemoveFromPath&lt;br /&gt;
  # ...&lt;br /&gt;
  Push &amp;quot;LIB&amp;quot;&lt;br /&gt;
  Push &amp;quot;c:\Mylibrary\lib&amp;quot;&lt;br /&gt;
  Call un.RemoveFromEnvVar&lt;br /&gt;
&lt;br /&gt;
  ;Likewise RemoveFromPath could be&lt;br /&gt;
  Push &amp;quot;PATH&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call un.RemoveFromEnvVar&lt;br /&gt;
  &lt;br /&gt;
SectionEnd&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Functions ===&lt;br /&gt;
The functions in the flesh:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;!ifndef _AddToPath_nsh&lt;br /&gt;
!define _AddToPath_nsh&lt;br /&gt;
&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
!verbose 4&lt;br /&gt;
&lt;br /&gt;
!ifndef WriteEnvStr_RegKey&lt;br /&gt;
  !ifdef ALL_USERS&lt;br /&gt;
    !define WriteEnvStr_RegKey \&lt;br /&gt;
       &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
  !else&lt;br /&gt;
    !define WriteEnvStr_RegKey &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
  !endif&lt;br /&gt;
!endif&lt;br /&gt;
&lt;br /&gt;
; AddToPath - Adds the given dir to the search path.&lt;br /&gt;
;        Input - head of the stack&lt;br /&gt;
;        Note - Win9x systems requires reboot&lt;br /&gt;
&lt;br /&gt;
Function AddToPath&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Push $1&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
&lt;br /&gt;
  # don&#039;t add if the path doesn&#039;t exist&lt;br /&gt;
  IfFileExists &amp;quot;$0\*.*&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  ReadEnvStr $1 PATH&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$0;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$0\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  GetFullPathName /SHORT $3 $0&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$3;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$3\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  Call IsNT&lt;br /&gt;
  Pop $1&lt;br /&gt;
  StrCmp $1 1 AddToPath_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $1 $WINDIR 2&lt;br /&gt;
    FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; a&lt;br /&gt;
    FileSeek $1 -1 END&lt;br /&gt;
    FileReadByte $1 $2&lt;br /&gt;
    IntCmp $2 26 0 +2 +2 # DOS EOF&lt;br /&gt;
      FileSeek $1 -1 END # write over EOF&lt;br /&gt;
    FileWrite $1 &amp;quot;$\r$\nSET PATH=%PATH%;$3$\r$\n&amp;quot;&lt;br /&gt;
    FileClose $1&lt;br /&gt;
    SetRebootFlag true&lt;br /&gt;
    Goto AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  AddToPath_NT:&lt;br /&gt;
    ReadRegStr $1 ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot;&lt;br /&gt;
    StrCmp $1 &amp;quot;&amp;quot; AddToPath_NTdoIt&lt;br /&gt;
      Push $1&lt;br /&gt;
      Call Trim&lt;br /&gt;
      Pop $1&lt;br /&gt;
      StrCpy $0 &amp;quot;$1;$0&amp;quot;&lt;br /&gt;
    AddToPath_NTdoIt:&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot; $0&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  AddToPath_done:&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
; RemoveFromPath - Remove a given dir from the path&lt;br /&gt;
;     Input: head of the stack&lt;br /&gt;
&lt;br /&gt;
Function un.RemoveFromPath&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Push $1&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
&lt;br /&gt;
  IntFmt $6 &amp;quot;%c&amp;quot; 26 # DOS EOF&lt;br /&gt;
&lt;br /&gt;
  Call un.IsNT&lt;br /&gt;
  Pop $1&lt;br /&gt;
  StrCmp $1 1 unRemoveFromPath_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $1 $WINDIR 2&lt;br /&gt;
    FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; r&lt;br /&gt;
    GetTempFileName $4&lt;br /&gt;
    FileOpen $2 $4 w&lt;br /&gt;
    GetFullPathName /SHORT $0 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;SET PATH=%PATH%;$0&amp;quot;&lt;br /&gt;
    Goto unRemoveFromPath_dosLoop&lt;br /&gt;
&lt;br /&gt;
    unRemoveFromPath_dosLoop:&lt;br /&gt;
      FileRead $1 $3&lt;br /&gt;
      StrCpy $5 $3 1 -1 # read last char&lt;br /&gt;
      StrCmp $5 $6 0 +2 # if DOS EOF&lt;br /&gt;
        StrCpy $3 $3 -1 # remove DOS EOF so we can compare&lt;br /&gt;
      StrCmp $3 &amp;quot;$0$\r$\n&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;$0$\n&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;$0&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;&amp;quot; unRemoveFromPath_dosLoopEnd&lt;br /&gt;
      FileWrite $2 $3&lt;br /&gt;
      Goto unRemoveFromPath_dosLoop&lt;br /&gt;
      unRemoveFromPath_dosLoopRemoveLine:&lt;br /&gt;
        SetRebootFlag true&lt;br /&gt;
        Goto unRemoveFromPath_dosLoop&lt;br /&gt;
&lt;br /&gt;
    unRemoveFromPath_dosLoopEnd:&lt;br /&gt;
      FileClose $2&lt;br /&gt;
      FileClose $1&lt;br /&gt;
      StrCpy $1 $WINDIR 2&lt;br /&gt;
      Delete &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
      CopyFiles /SILENT $4 &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
      Delete $4&lt;br /&gt;
      Goto unRemoveFromPath_done&lt;br /&gt;
&lt;br /&gt;
  unRemoveFromPath_NT:&lt;br /&gt;
    ReadRegStr $1 ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot;&lt;br /&gt;
    StrCpy $5 $1 1 -1 # copy last char&lt;br /&gt;
    StrCmp $5 &amp;quot;;&amp;quot; +2 # if last char != ;&lt;br /&gt;
      StrCpy $1 &amp;quot;$1;&amp;quot; # append ;&lt;br /&gt;
    Push $1&lt;br /&gt;
    Push &amp;quot;$0;&amp;quot;&lt;br /&gt;
    Call un.StrStr ; Find `$0;` in $1&lt;br /&gt;
    Pop $2 ; pos of our dir&lt;br /&gt;
    StrCmp $2 &amp;quot;&amp;quot; unRemoveFromPath_done&lt;br /&gt;
      ; else, it is in path&lt;br /&gt;
      # $0 - path to add&lt;br /&gt;
      # $1 - path var&lt;br /&gt;
      StrLen $3 &amp;quot;$0;&amp;quot;&lt;br /&gt;
      StrLen $4 $2&lt;br /&gt;
      StrCpy $5 $1 -$4 # $5 is now the part before the path to remove&lt;br /&gt;
      StrCpy $6 $2 &amp;quot;&amp;quot; $3 # $6 is now the part after the path to remove&lt;br /&gt;
      StrCpy $3 $5$6&lt;br /&gt;
&lt;br /&gt;
      StrCpy $5 $3 1 -1 # copy last char&lt;br /&gt;
      StrCmp $5 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
        StrCpy $3 $3 -1 # remove last char&lt;br /&gt;
&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot; $3&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  unRemoveFromPath_done:&lt;br /&gt;
    Pop $6&lt;br /&gt;
    Pop $5&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; AddToEnvVar - Adds the given value to the given environment var&lt;br /&gt;
;        Input - head of the stack $0 environement variable $1=value to add&lt;br /&gt;
;        Note - Win9x systems requires reboot&lt;br /&gt;
 &lt;br /&gt;
Function AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
  Exch $1 ; $1 has environment variable value&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $0 ; $0 has environment variable name&lt;br /&gt;
&lt;br /&gt;
  DetailPrint &amp;quot;Adding $1 to $0&amp;quot;&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
  ReadEnvStr $2 $0&lt;br /&gt;
  Push &amp;quot;$2;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $3&lt;br /&gt;
  StrCmp $3 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToEnvVar_done&lt;br /&gt;
&lt;br /&gt;
  Push &amp;quot;$2;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$1\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $3&lt;br /&gt;
  StrCmp $3 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToEnvVar_done&lt;br /&gt;
  &lt;br /&gt;
 &lt;br /&gt;
  Call IsNT&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 1 AddToEnvVar_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $2 $WINDIR 2&lt;br /&gt;
    FileOpen $2 &amp;quot;$2\autoexec.bat&amp;quot; a&lt;br /&gt;
    FileSeek $2 -1 END&lt;br /&gt;
    FileReadByte $2 $3&lt;br /&gt;
    IntCmp $3 26 0 +2 +2 # DOS EOF&lt;br /&gt;
      FileSeek $2 -1 END # write over EOF&lt;br /&gt;
    FileWrite $2 &amp;quot;$\r$\nSET $0=%$0%;$4$\r$\n&amp;quot;&lt;br /&gt;
    FileClose $2&lt;br /&gt;
    SetRebootFlag true&lt;br /&gt;
    Goto AddToEnvVar_done&lt;br /&gt;
 &lt;br /&gt;
  AddToEnvVar_NT:&lt;br /&gt;
    ReadRegStr $2 ${WriteEnvStr_RegKey} $0&lt;br /&gt;
    StrCpy $3 $2 1 -1 # copy last char&lt;br /&gt;
    StrCmp $3 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
      StrCpy $2 $2 -1 # remove last char&lt;br /&gt;
    StrCmp $2 &amp;quot;&amp;quot; AddToEnvVar_NTdoIt&lt;br /&gt;
      StrCpy $1 &amp;quot;$2;$1&amp;quot;&lt;br /&gt;
    AddToEnvVar_NTdoIt:&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $1&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  AddToEnvVar_done:&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Pop $1&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
 &lt;br /&gt;
; RemoveFromEnvVar - Remove a given value from a environment var&lt;br /&gt;
;     Input: head of the stack&lt;br /&gt;
 &lt;br /&gt;
Function un.RemoveFromEnvVar&lt;br /&gt;
&lt;br /&gt;
  Exch $1 ; $1 has environment variable value&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $0 ; $0 has environment variable name&lt;br /&gt;
&lt;br /&gt;
  DetailPrint &amp;quot;Removing $1 from $0&amp;quot;&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
 &lt;br /&gt;
  IntFmt $7 &amp;quot;%c&amp;quot; 26 # DOS EOF&lt;br /&gt;
 &lt;br /&gt;
  Call un.IsNT&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 1 unRemoveFromEnvVar_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $2 $WINDIR 2&lt;br /&gt;
    FileOpen $2 &amp;quot;$2\autoexec.bat&amp;quot; r&lt;br /&gt;
    GetTempFileName $5&lt;br /&gt;
    FileOpen $3 $5 w&lt;br /&gt;
    GetFullPathName /SHORT $1 $1&lt;br /&gt;
    StrCpy $1 &amp;quot;SET $0=%$0%;$1&amp;quot;&lt;br /&gt;
    Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
 &lt;br /&gt;
    unRemoveFromEnvVar_dosLoop:&lt;br /&gt;
      FileRead $2 $4&lt;br /&gt;
      StrCpy $6 $4 1 -1 # read last char&lt;br /&gt;
      StrCmp $6 $7 0 +2 # if DOS EOF&lt;br /&gt;
        StrCpy $4 $4 -1 # remove DOS EOF so we can compare&lt;br /&gt;
      StrCmp $4 &amp;quot;$1$\r$\n&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;$1$\n&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;$1&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;&amp;quot; unRemoveFromEnvVar_dosLoopEnd&lt;br /&gt;
      FileWrite $3 $4&lt;br /&gt;
      Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
      unRemoveFromEnvVar_dosLoopRemoveLine:&lt;br /&gt;
        SetRebootFlag true&lt;br /&gt;
        Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
 &lt;br /&gt;
    unRemoveFromEnvVar_dosLoopEnd:&lt;br /&gt;
      FileClose $3&lt;br /&gt;
      FileClose $2&lt;br /&gt;
      StrCpy $2 $WINDIR 2&lt;br /&gt;
      Delete &amp;quot;$2\autoexec.bat&amp;quot;&lt;br /&gt;
      CopyFiles /SILENT $5 &amp;quot;$2\autoexec.bat&amp;quot;&lt;br /&gt;
      Delete $5&lt;br /&gt;
      Goto unRemoveFromEnvVar_done&lt;br /&gt;
 &lt;br /&gt;
  unRemoveFromEnvVar_NT:&lt;br /&gt;
    ReadRegStr $2 ${WriteEnvStr_RegKey} $0&lt;br /&gt;
    StrCpy $6 $2 1 -1 # copy last char&lt;br /&gt;
    StrCmp $6 &amp;quot;;&amp;quot; +2 # if last char != ;&lt;br /&gt;
      StrCpy $2 &amp;quot;$2;&amp;quot; # append ;&lt;br /&gt;
    Push $2&lt;br /&gt;
    Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
    Call un.StrStr ; Find `$1;` in $2&lt;br /&gt;
    Pop $3 ; pos of our dir&lt;br /&gt;
    StrCmp $3 &amp;quot;&amp;quot; unRemoveFromEnvVar_done&lt;br /&gt;
      ; else, it is in path&lt;br /&gt;
      # $1 - path to add&lt;br /&gt;
      # $2 - path var&lt;br /&gt;
      StrLen $4 &amp;quot;$1;&amp;quot;&lt;br /&gt;
      StrLen $5 $3&lt;br /&gt;
      StrCpy $6 $2 -$5 # $6 is now the part before the path to remove&lt;br /&gt;
      StrCpy $7 $3 &amp;quot;&amp;quot; $4 # $7 is now the part after the path to remove&lt;br /&gt;
      StrCpy $4 $6$7&lt;br /&gt;
 &lt;br /&gt;
      StrCpy $6 $4 1 -1 # copy last char&lt;br /&gt;
      StrCmp $6 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
      StrCpy $4 $4 -1 # remove last char&lt;br /&gt;
 &lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $4&lt;br /&gt;
&lt;br /&gt;
      ; delete reg value if null&lt;br /&gt;
      StrCmp $4 &amp;quot;&amp;quot; 0 +2 # if null delete reg&lt;br /&gt;
      DeleteRegValue ${WriteEnvStr_RegKey} $0&lt;br /&gt;
&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
 &lt;br /&gt;
  unRemoveFromEnvVar_done:&lt;br /&gt;
    Pop $7&lt;br /&gt;
    Pop $6&lt;br /&gt;
    Pop $5&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
!ifndef IsNT_KiCHiK&lt;br /&gt;
!define IsNT_KiCHiK&lt;br /&gt;
&lt;br /&gt;
###########################################&lt;br /&gt;
#            Utility Functions            #&lt;br /&gt;
###########################################&lt;br /&gt;
&lt;br /&gt;
; IsNT&lt;br /&gt;
; no input&lt;br /&gt;
; output, top of the stack = 1 if NT or 0 if not&lt;br /&gt;
;&lt;br /&gt;
; Usage:&lt;br /&gt;
;   Call IsNT&lt;br /&gt;
;   Pop $R0&lt;br /&gt;
;  ($R0 at this point is 1 or 0)&lt;br /&gt;
&lt;br /&gt;
!macro IsNT un&lt;br /&gt;
Function ${un}IsNT&lt;br /&gt;
  Push $0&lt;br /&gt;
  ReadRegStr $0 HKLM &amp;quot;SOFTWARE\Microsoft\Windows NT\CurrentVersion&amp;quot; CurrentVersion&lt;br /&gt;
  StrCmp $0 &amp;quot;&amp;quot; 0 IsNT_yes&lt;br /&gt;
  ; we are not NT.&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Push 0&lt;br /&gt;
  Return&lt;br /&gt;
&lt;br /&gt;
  IsNT_yes:&lt;br /&gt;
    ; NT!!!&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Push 1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro IsNT &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro IsNT &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!endif ; IsNT_KiCHiK&lt;br /&gt;
&lt;br /&gt;
; StrStr&lt;br /&gt;
; input, top of stack = string to search for&lt;br /&gt;
;        top of stack-1 = string to search in&lt;br /&gt;
; output, top of stack (replaces with the portion of the string remaining)&lt;br /&gt;
; modifies no other variables.&lt;br /&gt;
;&lt;br /&gt;
; Usage:&lt;br /&gt;
;   Push &amp;quot;this is a long ass string&amp;quot;&lt;br /&gt;
;   Push &amp;quot;ass&amp;quot;&lt;br /&gt;
;   Call StrStr&lt;br /&gt;
;   Pop $R0&lt;br /&gt;
;  ($R0 at this point is &amp;quot;ass string&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
!macro StrStr un&lt;br /&gt;
Function ${un}StrStr&lt;br /&gt;
Exch $R1 ; st=haystack,old$R1, $R1=needle&lt;br /&gt;
  Exch    ; st=old$R1,haystack&lt;br /&gt;
  Exch $R2 ; st=old$R1,old$R2, $R2=haystack&lt;br /&gt;
  Push $R3&lt;br /&gt;
  Push $R4&lt;br /&gt;
  Push $R5&lt;br /&gt;
  StrLen $R3 $R1&lt;br /&gt;
  StrCpy $R4 0&lt;br /&gt;
  ; $R1=needle&lt;br /&gt;
  ; $R2=haystack&lt;br /&gt;
  ; $R3=len(needle)&lt;br /&gt;
  ; $R4=cnt&lt;br /&gt;
  ; $R5=tmp&lt;br /&gt;
  loop:&lt;br /&gt;
    StrCpy $R5 $R2 $R3 $R4&lt;br /&gt;
    StrCmp $R5 $R1 done&lt;br /&gt;
    StrCmp $R5 &amp;quot;&amp;quot; done&lt;br /&gt;
    IntOp $R4 $R4 + 1&lt;br /&gt;
    Goto loop&lt;br /&gt;
done:&lt;br /&gt;
  StrCpy $R1 $R2 &amp;quot;&amp;quot; $R4&lt;br /&gt;
  Pop $R5&lt;br /&gt;
  Pop $R4&lt;br /&gt;
  Pop $R3&lt;br /&gt;
  Pop $R2&lt;br /&gt;
  Exch $R1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrStr &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrStr &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!endif ; _AddToPath_nsh&lt;br /&gt;
&lt;br /&gt;
Function Trim ; Added by Pelaca&lt;br /&gt;
	Exch $R1&lt;br /&gt;
	Push $R2&lt;br /&gt;
Loop:&lt;br /&gt;
	StrCpy $R2 &amp;quot;$R1&amp;quot; 1 -1&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot; &amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;$\n&amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;$\r&amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;;&amp;quot; RTrim&lt;br /&gt;
	GoTo Done&lt;br /&gt;
RTrim:	&lt;br /&gt;
	StrCpy $R1 &amp;quot;$R1&amp;quot; -1&lt;br /&gt;
	Goto Loop&lt;br /&gt;
Done:&lt;br /&gt;
	Pop $R2&lt;br /&gt;
	Exch $R1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Path_Manipulation&amp;diff=15629</id>
		<title>Path Manipulation</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Path_Manipulation&amp;diff=15629"/>
		<updated>2008-07-03T14:55:56Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Credits */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2KiCHiK}} {{PageAuthor|KiCHiK}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname from the PATH environmental variable in either the &amp;quot;all users&amp;quot; (HKLM) or the &amp;quot;current user&amp;quot; (HKCU) section of the registry. &lt;br /&gt;
&lt;br /&gt;
Duplicates entries, leading and trailing spaces around each entry, and duplicate semicolons are removed from the contents of PATH before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname).&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
=== Syntax ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;Pathname&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;Pathname&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
:; ResultVar&lt;br /&gt;
:: Updated contents PATH returned by the function&lt;br /&gt;
&lt;br /&gt;
:; EnvVarName&lt;br /&gt;
:: &amp;quot;PATH&amp;quot; &lt;br /&gt;
&lt;br /&gt;
:; Action&lt;br /&gt;
:: &amp;quot;A&amp;quot; = Append&lt;br /&gt;
:: &amp;quot;P&amp;quot; = Prepend&lt;br /&gt;
:: &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
:; RegLoc&lt;br /&gt;
:: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
:: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
:; Pathname&lt;br /&gt;
:: Pathname to add to or remove from the contents of PATH (e.g., &amp;quot;C:\MyApp&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\Windows Resource Kits\Tools&amp;quot;  &lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;%WinDir%\System32&amp;quot;  &lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v1.0&amp;quot;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v2.0&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v1.0&amp;quot;   &lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v2.0&amp;quot;   &lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dependencies == &lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;EnvVarUpdate&#039;&#039;&#039; (available at  [[Environmental_Variables:_append%2C_prepend%2C_and_remove_entries]])&lt;br /&gt;
* &#039;&#039;&#039;StrTok, StrContains, and StrReplace:&#039;&#039;&#039;  Included in the EnvVarUpdate function code &lt;br /&gt;
* &#039;&#039;&#039;LogicLib header file:&#039;&#039;&#039; &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
&lt;br /&gt;
* Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
* Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr  &lt;br /&gt;
* Diego Pedroso (deguix) for StrTok&lt;br /&gt;
* Kevin English (kenglish_hi)for StrContains&lt;br /&gt;
* Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry (dandaman32) for StrReplace&lt;br /&gt;
&lt;br /&gt;
== Functions for Windows 95, 98, and ME ==&lt;br /&gt;
&lt;br /&gt;
The following routines, AddToPath, un.RemoveFromPath, AddToEnvVar, and un.RemoveFromEnvVar are provided for Windows 95, 98, or ME in that they support the update of the autoexec.bat file.  Note that they can cause corruption of the PATH if the path being removed happens to be a subset of another path.   For example, if PATH contains &amp;quot;C:\Windows\system32\wbem&amp;quot; and you remove&lt;br /&gt;
&amp;quot;C:\Windows\system32&amp;quot; the result is &amp;quot;\wbem&amp;quot;.  They also do not prevent duplication of entries if ,for example, the user runs the installer multiple times.    &lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Here are four functions, two for adding to and removing directories from the search path (i.e. PATH environment variable) of Windows and two more for adding to and removing directories from a user defined environment variable such as INCLUDE or LIB etc. These functions should work on every version of Windows including 95, 98, ME, NT, 2000, and XP.&lt;br /&gt;
&lt;br /&gt;
For Windows NT/2000/XP they will write to HKEY_CURRENT_USER\Environment\PATH. For 9x/ME they will write to the autoexec.bat file.&lt;br /&gt;
&lt;br /&gt;
Changes on 9x machines will take place after a reboot. These functions set the reboot flag if the path variable was changed on 9x.&lt;br /&gt;
&lt;br /&gt;
These functions require NSIS 2.0b0 and above due to the usage of SendMessage with /TIMEOUT. It is possible to use it with earlier versions of NSIS with a little application I have created called RefreshEnv. It does exactly the same as SendMessage with /TIMEOUT. You can find it at [http://forums.winamp.com/showthread.php?s=&amp;amp;threadid=77904&amp;amp;highlight=refreshenv this forum thread].&lt;br /&gt;
&lt;br /&gt;
The directory added to the path must exist prior to calling this function.&lt;br /&gt;
&lt;br /&gt;
=== Usage Example ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;Section &amp;quot;Add to path&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call AddToPath&lt;br /&gt;
&lt;br /&gt;
  Push &amp;quot;LIB&amp;quot;&lt;br /&gt;
  Push &amp;quot;c:\Mylibrary\lib&amp;quot;&lt;br /&gt;
  Call AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
  ;likewise AddToPath could be&lt;br /&gt;
  Push &amp;quot;PATH&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
SectionEnd&lt;br /&gt;
&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Section &amp;quot;uninstall&amp;quot;&lt;br /&gt;
  # ...&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call un.RemoveFromPath&lt;br /&gt;
  # ...&lt;br /&gt;
  Push &amp;quot;LIB&amp;quot;&lt;br /&gt;
  Push &amp;quot;c:\Mylibrary\lib&amp;quot;&lt;br /&gt;
  Call un.RemoveFromEnvVar&lt;br /&gt;
&lt;br /&gt;
  ;Likewise RemoveFromPath could be&lt;br /&gt;
  Push &amp;quot;PATH&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call un.RemoveFromEnvVar&lt;br /&gt;
  &lt;br /&gt;
SectionEnd&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Functions ===&lt;br /&gt;
The functions in the flesh:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;!ifndef _AddToPath_nsh&lt;br /&gt;
!define _AddToPath_nsh&lt;br /&gt;
&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
!verbose 4&lt;br /&gt;
&lt;br /&gt;
!ifndef WriteEnvStr_RegKey&lt;br /&gt;
  !ifdef ALL_USERS&lt;br /&gt;
    !define WriteEnvStr_RegKey \&lt;br /&gt;
       &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
  !else&lt;br /&gt;
    !define WriteEnvStr_RegKey &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
  !endif&lt;br /&gt;
!endif&lt;br /&gt;
&lt;br /&gt;
; AddToPath - Adds the given dir to the search path.&lt;br /&gt;
;        Input - head of the stack&lt;br /&gt;
;        Note - Win9x systems requires reboot&lt;br /&gt;
&lt;br /&gt;
Function AddToPath&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Push $1&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
&lt;br /&gt;
  # don&#039;t add if the path doesn&#039;t exist&lt;br /&gt;
  IfFileExists &amp;quot;$0\*.*&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  ReadEnvStr $1 PATH&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$0;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$0\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  GetFullPathName /SHORT $3 $0&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$3;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$3\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  Call IsNT&lt;br /&gt;
  Pop $1&lt;br /&gt;
  StrCmp $1 1 AddToPath_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $1 $WINDIR 2&lt;br /&gt;
    FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; a&lt;br /&gt;
    FileSeek $1 -1 END&lt;br /&gt;
    FileReadByte $1 $2&lt;br /&gt;
    IntCmp $2 26 0 +2 +2 # DOS EOF&lt;br /&gt;
      FileSeek $1 -1 END # write over EOF&lt;br /&gt;
    FileWrite $1 &amp;quot;$\r$\nSET PATH=%PATH%;$3$\r$\n&amp;quot;&lt;br /&gt;
    FileClose $1&lt;br /&gt;
    SetRebootFlag true&lt;br /&gt;
    Goto AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  AddToPath_NT:&lt;br /&gt;
    ReadRegStr $1 ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot;&lt;br /&gt;
    StrCmp $1 &amp;quot;&amp;quot; AddToPath_NTdoIt&lt;br /&gt;
      Push $1&lt;br /&gt;
      Call Trim&lt;br /&gt;
      Pop $1&lt;br /&gt;
      StrCpy $0 &amp;quot;$1;$0&amp;quot;&lt;br /&gt;
    AddToPath_NTdoIt:&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot; $0&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  AddToPath_done:&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
; RemoveFromPath - Remove a given dir from the path&lt;br /&gt;
;     Input: head of the stack&lt;br /&gt;
&lt;br /&gt;
Function un.RemoveFromPath&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Push $1&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
&lt;br /&gt;
  IntFmt $6 &amp;quot;%c&amp;quot; 26 # DOS EOF&lt;br /&gt;
&lt;br /&gt;
  Call un.IsNT&lt;br /&gt;
  Pop $1&lt;br /&gt;
  StrCmp $1 1 unRemoveFromPath_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $1 $WINDIR 2&lt;br /&gt;
    FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; r&lt;br /&gt;
    GetTempFileName $4&lt;br /&gt;
    FileOpen $2 $4 w&lt;br /&gt;
    GetFullPathName /SHORT $0 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;SET PATH=%PATH%;$0&amp;quot;&lt;br /&gt;
    Goto unRemoveFromPath_dosLoop&lt;br /&gt;
&lt;br /&gt;
    unRemoveFromPath_dosLoop:&lt;br /&gt;
      FileRead $1 $3&lt;br /&gt;
      StrCpy $5 $3 1 -1 # read last char&lt;br /&gt;
      StrCmp $5 $6 0 +2 # if DOS EOF&lt;br /&gt;
        StrCpy $3 $3 -1 # remove DOS EOF so we can compare&lt;br /&gt;
      StrCmp $3 &amp;quot;$0$\r$\n&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;$0$\n&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;$0&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;&amp;quot; unRemoveFromPath_dosLoopEnd&lt;br /&gt;
      FileWrite $2 $3&lt;br /&gt;
      Goto unRemoveFromPath_dosLoop&lt;br /&gt;
      unRemoveFromPath_dosLoopRemoveLine:&lt;br /&gt;
        SetRebootFlag true&lt;br /&gt;
        Goto unRemoveFromPath_dosLoop&lt;br /&gt;
&lt;br /&gt;
    unRemoveFromPath_dosLoopEnd:&lt;br /&gt;
      FileClose $2&lt;br /&gt;
      FileClose $1&lt;br /&gt;
      StrCpy $1 $WINDIR 2&lt;br /&gt;
      Delete &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
      CopyFiles /SILENT $4 &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
      Delete $4&lt;br /&gt;
      Goto unRemoveFromPath_done&lt;br /&gt;
&lt;br /&gt;
  unRemoveFromPath_NT:&lt;br /&gt;
    ReadRegStr $1 ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot;&lt;br /&gt;
    StrCpy $5 $1 1 -1 # copy last char&lt;br /&gt;
    StrCmp $5 &amp;quot;;&amp;quot; +2 # if last char != ;&lt;br /&gt;
      StrCpy $1 &amp;quot;$1;&amp;quot; # append ;&lt;br /&gt;
    Push $1&lt;br /&gt;
    Push &amp;quot;$0;&amp;quot;&lt;br /&gt;
    Call un.StrStr ; Find `$0;` in $1&lt;br /&gt;
    Pop $2 ; pos of our dir&lt;br /&gt;
    StrCmp $2 &amp;quot;&amp;quot; unRemoveFromPath_done&lt;br /&gt;
      ; else, it is in path&lt;br /&gt;
      # $0 - path to add&lt;br /&gt;
      # $1 - path var&lt;br /&gt;
      StrLen $3 &amp;quot;$0;&amp;quot;&lt;br /&gt;
      StrLen $4 $2&lt;br /&gt;
      StrCpy $5 $1 -$4 # $5 is now the part before the path to remove&lt;br /&gt;
      StrCpy $6 $2 &amp;quot;&amp;quot; $3 # $6 is now the part after the path to remove&lt;br /&gt;
      StrCpy $3 $5$6&lt;br /&gt;
&lt;br /&gt;
      StrCpy $5 $3 1 -1 # copy last char&lt;br /&gt;
      StrCmp $5 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
        StrCpy $3 $3 -1 # remove last char&lt;br /&gt;
&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot; $3&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  unRemoveFromPath_done:&lt;br /&gt;
    Pop $6&lt;br /&gt;
    Pop $5&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; AddToEnvVar - Adds the given value to the given environment var&lt;br /&gt;
;        Input - head of the stack $0 environement variable $1=value to add&lt;br /&gt;
;        Note - Win9x systems requires reboot&lt;br /&gt;
 &lt;br /&gt;
Function AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
  Exch $1 ; $1 has environment variable value&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $0 ; $0 has environment variable name&lt;br /&gt;
&lt;br /&gt;
  DetailPrint &amp;quot;Adding $1 to $0&amp;quot;&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
  ReadEnvStr $2 $0&lt;br /&gt;
  Push &amp;quot;$2;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $3&lt;br /&gt;
  StrCmp $3 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToEnvVar_done&lt;br /&gt;
&lt;br /&gt;
  Push &amp;quot;$2;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$1\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $3&lt;br /&gt;
  StrCmp $3 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToEnvVar_done&lt;br /&gt;
  &lt;br /&gt;
 &lt;br /&gt;
  Call IsNT&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 1 AddToEnvVar_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $2 $WINDIR 2&lt;br /&gt;
    FileOpen $2 &amp;quot;$2\autoexec.bat&amp;quot; a&lt;br /&gt;
    FileSeek $2 -1 END&lt;br /&gt;
    FileReadByte $2 $3&lt;br /&gt;
    IntCmp $3 26 0 +2 +2 # DOS EOF&lt;br /&gt;
      FileSeek $2 -1 END # write over EOF&lt;br /&gt;
    FileWrite $2 &amp;quot;$\r$\nSET $0=%$0%;$4$\r$\n&amp;quot;&lt;br /&gt;
    FileClose $2&lt;br /&gt;
    SetRebootFlag true&lt;br /&gt;
    Goto AddToEnvVar_done&lt;br /&gt;
 &lt;br /&gt;
  AddToEnvVar_NT:&lt;br /&gt;
    ReadRegStr $2 ${WriteEnvStr_RegKey} $0&lt;br /&gt;
    StrCpy $3 $2 1 -1 # copy last char&lt;br /&gt;
    StrCmp $3 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
      StrCpy $2 $2 -1 # remove last char&lt;br /&gt;
    StrCmp $2 &amp;quot;&amp;quot; AddToEnvVar_NTdoIt&lt;br /&gt;
      StrCpy $1 &amp;quot;$2;$1&amp;quot;&lt;br /&gt;
    AddToEnvVar_NTdoIt:&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $1&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  AddToEnvVar_done:&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Pop $1&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
 &lt;br /&gt;
; RemoveFromEnvVar - Remove a given value from a environment var&lt;br /&gt;
;     Input: head of the stack&lt;br /&gt;
 &lt;br /&gt;
Function un.RemoveFromEnvVar&lt;br /&gt;
&lt;br /&gt;
  Exch $1 ; $1 has environment variable value&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $0 ; $0 has environment variable name&lt;br /&gt;
&lt;br /&gt;
  DetailPrint &amp;quot;Removing $1 from $0&amp;quot;&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
 &lt;br /&gt;
  IntFmt $7 &amp;quot;%c&amp;quot; 26 # DOS EOF&lt;br /&gt;
 &lt;br /&gt;
  Call un.IsNT&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 1 unRemoveFromEnvVar_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $2 $WINDIR 2&lt;br /&gt;
    FileOpen $2 &amp;quot;$2\autoexec.bat&amp;quot; r&lt;br /&gt;
    GetTempFileName $5&lt;br /&gt;
    FileOpen $3 $5 w&lt;br /&gt;
    GetFullPathName /SHORT $1 $1&lt;br /&gt;
    StrCpy $1 &amp;quot;SET $0=%$0%;$1&amp;quot;&lt;br /&gt;
    Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
 &lt;br /&gt;
    unRemoveFromEnvVar_dosLoop:&lt;br /&gt;
      FileRead $2 $4&lt;br /&gt;
      StrCpy $6 $4 1 -1 # read last char&lt;br /&gt;
      StrCmp $6 $7 0 +2 # if DOS EOF&lt;br /&gt;
        StrCpy $4 $4 -1 # remove DOS EOF so we can compare&lt;br /&gt;
      StrCmp $4 &amp;quot;$1$\r$\n&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;$1$\n&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;$1&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;&amp;quot; unRemoveFromEnvVar_dosLoopEnd&lt;br /&gt;
      FileWrite $3 $4&lt;br /&gt;
      Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
      unRemoveFromEnvVar_dosLoopRemoveLine:&lt;br /&gt;
        SetRebootFlag true&lt;br /&gt;
        Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
 &lt;br /&gt;
    unRemoveFromEnvVar_dosLoopEnd:&lt;br /&gt;
      FileClose $3&lt;br /&gt;
      FileClose $2&lt;br /&gt;
      StrCpy $2 $WINDIR 2&lt;br /&gt;
      Delete &amp;quot;$2\autoexec.bat&amp;quot;&lt;br /&gt;
      CopyFiles /SILENT $5 &amp;quot;$2\autoexec.bat&amp;quot;&lt;br /&gt;
      Delete $5&lt;br /&gt;
      Goto unRemoveFromEnvVar_done&lt;br /&gt;
 &lt;br /&gt;
  unRemoveFromEnvVar_NT:&lt;br /&gt;
    ReadRegStr $2 ${WriteEnvStr_RegKey} $0&lt;br /&gt;
    StrCpy $6 $2 1 -1 # copy last char&lt;br /&gt;
    StrCmp $6 &amp;quot;;&amp;quot; +2 # if last char != ;&lt;br /&gt;
      StrCpy $2 &amp;quot;$2;&amp;quot; # append ;&lt;br /&gt;
    Push $2&lt;br /&gt;
    Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
    Call un.StrStr ; Find `$1;` in $2&lt;br /&gt;
    Pop $3 ; pos of our dir&lt;br /&gt;
    StrCmp $3 &amp;quot;&amp;quot; unRemoveFromEnvVar_done&lt;br /&gt;
      ; else, it is in path&lt;br /&gt;
      # $1 - path to add&lt;br /&gt;
      # $2 - path var&lt;br /&gt;
      StrLen $4 &amp;quot;$1;&amp;quot;&lt;br /&gt;
      StrLen $5 $3&lt;br /&gt;
      StrCpy $6 $2 -$5 # $6 is now the part before the path to remove&lt;br /&gt;
      StrCpy $7 $3 &amp;quot;&amp;quot; $4 # $7 is now the part after the path to remove&lt;br /&gt;
      StrCpy $4 $6$7&lt;br /&gt;
 &lt;br /&gt;
      StrCpy $6 $4 1 -1 # copy last char&lt;br /&gt;
      StrCmp $6 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
      StrCpy $4 $4 -1 # remove last char&lt;br /&gt;
 &lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $4&lt;br /&gt;
&lt;br /&gt;
      ; delete reg value if null&lt;br /&gt;
      StrCmp $4 &amp;quot;&amp;quot; 0 +2 # if null delete reg&lt;br /&gt;
      DeleteRegValue ${WriteEnvStr_RegKey} $0&lt;br /&gt;
&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
 &lt;br /&gt;
  unRemoveFromEnvVar_done:&lt;br /&gt;
    Pop $7&lt;br /&gt;
    Pop $6&lt;br /&gt;
    Pop $5&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
!ifndef IsNT_KiCHiK&lt;br /&gt;
!define IsNT_KiCHiK&lt;br /&gt;
&lt;br /&gt;
###########################################&lt;br /&gt;
#            Utility Functions            #&lt;br /&gt;
###########################################&lt;br /&gt;
&lt;br /&gt;
; IsNT&lt;br /&gt;
; no input&lt;br /&gt;
; output, top of the stack = 1 if NT or 0 if not&lt;br /&gt;
;&lt;br /&gt;
; Usage:&lt;br /&gt;
;   Call IsNT&lt;br /&gt;
;   Pop $R0&lt;br /&gt;
;  ($R0 at this point is 1 or 0)&lt;br /&gt;
&lt;br /&gt;
!macro IsNT un&lt;br /&gt;
Function ${un}IsNT&lt;br /&gt;
  Push $0&lt;br /&gt;
  ReadRegStr $0 HKLM &amp;quot;SOFTWARE\Microsoft\Windows NT\CurrentVersion&amp;quot; CurrentVersion&lt;br /&gt;
  StrCmp $0 &amp;quot;&amp;quot; 0 IsNT_yes&lt;br /&gt;
  ; we are not NT.&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Push 0&lt;br /&gt;
  Return&lt;br /&gt;
&lt;br /&gt;
  IsNT_yes:&lt;br /&gt;
    ; NT!!!&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Push 1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro IsNT &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro IsNT &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!endif ; IsNT_KiCHiK&lt;br /&gt;
&lt;br /&gt;
; StrStr&lt;br /&gt;
; input, top of stack = string to search for&lt;br /&gt;
;        top of stack-1 = string to search in&lt;br /&gt;
; output, top of stack (replaces with the portion of the string remaining)&lt;br /&gt;
; modifies no other variables.&lt;br /&gt;
;&lt;br /&gt;
; Usage:&lt;br /&gt;
;   Push &amp;quot;this is a long ass string&amp;quot;&lt;br /&gt;
;   Push &amp;quot;ass&amp;quot;&lt;br /&gt;
;   Call StrStr&lt;br /&gt;
;   Pop $R0&lt;br /&gt;
;  ($R0 at this point is &amp;quot;ass string&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
!macro StrStr un&lt;br /&gt;
Function ${un}StrStr&lt;br /&gt;
Exch $R1 ; st=haystack,old$R1, $R1=needle&lt;br /&gt;
  Exch    ; st=old$R1,haystack&lt;br /&gt;
  Exch $R2 ; st=old$R1,old$R2, $R2=haystack&lt;br /&gt;
  Push $R3&lt;br /&gt;
  Push $R4&lt;br /&gt;
  Push $R5&lt;br /&gt;
  StrLen $R3 $R1&lt;br /&gt;
  StrCpy $R4 0&lt;br /&gt;
  ; $R1=needle&lt;br /&gt;
  ; $R2=haystack&lt;br /&gt;
  ; $R3=len(needle)&lt;br /&gt;
  ; $R4=cnt&lt;br /&gt;
  ; $R5=tmp&lt;br /&gt;
  loop:&lt;br /&gt;
    StrCpy $R5 $R2 $R3 $R4&lt;br /&gt;
    StrCmp $R5 $R1 done&lt;br /&gt;
    StrCmp $R5 &amp;quot;&amp;quot; done&lt;br /&gt;
    IntOp $R4 $R4 + 1&lt;br /&gt;
    Goto loop&lt;br /&gt;
done:&lt;br /&gt;
  StrCpy $R1 $R2 &amp;quot;&amp;quot; $R4&lt;br /&gt;
  Pop $R5&lt;br /&gt;
  Pop $R4&lt;br /&gt;
  Pop $R3&lt;br /&gt;
  Pop $R2&lt;br /&gt;
  Exch $R1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrStr &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrStr &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!endif ; _AddToPath_nsh&lt;br /&gt;
&lt;br /&gt;
Function Trim ; Added by Pelaca&lt;br /&gt;
	Exch $R1&lt;br /&gt;
	Push $R2&lt;br /&gt;
Loop:&lt;br /&gt;
	StrCpy $R2 &amp;quot;$R1&amp;quot; 1 -1&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot; &amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;$\n&amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;$\r&amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;;&amp;quot; RTrim&lt;br /&gt;
	GoTo Done&lt;br /&gt;
RTrim:	&lt;br /&gt;
	StrCpy $R1 &amp;quot;$R1&amp;quot; -1&lt;br /&gt;
	Goto Loop&lt;br /&gt;
Done:&lt;br /&gt;
	Pop $R2&lt;br /&gt;
	Exch $R1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Path_Manipulation&amp;diff=15628</id>
		<title>Path Manipulation</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Path_Manipulation&amp;diff=15628"/>
		<updated>2008-07-03T14:52:34Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2KiCHiK}} {{PageAuthor|KiCHiK}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname from the PATH environmental variable in either the &amp;quot;all users&amp;quot; (HKLM) or the &amp;quot;current user&amp;quot; (HKCU) section of the registry. &lt;br /&gt;
&lt;br /&gt;
Duplicates entries, leading and trailing spaces around each entry, and duplicate semicolons are removed from the contents of PATH before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname).&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
=== Syntax ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;Pathname&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;Pathname&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
:; ResultVar&lt;br /&gt;
:: Updated contents PATH returned by the function&lt;br /&gt;
&lt;br /&gt;
:; EnvVarName&lt;br /&gt;
:: &amp;quot;PATH&amp;quot; &lt;br /&gt;
&lt;br /&gt;
:; Action&lt;br /&gt;
:: &amp;quot;A&amp;quot; = Append&lt;br /&gt;
:: &amp;quot;P&amp;quot; = Prepend&lt;br /&gt;
:: &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
:; RegLoc&lt;br /&gt;
:: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
:: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
:; Pathname&lt;br /&gt;
:: Pathname to add to or remove from the contents of PATH (e.g., &amp;quot;C:\MyApp&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\Windows Resource Kits\Tools&amp;quot;  &lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;%WinDir%\System32&amp;quot;  &lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v1.0&amp;quot;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v2.0&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v1.0&amp;quot;   &lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v2.0&amp;quot;   &lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dependencies == &lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;EnvVarUpdate&#039;&#039;&#039; (available at  [[Environmental_Variables:_append%2C_prepend%2C_and_remove_entries]])&lt;br /&gt;
* &#039;&#039;&#039;StrTok, StrContains, and StrReplace:&#039;&#039;&#039;  Included in the EnvVarUpdate function code &lt;br /&gt;
* &#039;&#039;&#039;LogicLib header file:&#039;&#039;&#039; &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
&lt;br /&gt;
* Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
* Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr  &lt;br /&gt;
* Diego Pedroso (deguix) for StrTok&lt;br /&gt;
* Kevin English (kenglish_hi)for StrContains&lt;br /&gt;
* Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Functions for Windows 95, 98, and ME ==&lt;br /&gt;
&lt;br /&gt;
The following routines, AddToPath, un.RemoveFromPath, AddToEnvVar, and un.RemoveFromEnvVar are provided for Windows 95, 98, or ME in that they support the update of the autoexec.bat file.  Note that they can cause corruption of the PATH if the path being removed happens to be a subset of another path.   For example, if PATH contains &amp;quot;C:\Windows\system32\wbem&amp;quot; and you remove&lt;br /&gt;
&amp;quot;C:\Windows\system32&amp;quot; the result is &amp;quot;\wbem&amp;quot;.  They also do not prevent duplication of entries if ,for example, the user runs the installer multiple times.    &lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Here are four functions, two for adding to and removing directories from the search path (i.e. PATH environment variable) of Windows and two more for adding to and removing directories from a user defined environment variable such as INCLUDE or LIB etc. These functions should work on every version of Windows including 95, 98, ME, NT, 2000, and XP.&lt;br /&gt;
&lt;br /&gt;
For Windows NT/2000/XP they will write to HKEY_CURRENT_USER\Environment\PATH. For 9x/ME they will write to the autoexec.bat file.&lt;br /&gt;
&lt;br /&gt;
Changes on 9x machines will take place after a reboot. These functions set the reboot flag if the path variable was changed on 9x.&lt;br /&gt;
&lt;br /&gt;
These functions require NSIS 2.0b0 and above due to the usage of SendMessage with /TIMEOUT. It is possible to use it with earlier versions of NSIS with a little application I have created called RefreshEnv. It does exactly the same as SendMessage with /TIMEOUT. You can find it at [http://forums.winamp.com/showthread.php?s=&amp;amp;threadid=77904&amp;amp;highlight=refreshenv this forum thread].&lt;br /&gt;
&lt;br /&gt;
The directory added to the path must exist prior to calling this function.&lt;br /&gt;
&lt;br /&gt;
=== Usage Example ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;Section &amp;quot;Add to path&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call AddToPath&lt;br /&gt;
&lt;br /&gt;
  Push &amp;quot;LIB&amp;quot;&lt;br /&gt;
  Push &amp;quot;c:\Mylibrary\lib&amp;quot;&lt;br /&gt;
  Call AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
  ;likewise AddToPath could be&lt;br /&gt;
  Push &amp;quot;PATH&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
SectionEnd&lt;br /&gt;
&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Section &amp;quot;uninstall&amp;quot;&lt;br /&gt;
  # ...&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call un.RemoveFromPath&lt;br /&gt;
  # ...&lt;br /&gt;
  Push &amp;quot;LIB&amp;quot;&lt;br /&gt;
  Push &amp;quot;c:\Mylibrary\lib&amp;quot;&lt;br /&gt;
  Call un.RemoveFromEnvVar&lt;br /&gt;
&lt;br /&gt;
  ;Likewise RemoveFromPath could be&lt;br /&gt;
  Push &amp;quot;PATH&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call un.RemoveFromEnvVar&lt;br /&gt;
  &lt;br /&gt;
SectionEnd&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Functions ===&lt;br /&gt;
The functions in the flesh:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;!ifndef _AddToPath_nsh&lt;br /&gt;
!define _AddToPath_nsh&lt;br /&gt;
&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
!verbose 4&lt;br /&gt;
&lt;br /&gt;
!ifndef WriteEnvStr_RegKey&lt;br /&gt;
  !ifdef ALL_USERS&lt;br /&gt;
    !define WriteEnvStr_RegKey \&lt;br /&gt;
       &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
  !else&lt;br /&gt;
    !define WriteEnvStr_RegKey &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
  !endif&lt;br /&gt;
!endif&lt;br /&gt;
&lt;br /&gt;
; AddToPath - Adds the given dir to the search path.&lt;br /&gt;
;        Input - head of the stack&lt;br /&gt;
;        Note - Win9x systems requires reboot&lt;br /&gt;
&lt;br /&gt;
Function AddToPath&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Push $1&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
&lt;br /&gt;
  # don&#039;t add if the path doesn&#039;t exist&lt;br /&gt;
  IfFileExists &amp;quot;$0\*.*&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  ReadEnvStr $1 PATH&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$0;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$0\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  GetFullPathName /SHORT $3 $0&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$3;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$3\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  Call IsNT&lt;br /&gt;
  Pop $1&lt;br /&gt;
  StrCmp $1 1 AddToPath_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $1 $WINDIR 2&lt;br /&gt;
    FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; a&lt;br /&gt;
    FileSeek $1 -1 END&lt;br /&gt;
    FileReadByte $1 $2&lt;br /&gt;
    IntCmp $2 26 0 +2 +2 # DOS EOF&lt;br /&gt;
      FileSeek $1 -1 END # write over EOF&lt;br /&gt;
    FileWrite $1 &amp;quot;$\r$\nSET PATH=%PATH%;$3$\r$\n&amp;quot;&lt;br /&gt;
    FileClose $1&lt;br /&gt;
    SetRebootFlag true&lt;br /&gt;
    Goto AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  AddToPath_NT:&lt;br /&gt;
    ReadRegStr $1 ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot;&lt;br /&gt;
    StrCmp $1 &amp;quot;&amp;quot; AddToPath_NTdoIt&lt;br /&gt;
      Push $1&lt;br /&gt;
      Call Trim&lt;br /&gt;
      Pop $1&lt;br /&gt;
      StrCpy $0 &amp;quot;$1;$0&amp;quot;&lt;br /&gt;
    AddToPath_NTdoIt:&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot; $0&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  AddToPath_done:&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
; RemoveFromPath - Remove a given dir from the path&lt;br /&gt;
;     Input: head of the stack&lt;br /&gt;
&lt;br /&gt;
Function un.RemoveFromPath&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Push $1&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
&lt;br /&gt;
  IntFmt $6 &amp;quot;%c&amp;quot; 26 # DOS EOF&lt;br /&gt;
&lt;br /&gt;
  Call un.IsNT&lt;br /&gt;
  Pop $1&lt;br /&gt;
  StrCmp $1 1 unRemoveFromPath_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $1 $WINDIR 2&lt;br /&gt;
    FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; r&lt;br /&gt;
    GetTempFileName $4&lt;br /&gt;
    FileOpen $2 $4 w&lt;br /&gt;
    GetFullPathName /SHORT $0 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;SET PATH=%PATH%;$0&amp;quot;&lt;br /&gt;
    Goto unRemoveFromPath_dosLoop&lt;br /&gt;
&lt;br /&gt;
    unRemoveFromPath_dosLoop:&lt;br /&gt;
      FileRead $1 $3&lt;br /&gt;
      StrCpy $5 $3 1 -1 # read last char&lt;br /&gt;
      StrCmp $5 $6 0 +2 # if DOS EOF&lt;br /&gt;
        StrCpy $3 $3 -1 # remove DOS EOF so we can compare&lt;br /&gt;
      StrCmp $3 &amp;quot;$0$\r$\n&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;$0$\n&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;$0&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;&amp;quot; unRemoveFromPath_dosLoopEnd&lt;br /&gt;
      FileWrite $2 $3&lt;br /&gt;
      Goto unRemoveFromPath_dosLoop&lt;br /&gt;
      unRemoveFromPath_dosLoopRemoveLine:&lt;br /&gt;
        SetRebootFlag true&lt;br /&gt;
        Goto unRemoveFromPath_dosLoop&lt;br /&gt;
&lt;br /&gt;
    unRemoveFromPath_dosLoopEnd:&lt;br /&gt;
      FileClose $2&lt;br /&gt;
      FileClose $1&lt;br /&gt;
      StrCpy $1 $WINDIR 2&lt;br /&gt;
      Delete &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
      CopyFiles /SILENT $4 &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
      Delete $4&lt;br /&gt;
      Goto unRemoveFromPath_done&lt;br /&gt;
&lt;br /&gt;
  unRemoveFromPath_NT:&lt;br /&gt;
    ReadRegStr $1 ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot;&lt;br /&gt;
    StrCpy $5 $1 1 -1 # copy last char&lt;br /&gt;
    StrCmp $5 &amp;quot;;&amp;quot; +2 # if last char != ;&lt;br /&gt;
      StrCpy $1 &amp;quot;$1;&amp;quot; # append ;&lt;br /&gt;
    Push $1&lt;br /&gt;
    Push &amp;quot;$0;&amp;quot;&lt;br /&gt;
    Call un.StrStr ; Find `$0;` in $1&lt;br /&gt;
    Pop $2 ; pos of our dir&lt;br /&gt;
    StrCmp $2 &amp;quot;&amp;quot; unRemoveFromPath_done&lt;br /&gt;
      ; else, it is in path&lt;br /&gt;
      # $0 - path to add&lt;br /&gt;
      # $1 - path var&lt;br /&gt;
      StrLen $3 &amp;quot;$0;&amp;quot;&lt;br /&gt;
      StrLen $4 $2&lt;br /&gt;
      StrCpy $5 $1 -$4 # $5 is now the part before the path to remove&lt;br /&gt;
      StrCpy $6 $2 &amp;quot;&amp;quot; $3 # $6 is now the part after the path to remove&lt;br /&gt;
      StrCpy $3 $5$6&lt;br /&gt;
&lt;br /&gt;
      StrCpy $5 $3 1 -1 # copy last char&lt;br /&gt;
      StrCmp $5 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
        StrCpy $3 $3 -1 # remove last char&lt;br /&gt;
&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot; $3&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  unRemoveFromPath_done:&lt;br /&gt;
    Pop $6&lt;br /&gt;
    Pop $5&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; AddToEnvVar - Adds the given value to the given environment var&lt;br /&gt;
;        Input - head of the stack $0 environement variable $1=value to add&lt;br /&gt;
;        Note - Win9x systems requires reboot&lt;br /&gt;
 &lt;br /&gt;
Function AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
  Exch $1 ; $1 has environment variable value&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $0 ; $0 has environment variable name&lt;br /&gt;
&lt;br /&gt;
  DetailPrint &amp;quot;Adding $1 to $0&amp;quot;&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
  ReadEnvStr $2 $0&lt;br /&gt;
  Push &amp;quot;$2;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $3&lt;br /&gt;
  StrCmp $3 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToEnvVar_done&lt;br /&gt;
&lt;br /&gt;
  Push &amp;quot;$2;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$1\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $3&lt;br /&gt;
  StrCmp $3 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToEnvVar_done&lt;br /&gt;
  &lt;br /&gt;
 &lt;br /&gt;
  Call IsNT&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 1 AddToEnvVar_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $2 $WINDIR 2&lt;br /&gt;
    FileOpen $2 &amp;quot;$2\autoexec.bat&amp;quot; a&lt;br /&gt;
    FileSeek $2 -1 END&lt;br /&gt;
    FileReadByte $2 $3&lt;br /&gt;
    IntCmp $3 26 0 +2 +2 # DOS EOF&lt;br /&gt;
      FileSeek $2 -1 END # write over EOF&lt;br /&gt;
    FileWrite $2 &amp;quot;$\r$\nSET $0=%$0%;$4$\r$\n&amp;quot;&lt;br /&gt;
    FileClose $2&lt;br /&gt;
    SetRebootFlag true&lt;br /&gt;
    Goto AddToEnvVar_done&lt;br /&gt;
 &lt;br /&gt;
  AddToEnvVar_NT:&lt;br /&gt;
    ReadRegStr $2 ${WriteEnvStr_RegKey} $0&lt;br /&gt;
    StrCpy $3 $2 1 -1 # copy last char&lt;br /&gt;
    StrCmp $3 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
      StrCpy $2 $2 -1 # remove last char&lt;br /&gt;
    StrCmp $2 &amp;quot;&amp;quot; AddToEnvVar_NTdoIt&lt;br /&gt;
      StrCpy $1 &amp;quot;$2;$1&amp;quot;&lt;br /&gt;
    AddToEnvVar_NTdoIt:&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $1&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  AddToEnvVar_done:&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Pop $1&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
 &lt;br /&gt;
; RemoveFromEnvVar - Remove a given value from a environment var&lt;br /&gt;
;     Input: head of the stack&lt;br /&gt;
 &lt;br /&gt;
Function un.RemoveFromEnvVar&lt;br /&gt;
&lt;br /&gt;
  Exch $1 ; $1 has environment variable value&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $0 ; $0 has environment variable name&lt;br /&gt;
&lt;br /&gt;
  DetailPrint &amp;quot;Removing $1 from $0&amp;quot;&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
 &lt;br /&gt;
  IntFmt $7 &amp;quot;%c&amp;quot; 26 # DOS EOF&lt;br /&gt;
 &lt;br /&gt;
  Call un.IsNT&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 1 unRemoveFromEnvVar_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $2 $WINDIR 2&lt;br /&gt;
    FileOpen $2 &amp;quot;$2\autoexec.bat&amp;quot; r&lt;br /&gt;
    GetTempFileName $5&lt;br /&gt;
    FileOpen $3 $5 w&lt;br /&gt;
    GetFullPathName /SHORT $1 $1&lt;br /&gt;
    StrCpy $1 &amp;quot;SET $0=%$0%;$1&amp;quot;&lt;br /&gt;
    Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
 &lt;br /&gt;
    unRemoveFromEnvVar_dosLoop:&lt;br /&gt;
      FileRead $2 $4&lt;br /&gt;
      StrCpy $6 $4 1 -1 # read last char&lt;br /&gt;
      StrCmp $6 $7 0 +2 # if DOS EOF&lt;br /&gt;
        StrCpy $4 $4 -1 # remove DOS EOF so we can compare&lt;br /&gt;
      StrCmp $4 &amp;quot;$1$\r$\n&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;$1$\n&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;$1&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;&amp;quot; unRemoveFromEnvVar_dosLoopEnd&lt;br /&gt;
      FileWrite $3 $4&lt;br /&gt;
      Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
      unRemoveFromEnvVar_dosLoopRemoveLine:&lt;br /&gt;
        SetRebootFlag true&lt;br /&gt;
        Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
 &lt;br /&gt;
    unRemoveFromEnvVar_dosLoopEnd:&lt;br /&gt;
      FileClose $3&lt;br /&gt;
      FileClose $2&lt;br /&gt;
      StrCpy $2 $WINDIR 2&lt;br /&gt;
      Delete &amp;quot;$2\autoexec.bat&amp;quot;&lt;br /&gt;
      CopyFiles /SILENT $5 &amp;quot;$2\autoexec.bat&amp;quot;&lt;br /&gt;
      Delete $5&lt;br /&gt;
      Goto unRemoveFromEnvVar_done&lt;br /&gt;
 &lt;br /&gt;
  unRemoveFromEnvVar_NT:&lt;br /&gt;
    ReadRegStr $2 ${WriteEnvStr_RegKey} $0&lt;br /&gt;
    StrCpy $6 $2 1 -1 # copy last char&lt;br /&gt;
    StrCmp $6 &amp;quot;;&amp;quot; +2 # if last char != ;&lt;br /&gt;
      StrCpy $2 &amp;quot;$2;&amp;quot; # append ;&lt;br /&gt;
    Push $2&lt;br /&gt;
    Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
    Call un.StrStr ; Find `$1;` in $2&lt;br /&gt;
    Pop $3 ; pos of our dir&lt;br /&gt;
    StrCmp $3 &amp;quot;&amp;quot; unRemoveFromEnvVar_done&lt;br /&gt;
      ; else, it is in path&lt;br /&gt;
      # $1 - path to add&lt;br /&gt;
      # $2 - path var&lt;br /&gt;
      StrLen $4 &amp;quot;$1;&amp;quot;&lt;br /&gt;
      StrLen $5 $3&lt;br /&gt;
      StrCpy $6 $2 -$5 # $6 is now the part before the path to remove&lt;br /&gt;
      StrCpy $7 $3 &amp;quot;&amp;quot; $4 # $7 is now the part after the path to remove&lt;br /&gt;
      StrCpy $4 $6$7&lt;br /&gt;
 &lt;br /&gt;
      StrCpy $6 $4 1 -1 # copy last char&lt;br /&gt;
      StrCmp $6 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
      StrCpy $4 $4 -1 # remove last char&lt;br /&gt;
 &lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $4&lt;br /&gt;
&lt;br /&gt;
      ; delete reg value if null&lt;br /&gt;
      StrCmp $4 &amp;quot;&amp;quot; 0 +2 # if null delete reg&lt;br /&gt;
      DeleteRegValue ${WriteEnvStr_RegKey} $0&lt;br /&gt;
&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
 &lt;br /&gt;
  unRemoveFromEnvVar_done:&lt;br /&gt;
    Pop $7&lt;br /&gt;
    Pop $6&lt;br /&gt;
    Pop $5&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
!ifndef IsNT_KiCHiK&lt;br /&gt;
!define IsNT_KiCHiK&lt;br /&gt;
&lt;br /&gt;
###########################################&lt;br /&gt;
#            Utility Functions            #&lt;br /&gt;
###########################################&lt;br /&gt;
&lt;br /&gt;
; IsNT&lt;br /&gt;
; no input&lt;br /&gt;
; output, top of the stack = 1 if NT or 0 if not&lt;br /&gt;
;&lt;br /&gt;
; Usage:&lt;br /&gt;
;   Call IsNT&lt;br /&gt;
;   Pop $R0&lt;br /&gt;
;  ($R0 at this point is 1 or 0)&lt;br /&gt;
&lt;br /&gt;
!macro IsNT un&lt;br /&gt;
Function ${un}IsNT&lt;br /&gt;
  Push $0&lt;br /&gt;
  ReadRegStr $0 HKLM &amp;quot;SOFTWARE\Microsoft\Windows NT\CurrentVersion&amp;quot; CurrentVersion&lt;br /&gt;
  StrCmp $0 &amp;quot;&amp;quot; 0 IsNT_yes&lt;br /&gt;
  ; we are not NT.&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Push 0&lt;br /&gt;
  Return&lt;br /&gt;
&lt;br /&gt;
  IsNT_yes:&lt;br /&gt;
    ; NT!!!&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Push 1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro IsNT &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro IsNT &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!endif ; IsNT_KiCHiK&lt;br /&gt;
&lt;br /&gt;
; StrStr&lt;br /&gt;
; input, top of stack = string to search for&lt;br /&gt;
;        top of stack-1 = string to search in&lt;br /&gt;
; output, top of stack (replaces with the portion of the string remaining)&lt;br /&gt;
; modifies no other variables.&lt;br /&gt;
;&lt;br /&gt;
; Usage:&lt;br /&gt;
;   Push &amp;quot;this is a long ass string&amp;quot;&lt;br /&gt;
;   Push &amp;quot;ass&amp;quot;&lt;br /&gt;
;   Call StrStr&lt;br /&gt;
;   Pop $R0&lt;br /&gt;
;  ($R0 at this point is &amp;quot;ass string&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
!macro StrStr un&lt;br /&gt;
Function ${un}StrStr&lt;br /&gt;
Exch $R1 ; st=haystack,old$R1, $R1=needle&lt;br /&gt;
  Exch    ; st=old$R1,haystack&lt;br /&gt;
  Exch $R2 ; st=old$R1,old$R2, $R2=haystack&lt;br /&gt;
  Push $R3&lt;br /&gt;
  Push $R4&lt;br /&gt;
  Push $R5&lt;br /&gt;
  StrLen $R3 $R1&lt;br /&gt;
  StrCpy $R4 0&lt;br /&gt;
  ; $R1=needle&lt;br /&gt;
  ; $R2=haystack&lt;br /&gt;
  ; $R3=len(needle)&lt;br /&gt;
  ; $R4=cnt&lt;br /&gt;
  ; $R5=tmp&lt;br /&gt;
  loop:&lt;br /&gt;
    StrCpy $R5 $R2 $R3 $R4&lt;br /&gt;
    StrCmp $R5 $R1 done&lt;br /&gt;
    StrCmp $R5 &amp;quot;&amp;quot; done&lt;br /&gt;
    IntOp $R4 $R4 + 1&lt;br /&gt;
    Goto loop&lt;br /&gt;
done:&lt;br /&gt;
  StrCpy $R1 $R2 &amp;quot;&amp;quot; $R4&lt;br /&gt;
  Pop $R5&lt;br /&gt;
  Pop $R4&lt;br /&gt;
  Pop $R3&lt;br /&gt;
  Pop $R2&lt;br /&gt;
  Exch $R1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrStr &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrStr &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!endif ; _AddToPath_nsh&lt;br /&gt;
&lt;br /&gt;
Function Trim ; Added by Pelaca&lt;br /&gt;
	Exch $R1&lt;br /&gt;
	Push $R2&lt;br /&gt;
Loop:&lt;br /&gt;
	StrCpy $R2 &amp;quot;$R1&amp;quot; 1 -1&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot; &amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;$\n&amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;$\r&amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;;&amp;quot; RTrim&lt;br /&gt;
	GoTo Done&lt;br /&gt;
RTrim:	&lt;br /&gt;
	StrCpy $R1 &amp;quot;$R1&amp;quot; -1&lt;br /&gt;
	Goto Loop&lt;br /&gt;
Done:&lt;br /&gt;
	Pop $R2&lt;br /&gt;
	Exch $R1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Path_Manipulation&amp;diff=15627</id>
		<title>Path Manipulation</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Path_Manipulation&amp;diff=15627"/>
		<updated>2008-07-03T14:51:38Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2|KiCHiK}}&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname from the PATH environmental variable in either the &amp;quot;all users&amp;quot; (HKLM) or the &amp;quot;current user&amp;quot; (HKCU) section of the registry. &lt;br /&gt;
&lt;br /&gt;
Duplicates entries, leading and trailing spaces around each entry, and duplicate semicolons are removed from the contents of PATH before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname).&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
=== Syntax ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;Pathname&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;Pathname&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
:; ResultVar&lt;br /&gt;
:: Updated contents PATH returned by the function&lt;br /&gt;
&lt;br /&gt;
:; EnvVarName&lt;br /&gt;
:: &amp;quot;PATH&amp;quot; &lt;br /&gt;
&lt;br /&gt;
:; Action&lt;br /&gt;
:: &amp;quot;A&amp;quot; = Append&lt;br /&gt;
:: &amp;quot;P&amp;quot; = Prepend&lt;br /&gt;
:: &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
:; RegLoc&lt;br /&gt;
:: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
:: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
:; Pathname&lt;br /&gt;
:: Pathname to add to or remove from the contents of PATH (e.g., &amp;quot;C:\MyApp&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\Windows Resource Kits\Tools&amp;quot;  &lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;%WinDir%\System32&amp;quot;  &lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v1.0&amp;quot;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v2.0&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v1.0&amp;quot;   &lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v2.0&amp;quot;   &lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dependencies == &lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;EnvVarUpdate&#039;&#039;&#039; (available at  [[Environmental_Variables:_append%2C_prepend%2C_and_remove_entries]])&lt;br /&gt;
* &#039;&#039;&#039;StrTok, StrContains, and StrReplace:&#039;&#039;&#039;  Included in the EnvVarUpdate function code &lt;br /&gt;
* &#039;&#039;&#039;LogicLib header file:&#039;&#039;&#039; &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
&lt;br /&gt;
* Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
* Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr  &lt;br /&gt;
* Diego Pedroso (deguix) for StrTok&lt;br /&gt;
* Kevin English (kenglish_hi)for StrContains&lt;br /&gt;
* Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Functions for Windows 95, 98, and ME ==&lt;br /&gt;
&lt;br /&gt;
The following routines, AddToPath, un.RemoveFromPath, AddToEnvVar, and un.RemoveFromEnvVar are provided for Windows 95, 98, or ME in that they support the update of the autoexec.bat file.  Note that they can cause corruption of the PATH if the path being removed happens to be a subset of another path.   For example, if PATH contains &amp;quot;C:\Windows\system32\wbem&amp;quot; and you remove&lt;br /&gt;
&amp;quot;C:\Windows\system32&amp;quot; the result is &amp;quot;\wbem&amp;quot;.  They also do not prevent duplication of entries if ,for example, the user runs the installer multiple times.    &lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Here are four functions, two for adding to and removing directories from the search path (i.e. PATH environment variable) of Windows and two more for adding to and removing directories from a user defined environment variable such as INCLUDE or LIB etc. These functions should work on every version of Windows including 95, 98, ME, NT, 2000, and XP.&lt;br /&gt;
&lt;br /&gt;
For Windows NT/2000/XP they will write to HKEY_CURRENT_USER\Environment\PATH. For 9x/ME they will write to the autoexec.bat file.&lt;br /&gt;
&lt;br /&gt;
Changes on 9x machines will take place after a reboot. These functions set the reboot flag if the path variable was changed on 9x.&lt;br /&gt;
&lt;br /&gt;
These functions require NSIS 2.0b0 and above due to the usage of SendMessage with /TIMEOUT. It is possible to use it with earlier versions of NSIS with a little application I have created called RefreshEnv. It does exactly the same as SendMessage with /TIMEOUT. You can find it at [http://forums.winamp.com/showthread.php?s=&amp;amp;threadid=77904&amp;amp;highlight=refreshenv this forum thread].&lt;br /&gt;
&lt;br /&gt;
The directory added to the path must exist prior to calling this function.&lt;br /&gt;
&lt;br /&gt;
=== Usage Example ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;Section &amp;quot;Add to path&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call AddToPath&lt;br /&gt;
&lt;br /&gt;
  Push &amp;quot;LIB&amp;quot;&lt;br /&gt;
  Push &amp;quot;c:\Mylibrary\lib&amp;quot;&lt;br /&gt;
  Call AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
  ;likewise AddToPath could be&lt;br /&gt;
  Push &amp;quot;PATH&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
SectionEnd&lt;br /&gt;
&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Section &amp;quot;uninstall&amp;quot;&lt;br /&gt;
  # ...&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call un.RemoveFromPath&lt;br /&gt;
  # ...&lt;br /&gt;
  Push &amp;quot;LIB&amp;quot;&lt;br /&gt;
  Push &amp;quot;c:\Mylibrary\lib&amp;quot;&lt;br /&gt;
  Call un.RemoveFromEnvVar&lt;br /&gt;
&lt;br /&gt;
  ;Likewise RemoveFromPath could be&lt;br /&gt;
  Push &amp;quot;PATH&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call un.RemoveFromEnvVar&lt;br /&gt;
  &lt;br /&gt;
SectionEnd&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Functions ===&lt;br /&gt;
The functions in the flesh:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;!ifndef _AddToPath_nsh&lt;br /&gt;
!define _AddToPath_nsh&lt;br /&gt;
&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
!verbose 4&lt;br /&gt;
&lt;br /&gt;
!ifndef WriteEnvStr_RegKey&lt;br /&gt;
  !ifdef ALL_USERS&lt;br /&gt;
    !define WriteEnvStr_RegKey \&lt;br /&gt;
       &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
  !else&lt;br /&gt;
    !define WriteEnvStr_RegKey &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
  !endif&lt;br /&gt;
!endif&lt;br /&gt;
&lt;br /&gt;
; AddToPath - Adds the given dir to the search path.&lt;br /&gt;
;        Input - head of the stack&lt;br /&gt;
;        Note - Win9x systems requires reboot&lt;br /&gt;
&lt;br /&gt;
Function AddToPath&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Push $1&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
&lt;br /&gt;
  # don&#039;t add if the path doesn&#039;t exist&lt;br /&gt;
  IfFileExists &amp;quot;$0\*.*&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  ReadEnvStr $1 PATH&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$0;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$0\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  GetFullPathName /SHORT $3 $0&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$3;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$3\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  Call IsNT&lt;br /&gt;
  Pop $1&lt;br /&gt;
  StrCmp $1 1 AddToPath_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $1 $WINDIR 2&lt;br /&gt;
    FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; a&lt;br /&gt;
    FileSeek $1 -1 END&lt;br /&gt;
    FileReadByte $1 $2&lt;br /&gt;
    IntCmp $2 26 0 +2 +2 # DOS EOF&lt;br /&gt;
      FileSeek $1 -1 END # write over EOF&lt;br /&gt;
    FileWrite $1 &amp;quot;$\r$\nSET PATH=%PATH%;$3$\r$\n&amp;quot;&lt;br /&gt;
    FileClose $1&lt;br /&gt;
    SetRebootFlag true&lt;br /&gt;
    Goto AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  AddToPath_NT:&lt;br /&gt;
    ReadRegStr $1 ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot;&lt;br /&gt;
    StrCmp $1 &amp;quot;&amp;quot; AddToPath_NTdoIt&lt;br /&gt;
      Push $1&lt;br /&gt;
      Call Trim&lt;br /&gt;
      Pop $1&lt;br /&gt;
      StrCpy $0 &amp;quot;$1;$0&amp;quot;&lt;br /&gt;
    AddToPath_NTdoIt:&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot; $0&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  AddToPath_done:&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
; RemoveFromPath - Remove a given dir from the path&lt;br /&gt;
;     Input: head of the stack&lt;br /&gt;
&lt;br /&gt;
Function un.RemoveFromPath&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Push $1&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
&lt;br /&gt;
  IntFmt $6 &amp;quot;%c&amp;quot; 26 # DOS EOF&lt;br /&gt;
&lt;br /&gt;
  Call un.IsNT&lt;br /&gt;
  Pop $1&lt;br /&gt;
  StrCmp $1 1 unRemoveFromPath_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $1 $WINDIR 2&lt;br /&gt;
    FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; r&lt;br /&gt;
    GetTempFileName $4&lt;br /&gt;
    FileOpen $2 $4 w&lt;br /&gt;
    GetFullPathName /SHORT $0 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;SET PATH=%PATH%;$0&amp;quot;&lt;br /&gt;
    Goto unRemoveFromPath_dosLoop&lt;br /&gt;
&lt;br /&gt;
    unRemoveFromPath_dosLoop:&lt;br /&gt;
      FileRead $1 $3&lt;br /&gt;
      StrCpy $5 $3 1 -1 # read last char&lt;br /&gt;
      StrCmp $5 $6 0 +2 # if DOS EOF&lt;br /&gt;
        StrCpy $3 $3 -1 # remove DOS EOF so we can compare&lt;br /&gt;
      StrCmp $3 &amp;quot;$0$\r$\n&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;$0$\n&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;$0&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;&amp;quot; unRemoveFromPath_dosLoopEnd&lt;br /&gt;
      FileWrite $2 $3&lt;br /&gt;
      Goto unRemoveFromPath_dosLoop&lt;br /&gt;
      unRemoveFromPath_dosLoopRemoveLine:&lt;br /&gt;
        SetRebootFlag true&lt;br /&gt;
        Goto unRemoveFromPath_dosLoop&lt;br /&gt;
&lt;br /&gt;
    unRemoveFromPath_dosLoopEnd:&lt;br /&gt;
      FileClose $2&lt;br /&gt;
      FileClose $1&lt;br /&gt;
      StrCpy $1 $WINDIR 2&lt;br /&gt;
      Delete &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
      CopyFiles /SILENT $4 &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
      Delete $4&lt;br /&gt;
      Goto unRemoveFromPath_done&lt;br /&gt;
&lt;br /&gt;
  unRemoveFromPath_NT:&lt;br /&gt;
    ReadRegStr $1 ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot;&lt;br /&gt;
    StrCpy $5 $1 1 -1 # copy last char&lt;br /&gt;
    StrCmp $5 &amp;quot;;&amp;quot; +2 # if last char != ;&lt;br /&gt;
      StrCpy $1 &amp;quot;$1;&amp;quot; # append ;&lt;br /&gt;
    Push $1&lt;br /&gt;
    Push &amp;quot;$0;&amp;quot;&lt;br /&gt;
    Call un.StrStr ; Find `$0;` in $1&lt;br /&gt;
    Pop $2 ; pos of our dir&lt;br /&gt;
    StrCmp $2 &amp;quot;&amp;quot; unRemoveFromPath_done&lt;br /&gt;
      ; else, it is in path&lt;br /&gt;
      # $0 - path to add&lt;br /&gt;
      # $1 - path var&lt;br /&gt;
      StrLen $3 &amp;quot;$0;&amp;quot;&lt;br /&gt;
      StrLen $4 $2&lt;br /&gt;
      StrCpy $5 $1 -$4 # $5 is now the part before the path to remove&lt;br /&gt;
      StrCpy $6 $2 &amp;quot;&amp;quot; $3 # $6 is now the part after the path to remove&lt;br /&gt;
      StrCpy $3 $5$6&lt;br /&gt;
&lt;br /&gt;
      StrCpy $5 $3 1 -1 # copy last char&lt;br /&gt;
      StrCmp $5 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
        StrCpy $3 $3 -1 # remove last char&lt;br /&gt;
&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot; $3&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  unRemoveFromPath_done:&lt;br /&gt;
    Pop $6&lt;br /&gt;
    Pop $5&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; AddToEnvVar - Adds the given value to the given environment var&lt;br /&gt;
;        Input - head of the stack $0 environement variable $1=value to add&lt;br /&gt;
;        Note - Win9x systems requires reboot&lt;br /&gt;
 &lt;br /&gt;
Function AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
  Exch $1 ; $1 has environment variable value&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $0 ; $0 has environment variable name&lt;br /&gt;
&lt;br /&gt;
  DetailPrint &amp;quot;Adding $1 to $0&amp;quot;&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
  ReadEnvStr $2 $0&lt;br /&gt;
  Push &amp;quot;$2;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $3&lt;br /&gt;
  StrCmp $3 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToEnvVar_done&lt;br /&gt;
&lt;br /&gt;
  Push &amp;quot;$2;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$1\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $3&lt;br /&gt;
  StrCmp $3 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToEnvVar_done&lt;br /&gt;
  &lt;br /&gt;
 &lt;br /&gt;
  Call IsNT&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 1 AddToEnvVar_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $2 $WINDIR 2&lt;br /&gt;
    FileOpen $2 &amp;quot;$2\autoexec.bat&amp;quot; a&lt;br /&gt;
    FileSeek $2 -1 END&lt;br /&gt;
    FileReadByte $2 $3&lt;br /&gt;
    IntCmp $3 26 0 +2 +2 # DOS EOF&lt;br /&gt;
      FileSeek $2 -1 END # write over EOF&lt;br /&gt;
    FileWrite $2 &amp;quot;$\r$\nSET $0=%$0%;$4$\r$\n&amp;quot;&lt;br /&gt;
    FileClose $2&lt;br /&gt;
    SetRebootFlag true&lt;br /&gt;
    Goto AddToEnvVar_done&lt;br /&gt;
 &lt;br /&gt;
  AddToEnvVar_NT:&lt;br /&gt;
    ReadRegStr $2 ${WriteEnvStr_RegKey} $0&lt;br /&gt;
    StrCpy $3 $2 1 -1 # copy last char&lt;br /&gt;
    StrCmp $3 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
      StrCpy $2 $2 -1 # remove last char&lt;br /&gt;
    StrCmp $2 &amp;quot;&amp;quot; AddToEnvVar_NTdoIt&lt;br /&gt;
      StrCpy $1 &amp;quot;$2;$1&amp;quot;&lt;br /&gt;
    AddToEnvVar_NTdoIt:&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $1&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  AddToEnvVar_done:&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Pop $1&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
 &lt;br /&gt;
; RemoveFromEnvVar - Remove a given value from a environment var&lt;br /&gt;
;     Input: head of the stack&lt;br /&gt;
 &lt;br /&gt;
Function un.RemoveFromEnvVar&lt;br /&gt;
&lt;br /&gt;
  Exch $1 ; $1 has environment variable value&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $0 ; $0 has environment variable name&lt;br /&gt;
&lt;br /&gt;
  DetailPrint &amp;quot;Removing $1 from $0&amp;quot;&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
 &lt;br /&gt;
  IntFmt $7 &amp;quot;%c&amp;quot; 26 # DOS EOF&lt;br /&gt;
 &lt;br /&gt;
  Call un.IsNT&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 1 unRemoveFromEnvVar_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $2 $WINDIR 2&lt;br /&gt;
    FileOpen $2 &amp;quot;$2\autoexec.bat&amp;quot; r&lt;br /&gt;
    GetTempFileName $5&lt;br /&gt;
    FileOpen $3 $5 w&lt;br /&gt;
    GetFullPathName /SHORT $1 $1&lt;br /&gt;
    StrCpy $1 &amp;quot;SET $0=%$0%;$1&amp;quot;&lt;br /&gt;
    Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
 &lt;br /&gt;
    unRemoveFromEnvVar_dosLoop:&lt;br /&gt;
      FileRead $2 $4&lt;br /&gt;
      StrCpy $6 $4 1 -1 # read last char&lt;br /&gt;
      StrCmp $6 $7 0 +2 # if DOS EOF&lt;br /&gt;
        StrCpy $4 $4 -1 # remove DOS EOF so we can compare&lt;br /&gt;
      StrCmp $4 &amp;quot;$1$\r$\n&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;$1$\n&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;$1&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;&amp;quot; unRemoveFromEnvVar_dosLoopEnd&lt;br /&gt;
      FileWrite $3 $4&lt;br /&gt;
      Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
      unRemoveFromEnvVar_dosLoopRemoveLine:&lt;br /&gt;
        SetRebootFlag true&lt;br /&gt;
        Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
 &lt;br /&gt;
    unRemoveFromEnvVar_dosLoopEnd:&lt;br /&gt;
      FileClose $3&lt;br /&gt;
      FileClose $2&lt;br /&gt;
      StrCpy $2 $WINDIR 2&lt;br /&gt;
      Delete &amp;quot;$2\autoexec.bat&amp;quot;&lt;br /&gt;
      CopyFiles /SILENT $5 &amp;quot;$2\autoexec.bat&amp;quot;&lt;br /&gt;
      Delete $5&lt;br /&gt;
      Goto unRemoveFromEnvVar_done&lt;br /&gt;
 &lt;br /&gt;
  unRemoveFromEnvVar_NT:&lt;br /&gt;
    ReadRegStr $2 ${WriteEnvStr_RegKey} $0&lt;br /&gt;
    StrCpy $6 $2 1 -1 # copy last char&lt;br /&gt;
    StrCmp $6 &amp;quot;;&amp;quot; +2 # if last char != ;&lt;br /&gt;
      StrCpy $2 &amp;quot;$2;&amp;quot; # append ;&lt;br /&gt;
    Push $2&lt;br /&gt;
    Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
    Call un.StrStr ; Find `$1;` in $2&lt;br /&gt;
    Pop $3 ; pos of our dir&lt;br /&gt;
    StrCmp $3 &amp;quot;&amp;quot; unRemoveFromEnvVar_done&lt;br /&gt;
      ; else, it is in path&lt;br /&gt;
      # $1 - path to add&lt;br /&gt;
      # $2 - path var&lt;br /&gt;
      StrLen $4 &amp;quot;$1;&amp;quot;&lt;br /&gt;
      StrLen $5 $3&lt;br /&gt;
      StrCpy $6 $2 -$5 # $6 is now the part before the path to remove&lt;br /&gt;
      StrCpy $7 $3 &amp;quot;&amp;quot; $4 # $7 is now the part after the path to remove&lt;br /&gt;
      StrCpy $4 $6$7&lt;br /&gt;
 &lt;br /&gt;
      StrCpy $6 $4 1 -1 # copy last char&lt;br /&gt;
      StrCmp $6 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
      StrCpy $4 $4 -1 # remove last char&lt;br /&gt;
 &lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $4&lt;br /&gt;
&lt;br /&gt;
      ; delete reg value if null&lt;br /&gt;
      StrCmp $4 &amp;quot;&amp;quot; 0 +2 # if null delete reg&lt;br /&gt;
      DeleteRegValue ${WriteEnvStr_RegKey} $0&lt;br /&gt;
&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
 &lt;br /&gt;
  unRemoveFromEnvVar_done:&lt;br /&gt;
    Pop $7&lt;br /&gt;
    Pop $6&lt;br /&gt;
    Pop $5&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
!ifndef IsNT_KiCHiK&lt;br /&gt;
!define IsNT_KiCHiK&lt;br /&gt;
&lt;br /&gt;
###########################################&lt;br /&gt;
#            Utility Functions            #&lt;br /&gt;
###########################################&lt;br /&gt;
&lt;br /&gt;
; IsNT&lt;br /&gt;
; no input&lt;br /&gt;
; output, top of the stack = 1 if NT or 0 if not&lt;br /&gt;
;&lt;br /&gt;
; Usage:&lt;br /&gt;
;   Call IsNT&lt;br /&gt;
;   Pop $R0&lt;br /&gt;
;  ($R0 at this point is 1 or 0)&lt;br /&gt;
&lt;br /&gt;
!macro IsNT un&lt;br /&gt;
Function ${un}IsNT&lt;br /&gt;
  Push $0&lt;br /&gt;
  ReadRegStr $0 HKLM &amp;quot;SOFTWARE\Microsoft\Windows NT\CurrentVersion&amp;quot; CurrentVersion&lt;br /&gt;
  StrCmp $0 &amp;quot;&amp;quot; 0 IsNT_yes&lt;br /&gt;
  ; we are not NT.&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Push 0&lt;br /&gt;
  Return&lt;br /&gt;
&lt;br /&gt;
  IsNT_yes:&lt;br /&gt;
    ; NT!!!&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Push 1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro IsNT &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro IsNT &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!endif ; IsNT_KiCHiK&lt;br /&gt;
&lt;br /&gt;
; StrStr&lt;br /&gt;
; input, top of stack = string to search for&lt;br /&gt;
;        top of stack-1 = string to search in&lt;br /&gt;
; output, top of stack (replaces with the portion of the string remaining)&lt;br /&gt;
; modifies no other variables.&lt;br /&gt;
;&lt;br /&gt;
; Usage:&lt;br /&gt;
;   Push &amp;quot;this is a long ass string&amp;quot;&lt;br /&gt;
;   Push &amp;quot;ass&amp;quot;&lt;br /&gt;
;   Call StrStr&lt;br /&gt;
;   Pop $R0&lt;br /&gt;
;  ($R0 at this point is &amp;quot;ass string&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
!macro StrStr un&lt;br /&gt;
Function ${un}StrStr&lt;br /&gt;
Exch $R1 ; st=haystack,old$R1, $R1=needle&lt;br /&gt;
  Exch    ; st=old$R1,haystack&lt;br /&gt;
  Exch $R2 ; st=old$R1,old$R2, $R2=haystack&lt;br /&gt;
  Push $R3&lt;br /&gt;
  Push $R4&lt;br /&gt;
  Push $R5&lt;br /&gt;
  StrLen $R3 $R1&lt;br /&gt;
  StrCpy $R4 0&lt;br /&gt;
  ; $R1=needle&lt;br /&gt;
  ; $R2=haystack&lt;br /&gt;
  ; $R3=len(needle)&lt;br /&gt;
  ; $R4=cnt&lt;br /&gt;
  ; $R5=tmp&lt;br /&gt;
  loop:&lt;br /&gt;
    StrCpy $R5 $R2 $R3 $R4&lt;br /&gt;
    StrCmp $R5 $R1 done&lt;br /&gt;
    StrCmp $R5 &amp;quot;&amp;quot; done&lt;br /&gt;
    IntOp $R4 $R4 + 1&lt;br /&gt;
    Goto loop&lt;br /&gt;
done:&lt;br /&gt;
  StrCpy $R1 $R2 &amp;quot;&amp;quot; $R4&lt;br /&gt;
  Pop $R5&lt;br /&gt;
  Pop $R4&lt;br /&gt;
  Pop $R3&lt;br /&gt;
  Pop $R2&lt;br /&gt;
  Exch $R1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrStr &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrStr &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!endif ; _AddToPath_nsh&lt;br /&gt;
&lt;br /&gt;
Function Trim ; Added by Pelaca&lt;br /&gt;
	Exch $R1&lt;br /&gt;
	Push $R2&lt;br /&gt;
Loop:&lt;br /&gt;
	StrCpy $R2 &amp;quot;$R1&amp;quot; 1 -1&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot; &amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;$\n&amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;$\r&amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;;&amp;quot; RTrim&lt;br /&gt;
	GoTo Done&lt;br /&gt;
RTrim:	&lt;br /&gt;
	StrCpy $R1 &amp;quot;$R1&amp;quot; -1&lt;br /&gt;
	Goto Loop&lt;br /&gt;
Done:&lt;br /&gt;
	Pop $R2&lt;br /&gt;
	Exch $R1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15626</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15626"/>
		<updated>2008-07-03T14:48:40Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Parameters */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read the contents of EnvVarName from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# Remove all instances of the target path/string regardless of the operation because this not only eliminates duplicate entries, it also allows for the search order of the target entry to be changed from first to last and vice versa.&lt;br /&gt;
# If Action is &amp;quot;R&amp;quot; (remove), skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated variable to RegLoc even if the Action is &amp;quot;R&amp;quot; or the target is not found because this allows for the elimination of duplicate semicolons, spaces around semicolons, spaces preceding the first entry, and spaces following the last entry.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
==== Syntax ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
:; ResultVar&lt;br /&gt;
::Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
:; EnvVarName&lt;br /&gt;
:: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
:; Action&lt;br /&gt;
:: &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
:; RegLoc&lt;br /&gt;
:: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
:: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
:; PathString&lt;br /&gt;
:: A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   &lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
; NOTE: Do not substitute &#039;StrReplaceV4&#039; for this function. It will fail due to the way I call it.&lt;br /&gt;
;&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15625</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15625"/>
		<updated>2008-07-03T14:47:00Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Syntax */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read the contents of EnvVarName from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# Remove all instances of the target path/string regardless of the operation because this not only eliminates duplicate entries, it also allows for the search order of the target entry to be changed from first to last and vice versa.&lt;br /&gt;
# If Action is &amp;quot;R&amp;quot; (remove), skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated variable to RegLoc even if the Action is &amp;quot;R&amp;quot; or the target is not found because this allows for the elimination of duplicate semicolons, spaces around semicolons, spaces preceding the first entry, and spaces following the last entry.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
==== Syntax ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
; ResultVar&lt;br /&gt;
:Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
; EnvVarName&lt;br /&gt;
: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
; Action&lt;br /&gt;
: &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
; RegLoc&lt;br /&gt;
: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
; PathString&lt;br /&gt;
: A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   &lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
; NOTE: Do not substitute &#039;StrReplaceV4&#039; for this function. It will fail due to the way I call it.&lt;br /&gt;
;&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Path_Manipulation&amp;diff=15624</id>
		<title>Path Manipulation</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Path_Manipulation&amp;diff=15624"/>
		<updated>2008-07-03T14:42:55Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2, KiCHiK}}&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname from the PATH environmental variable in either the &amp;quot;all users&amp;quot; (HKLM) or the &amp;quot;current user&amp;quot; (HKCU) section of the registry. &lt;br /&gt;
&lt;br /&gt;
Duplicates entries, leading and trailing spaces around each entry, and duplicate semicolons are removed from the contents of PATH before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname).&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
=== Syntax ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;Pathname&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;Pathname&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
:; ResultVar&lt;br /&gt;
:: Updated contents PATH returned by the function&lt;br /&gt;
&lt;br /&gt;
:; EnvVarName&lt;br /&gt;
:: &amp;quot;PATH&amp;quot; &lt;br /&gt;
&lt;br /&gt;
:; Action&lt;br /&gt;
:: &amp;quot;A&amp;quot; = Append&lt;br /&gt;
:: &amp;quot;P&amp;quot; = Prepend&lt;br /&gt;
:: &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
:; RegLoc&lt;br /&gt;
:: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
:: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
:; Pathname&lt;br /&gt;
:: Pathname to add to or remove from the contents of PATH (e.g., &amp;quot;C:\MyApp&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\Windows Resource Kits\Tools&amp;quot;  &lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;%WinDir%\System32&amp;quot;  &lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v1.0&amp;quot;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Program Files\MyApp-v2.0&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v1.0&amp;quot;   &lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib-v2.0&amp;quot;   &lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dependencies == &lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;EnvVarUpdate&#039;&#039;&#039; (available at  [[Environmental_Variables:_append%2C_prepend%2C_and_remove_entries]])&lt;br /&gt;
* &#039;&#039;&#039;StrTok, StrContains, and StrReplace:&#039;&#039;&#039;  Included in the EnvVarUpdate function code &lt;br /&gt;
* &#039;&#039;&#039;LogicLib header file:&#039;&#039;&#039; &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Credits ==&lt;br /&gt;
&lt;br /&gt;
* Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
* Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr  &lt;br /&gt;
* Diego Pedroso (deguix) for StrTok&lt;br /&gt;
* Kevin English (kenglish_hi)for StrContains&lt;br /&gt;
* Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Functions for Windows 95, 98, and ME ==&lt;br /&gt;
&lt;br /&gt;
The following routines, AddToPath, un.RemoveFromPath, AddToEnvVar, and un.RemoveFromEnvVar are provided for Windows 95, 98, or ME in that they support the update of the autoexec.bat file.  Note that they can cause corruption of the PATH if the path being removed happens to be a subset of another path.   For example, if PATH contains &amp;quot;C:\Windows\system32\wbem&amp;quot; and you remove&lt;br /&gt;
&amp;quot;C:\Windows\system32&amp;quot; the result is &amp;quot;\wbem&amp;quot;.  They also do not prevent duplication of entries if ,for example, the user runs the installer multiple times.    &lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
Here are four functions, two for adding to and removing directories from the search path (i.e. PATH environment variable) of Windows and two more for adding to and removing directories from a user defined environment variable such as INCLUDE or LIB etc. These functions should work on every version of Windows including 95, 98, ME, NT, 2000, and XP.&lt;br /&gt;
&lt;br /&gt;
For Windows NT/2000/XP they will write to HKEY_CURRENT_USER\Environment\PATH. For 9x/ME they will write to the autoexec.bat file.&lt;br /&gt;
&lt;br /&gt;
Changes on 9x machines will take place after a reboot. These functions set the reboot flag if the path variable was changed on 9x.&lt;br /&gt;
&lt;br /&gt;
These functions require NSIS 2.0b0 and above due to the usage of SendMessage with /TIMEOUT. It is possible to use it with earlier versions of NSIS with a little application I have created called RefreshEnv. It does exactly the same as SendMessage with /TIMEOUT. You can find it at [http://forums.winamp.com/showthread.php?s=&amp;amp;threadid=77904&amp;amp;highlight=refreshenv this forum thread].&lt;br /&gt;
&lt;br /&gt;
The directory added to the path must exist prior to calling this function.&lt;br /&gt;
&lt;br /&gt;
=== Usage Example ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;Section &amp;quot;Add to path&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call AddToPath&lt;br /&gt;
&lt;br /&gt;
  Push &amp;quot;LIB&amp;quot;&lt;br /&gt;
  Push &amp;quot;c:\Mylibrary\lib&amp;quot;&lt;br /&gt;
  Call AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
  ;likewise AddToPath could be&lt;br /&gt;
  Push &amp;quot;PATH&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
SectionEnd&lt;br /&gt;
&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Section &amp;quot;uninstall&amp;quot;&lt;br /&gt;
  # ...&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call un.RemoveFromPath&lt;br /&gt;
  # ...&lt;br /&gt;
  Push &amp;quot;LIB&amp;quot;&lt;br /&gt;
  Push &amp;quot;c:\Mylibrary\lib&amp;quot;&lt;br /&gt;
  Call un.RemoveFromEnvVar&lt;br /&gt;
&lt;br /&gt;
  ;Likewise RemoveFromPath could be&lt;br /&gt;
  Push &amp;quot;PATH&amp;quot;&lt;br /&gt;
  Push $INSTDIR&lt;br /&gt;
  Call un.RemoveFromEnvVar&lt;br /&gt;
  &lt;br /&gt;
SectionEnd&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Functions ===&lt;br /&gt;
The functions in the flesh:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;!ifndef _AddToPath_nsh&lt;br /&gt;
!define _AddToPath_nsh&lt;br /&gt;
&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
!verbose 4&lt;br /&gt;
&lt;br /&gt;
!ifndef WriteEnvStr_RegKey&lt;br /&gt;
  !ifdef ALL_USERS&lt;br /&gt;
    !define WriteEnvStr_RegKey \&lt;br /&gt;
       &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
  !else&lt;br /&gt;
    !define WriteEnvStr_RegKey &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
  !endif&lt;br /&gt;
!endif&lt;br /&gt;
&lt;br /&gt;
; AddToPath - Adds the given dir to the search path.&lt;br /&gt;
;        Input - head of the stack&lt;br /&gt;
;        Note - Win9x systems requires reboot&lt;br /&gt;
&lt;br /&gt;
Function AddToPath&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Push $1&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
&lt;br /&gt;
  # don&#039;t add if the path doesn&#039;t exist&lt;br /&gt;
  IfFileExists &amp;quot;$0\*.*&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  ReadEnvStr $1 PATH&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$0;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$0\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  GetFullPathName /SHORT $3 $0&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$3;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$3\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  Call IsNT&lt;br /&gt;
  Pop $1&lt;br /&gt;
  StrCmp $1 1 AddToPath_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $1 $WINDIR 2&lt;br /&gt;
    FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; a&lt;br /&gt;
    FileSeek $1 -1 END&lt;br /&gt;
    FileReadByte $1 $2&lt;br /&gt;
    IntCmp $2 26 0 +2 +2 # DOS EOF&lt;br /&gt;
      FileSeek $1 -1 END # write over EOF&lt;br /&gt;
    FileWrite $1 &amp;quot;$\r$\nSET PATH=%PATH%;$3$\r$\n&amp;quot;&lt;br /&gt;
    FileClose $1&lt;br /&gt;
    SetRebootFlag true&lt;br /&gt;
    Goto AddToPath_done&lt;br /&gt;
&lt;br /&gt;
  AddToPath_NT:&lt;br /&gt;
    ReadRegStr $1 ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot;&lt;br /&gt;
    StrCmp $1 &amp;quot;&amp;quot; AddToPath_NTdoIt&lt;br /&gt;
      Push $1&lt;br /&gt;
      Call Trim&lt;br /&gt;
      Pop $1&lt;br /&gt;
      StrCpy $0 &amp;quot;$1;$0&amp;quot;&lt;br /&gt;
    AddToPath_NTdoIt:&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot; $0&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  AddToPath_done:&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
; RemoveFromPath - Remove a given dir from the path&lt;br /&gt;
;     Input: head of the stack&lt;br /&gt;
&lt;br /&gt;
Function un.RemoveFromPath&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Push $1&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
&lt;br /&gt;
  IntFmt $6 &amp;quot;%c&amp;quot; 26 # DOS EOF&lt;br /&gt;
&lt;br /&gt;
  Call un.IsNT&lt;br /&gt;
  Pop $1&lt;br /&gt;
  StrCmp $1 1 unRemoveFromPath_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $1 $WINDIR 2&lt;br /&gt;
    FileOpen $1 &amp;quot;$1\autoexec.bat&amp;quot; r&lt;br /&gt;
    GetTempFileName $4&lt;br /&gt;
    FileOpen $2 $4 w&lt;br /&gt;
    GetFullPathName /SHORT $0 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;SET PATH=%PATH%;$0&amp;quot;&lt;br /&gt;
    Goto unRemoveFromPath_dosLoop&lt;br /&gt;
&lt;br /&gt;
    unRemoveFromPath_dosLoop:&lt;br /&gt;
      FileRead $1 $3&lt;br /&gt;
      StrCpy $5 $3 1 -1 # read last char&lt;br /&gt;
      StrCmp $5 $6 0 +2 # if DOS EOF&lt;br /&gt;
        StrCpy $3 $3 -1 # remove DOS EOF so we can compare&lt;br /&gt;
      StrCmp $3 &amp;quot;$0$\r$\n&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;$0$\n&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;$0&amp;quot; unRemoveFromPath_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $3 &amp;quot;&amp;quot; unRemoveFromPath_dosLoopEnd&lt;br /&gt;
      FileWrite $2 $3&lt;br /&gt;
      Goto unRemoveFromPath_dosLoop&lt;br /&gt;
      unRemoveFromPath_dosLoopRemoveLine:&lt;br /&gt;
        SetRebootFlag true&lt;br /&gt;
        Goto unRemoveFromPath_dosLoop&lt;br /&gt;
&lt;br /&gt;
    unRemoveFromPath_dosLoopEnd:&lt;br /&gt;
      FileClose $2&lt;br /&gt;
      FileClose $1&lt;br /&gt;
      StrCpy $1 $WINDIR 2&lt;br /&gt;
      Delete &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
      CopyFiles /SILENT $4 &amp;quot;$1\autoexec.bat&amp;quot;&lt;br /&gt;
      Delete $4&lt;br /&gt;
      Goto unRemoveFromPath_done&lt;br /&gt;
&lt;br /&gt;
  unRemoveFromPath_NT:&lt;br /&gt;
    ReadRegStr $1 ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot;&lt;br /&gt;
    StrCpy $5 $1 1 -1 # copy last char&lt;br /&gt;
    StrCmp $5 &amp;quot;;&amp;quot; +2 # if last char != ;&lt;br /&gt;
      StrCpy $1 &amp;quot;$1;&amp;quot; # append ;&lt;br /&gt;
    Push $1&lt;br /&gt;
    Push &amp;quot;$0;&amp;quot;&lt;br /&gt;
    Call un.StrStr ; Find `$0;` in $1&lt;br /&gt;
    Pop $2 ; pos of our dir&lt;br /&gt;
    StrCmp $2 &amp;quot;&amp;quot; unRemoveFromPath_done&lt;br /&gt;
      ; else, it is in path&lt;br /&gt;
      # $0 - path to add&lt;br /&gt;
      # $1 - path var&lt;br /&gt;
      StrLen $3 &amp;quot;$0;&amp;quot;&lt;br /&gt;
      StrLen $4 $2&lt;br /&gt;
      StrCpy $5 $1 -$4 # $5 is now the part before the path to remove&lt;br /&gt;
      StrCpy $6 $2 &amp;quot;&amp;quot; $3 # $6 is now the part after the path to remove&lt;br /&gt;
      StrCpy $3 $5$6&lt;br /&gt;
&lt;br /&gt;
      StrCpy $5 $3 1 -1 # copy last char&lt;br /&gt;
      StrCmp $5 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
        StrCpy $3 $3 -1 # remove last char&lt;br /&gt;
&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} &amp;quot;PATH&amp;quot; $3&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  unRemoveFromPath_done:&lt;br /&gt;
    Pop $6&lt;br /&gt;
    Pop $5&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; AddToEnvVar - Adds the given value to the given environment var&lt;br /&gt;
;        Input - head of the stack $0 environement variable $1=value to add&lt;br /&gt;
;        Note - Win9x systems requires reboot&lt;br /&gt;
 &lt;br /&gt;
Function AddToEnvVar&lt;br /&gt;
&lt;br /&gt;
  Exch $1 ; $1 has environment variable value&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $0 ; $0 has environment variable name&lt;br /&gt;
&lt;br /&gt;
  DetailPrint &amp;quot;Adding $1 to $0&amp;quot;&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
  ReadEnvStr $2 $0&lt;br /&gt;
  Push &amp;quot;$2;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $3&lt;br /&gt;
  StrCmp $3 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToEnvVar_done&lt;br /&gt;
&lt;br /&gt;
  Push &amp;quot;$2;&amp;quot;&lt;br /&gt;
  Push &amp;quot;$1\;&amp;quot;&lt;br /&gt;
  Call StrStr&lt;br /&gt;
  Pop $3&lt;br /&gt;
  StrCmp $3 &amp;quot;&amp;quot; &amp;quot;&amp;quot; AddToEnvVar_done&lt;br /&gt;
  &lt;br /&gt;
 &lt;br /&gt;
  Call IsNT&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 1 AddToEnvVar_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $2 $WINDIR 2&lt;br /&gt;
    FileOpen $2 &amp;quot;$2\autoexec.bat&amp;quot; a&lt;br /&gt;
    FileSeek $2 -1 END&lt;br /&gt;
    FileReadByte $2 $3&lt;br /&gt;
    IntCmp $3 26 0 +2 +2 # DOS EOF&lt;br /&gt;
      FileSeek $2 -1 END # write over EOF&lt;br /&gt;
    FileWrite $2 &amp;quot;$\r$\nSET $0=%$0%;$4$\r$\n&amp;quot;&lt;br /&gt;
    FileClose $2&lt;br /&gt;
    SetRebootFlag true&lt;br /&gt;
    Goto AddToEnvVar_done&lt;br /&gt;
 &lt;br /&gt;
  AddToEnvVar_NT:&lt;br /&gt;
    ReadRegStr $2 ${WriteEnvStr_RegKey} $0&lt;br /&gt;
    StrCpy $3 $2 1 -1 # copy last char&lt;br /&gt;
    StrCmp $3 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
      StrCpy $2 $2 -1 # remove last char&lt;br /&gt;
    StrCmp $2 &amp;quot;&amp;quot; AddToEnvVar_NTdoIt&lt;br /&gt;
      StrCpy $1 &amp;quot;$2;$1&amp;quot;&lt;br /&gt;
    AddToEnvVar_NTdoIt:&lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $1&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
&lt;br /&gt;
  AddToEnvVar_done:&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Pop $1&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
 &lt;br /&gt;
; RemoveFromEnvVar - Remove a given value from a environment var&lt;br /&gt;
;     Input: head of the stack&lt;br /&gt;
 &lt;br /&gt;
Function un.RemoveFromEnvVar&lt;br /&gt;
&lt;br /&gt;
  Exch $1 ; $1 has environment variable value&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $0 ; $0 has environment variable name&lt;br /&gt;
&lt;br /&gt;
  DetailPrint &amp;quot;Removing $1 from $0&amp;quot;&lt;br /&gt;
  Push $2&lt;br /&gt;
  Push $3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
 &lt;br /&gt;
  IntFmt $7 &amp;quot;%c&amp;quot; 26 # DOS EOF&lt;br /&gt;
 &lt;br /&gt;
  Call un.IsNT&lt;br /&gt;
  Pop $2&lt;br /&gt;
  StrCmp $2 1 unRemoveFromEnvVar_NT&lt;br /&gt;
    ; Not on NT&lt;br /&gt;
    StrCpy $2 $WINDIR 2&lt;br /&gt;
    FileOpen $2 &amp;quot;$2\autoexec.bat&amp;quot; r&lt;br /&gt;
    GetTempFileName $5&lt;br /&gt;
    FileOpen $3 $5 w&lt;br /&gt;
    GetFullPathName /SHORT $1 $1&lt;br /&gt;
    StrCpy $1 &amp;quot;SET $0=%$0%;$1&amp;quot;&lt;br /&gt;
    Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
 &lt;br /&gt;
    unRemoveFromEnvVar_dosLoop:&lt;br /&gt;
      FileRead $2 $4&lt;br /&gt;
      StrCpy $6 $4 1 -1 # read last char&lt;br /&gt;
      StrCmp $6 $7 0 +2 # if DOS EOF&lt;br /&gt;
        StrCpy $4 $4 -1 # remove DOS EOF so we can compare&lt;br /&gt;
      StrCmp $4 &amp;quot;$1$\r$\n&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;$1$\n&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;$1&amp;quot; unRemoveFromEnvVar_dosLoopRemoveLine&lt;br /&gt;
      StrCmp $4 &amp;quot;&amp;quot; unRemoveFromEnvVar_dosLoopEnd&lt;br /&gt;
      FileWrite $3 $4&lt;br /&gt;
      Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
      unRemoveFromEnvVar_dosLoopRemoveLine:&lt;br /&gt;
        SetRebootFlag true&lt;br /&gt;
        Goto unRemoveFromEnvVar_dosLoop&lt;br /&gt;
 &lt;br /&gt;
    unRemoveFromEnvVar_dosLoopEnd:&lt;br /&gt;
      FileClose $3&lt;br /&gt;
      FileClose $2&lt;br /&gt;
      StrCpy $2 $WINDIR 2&lt;br /&gt;
      Delete &amp;quot;$2\autoexec.bat&amp;quot;&lt;br /&gt;
      CopyFiles /SILENT $5 &amp;quot;$2\autoexec.bat&amp;quot;&lt;br /&gt;
      Delete $5&lt;br /&gt;
      Goto unRemoveFromEnvVar_done&lt;br /&gt;
 &lt;br /&gt;
  unRemoveFromEnvVar_NT:&lt;br /&gt;
    ReadRegStr $2 ${WriteEnvStr_RegKey} $0&lt;br /&gt;
    StrCpy $6 $2 1 -1 # copy last char&lt;br /&gt;
    StrCmp $6 &amp;quot;;&amp;quot; +2 # if last char != ;&lt;br /&gt;
      StrCpy $2 &amp;quot;$2;&amp;quot; # append ;&lt;br /&gt;
    Push $2&lt;br /&gt;
    Push &amp;quot;$1;&amp;quot;&lt;br /&gt;
    Call un.StrStr ; Find `$1;` in $2&lt;br /&gt;
    Pop $3 ; pos of our dir&lt;br /&gt;
    StrCmp $3 &amp;quot;&amp;quot; unRemoveFromEnvVar_done&lt;br /&gt;
      ; else, it is in path&lt;br /&gt;
      # $1 - path to add&lt;br /&gt;
      # $2 - path var&lt;br /&gt;
      StrLen $4 &amp;quot;$1;&amp;quot;&lt;br /&gt;
      StrLen $5 $3&lt;br /&gt;
      StrCpy $6 $2 -$5 # $6 is now the part before the path to remove&lt;br /&gt;
      StrCpy $7 $3 &amp;quot;&amp;quot; $4 # $7 is now the part after the path to remove&lt;br /&gt;
      StrCpy $4 $6$7&lt;br /&gt;
 &lt;br /&gt;
      StrCpy $6 $4 1 -1 # copy last char&lt;br /&gt;
      StrCmp $6 &amp;quot;;&amp;quot; 0 +2 # if last char == ;&lt;br /&gt;
      StrCpy $4 $4 -1 # remove last char&lt;br /&gt;
 &lt;br /&gt;
      WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $4&lt;br /&gt;
&lt;br /&gt;
      ; delete reg value if null&lt;br /&gt;
      StrCmp $4 &amp;quot;&amp;quot; 0 +2 # if null delete reg&lt;br /&gt;
      DeleteRegValue ${WriteEnvStr_RegKey} $0&lt;br /&gt;
&lt;br /&gt;
      SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000&lt;br /&gt;
 &lt;br /&gt;
  unRemoveFromEnvVar_done:&lt;br /&gt;
    Pop $7&lt;br /&gt;
    Pop $6&lt;br /&gt;
    Pop $5&lt;br /&gt;
    Pop $4&lt;br /&gt;
    Pop $3&lt;br /&gt;
    Pop $2&lt;br /&gt;
    Pop $1&lt;br /&gt;
    Pop $0&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
!ifndef IsNT_KiCHiK&lt;br /&gt;
!define IsNT_KiCHiK&lt;br /&gt;
&lt;br /&gt;
###########################################&lt;br /&gt;
#            Utility Functions            #&lt;br /&gt;
###########################################&lt;br /&gt;
&lt;br /&gt;
; IsNT&lt;br /&gt;
; no input&lt;br /&gt;
; output, top of the stack = 1 if NT or 0 if not&lt;br /&gt;
;&lt;br /&gt;
; Usage:&lt;br /&gt;
;   Call IsNT&lt;br /&gt;
;   Pop $R0&lt;br /&gt;
;  ($R0 at this point is 1 or 0)&lt;br /&gt;
&lt;br /&gt;
!macro IsNT un&lt;br /&gt;
Function ${un}IsNT&lt;br /&gt;
  Push $0&lt;br /&gt;
  ReadRegStr $0 HKLM &amp;quot;SOFTWARE\Microsoft\Windows NT\CurrentVersion&amp;quot; CurrentVersion&lt;br /&gt;
  StrCmp $0 &amp;quot;&amp;quot; 0 IsNT_yes&lt;br /&gt;
  ; we are not NT.&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Push 0&lt;br /&gt;
  Return&lt;br /&gt;
&lt;br /&gt;
  IsNT_yes:&lt;br /&gt;
    ; NT!!!&lt;br /&gt;
    Pop $0&lt;br /&gt;
    Push 1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro IsNT &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro IsNT &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!endif ; IsNT_KiCHiK&lt;br /&gt;
&lt;br /&gt;
; StrStr&lt;br /&gt;
; input, top of stack = string to search for&lt;br /&gt;
;        top of stack-1 = string to search in&lt;br /&gt;
; output, top of stack (replaces with the portion of the string remaining)&lt;br /&gt;
; modifies no other variables.&lt;br /&gt;
;&lt;br /&gt;
; Usage:&lt;br /&gt;
;   Push &amp;quot;this is a long ass string&amp;quot;&lt;br /&gt;
;   Push &amp;quot;ass&amp;quot;&lt;br /&gt;
;   Call StrStr&lt;br /&gt;
;   Pop $R0&lt;br /&gt;
;  ($R0 at this point is &amp;quot;ass string&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
!macro StrStr un&lt;br /&gt;
Function ${un}StrStr&lt;br /&gt;
Exch $R1 ; st=haystack,old$R1, $R1=needle&lt;br /&gt;
  Exch    ; st=old$R1,haystack&lt;br /&gt;
  Exch $R2 ; st=old$R1,old$R2, $R2=haystack&lt;br /&gt;
  Push $R3&lt;br /&gt;
  Push $R4&lt;br /&gt;
  Push $R5&lt;br /&gt;
  StrLen $R3 $R1&lt;br /&gt;
  StrCpy $R4 0&lt;br /&gt;
  ; $R1=needle&lt;br /&gt;
  ; $R2=haystack&lt;br /&gt;
  ; $R3=len(needle)&lt;br /&gt;
  ; $R4=cnt&lt;br /&gt;
  ; $R5=tmp&lt;br /&gt;
  loop:&lt;br /&gt;
    StrCpy $R5 $R2 $R3 $R4&lt;br /&gt;
    StrCmp $R5 $R1 done&lt;br /&gt;
    StrCmp $R5 &amp;quot;&amp;quot; done&lt;br /&gt;
    IntOp $R4 $R4 + 1&lt;br /&gt;
    Goto loop&lt;br /&gt;
done:&lt;br /&gt;
  StrCpy $R1 $R2 &amp;quot;&amp;quot; $R4&lt;br /&gt;
  Pop $R5&lt;br /&gt;
  Pop $R4&lt;br /&gt;
  Pop $R3&lt;br /&gt;
  Pop $R2&lt;br /&gt;
  Exch $R1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrStr &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrStr &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!endif ; _AddToPath_nsh&lt;br /&gt;
&lt;br /&gt;
Function Trim ; Added by Pelaca&lt;br /&gt;
	Exch $R1&lt;br /&gt;
	Push $R2&lt;br /&gt;
Loop:&lt;br /&gt;
	StrCpy $R2 &amp;quot;$R1&amp;quot; 1 -1&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot; &amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;$\n&amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;$\r&amp;quot; RTrim&lt;br /&gt;
	StrCmp &amp;quot;$R2&amp;quot; &amp;quot;;&amp;quot; RTrim&lt;br /&gt;
	GoTo Done&lt;br /&gt;
RTrim:	&lt;br /&gt;
	StrCpy $R1 &amp;quot;$R1&amp;quot; -1&lt;br /&gt;
	Goto Loop&lt;br /&gt;
Done:&lt;br /&gt;
	Pop $R2&lt;br /&gt;
	Exch $R1&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15619</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15619"/>
		<updated>2008-07-03T13:06:25Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read the contents of EnvVarName from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# Remove all instances of the target path/string regardless of the operation because this not only eliminates duplicate entries, it also allows for the search order of the target entry to be changed from first to last and vice versa.&lt;br /&gt;
# If Action is &amp;quot;R&amp;quot; (remove), skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated variable to RegLoc even if the Action is &amp;quot;R&amp;quot; or the target is not found because this allows for the elimination of duplicate semicolons, spaces around semicolons, spaces preceding the first entry, and spaces following the last entry.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
==== Syntax ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
; ResultVar&lt;br /&gt;
:Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
; EnvVarName&lt;br /&gt;
: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
; Action&lt;br /&gt;
: &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
; RegLoc&lt;br /&gt;
: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
; PathString&lt;br /&gt;
: A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   &lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
; NOTE: Do not substitute &#039;StrReplaceV4&#039; for this function. It will fail due to the way I call it.&lt;br /&gt;
;&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15617</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15617"/>
		<updated>2008-07-03T02:03:08Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read the contents of EnvVarName from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# Remove all instances of the target path/string regardless of the operation because this not only eliminates duplicate entries, it also allows for the search order of the target entry to be changed from first to last and vice versa.&lt;br /&gt;
# If Action is &amp;quot;R&amp;quot; (remove), skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated variable to RegLoc even if the Action is &amp;quot;R&amp;quot; or the target is not found because this allows for the elimination of duplicate semicolons, spaces around semicolons, spaces preceding the first entry, and spaces following the last entry.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
==== Syntax ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
; ResultVar&lt;br /&gt;
:Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
; EnvVarName&lt;br /&gt;
: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
; Action&lt;br /&gt;
: &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
; RegLoc&lt;br /&gt;
: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
; PathString&lt;br /&gt;
: A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   &lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
; NOTE: Do not substitute &#039;StrReplaceV4&#039; for this function. It will fail due to the way I call it.&lt;br /&gt;
;&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15616</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15616"/>
		<updated>2008-07-03T02:00:08Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Usage */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read the contents of EnvVarName from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# Remove all instances of the target path/string regardless of the operation because this not only eliminates duplicate entries, it also allows for the search order of the target entry to be changed from first to last and vice versa.&lt;br /&gt;
# If Action is &amp;quot;R&amp;quot; (remove), skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated variable to RegLoc even if the Action is &amp;quot;R&amp;quot; or the target is not found because this allows for the elimination of duplicate semicolons, spaces around semicolons, spaces preceding the first entry, and spaces following the last entry.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
==== Syntax ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
; ResultVar&lt;br /&gt;
:Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
; EnvVarName&lt;br /&gt;
: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
; Action&lt;br /&gt;
: &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
; RegLoc&lt;br /&gt;
: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
; PathString&lt;br /&gt;
: A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   &lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
; NOTE: Do not substitute &#039;StrReplaceV4&#039; for this function. It will fail due to the way I call it.&lt;br /&gt;
;&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15615</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15615"/>
		<updated>2008-07-03T01:56:34Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read the contents of EnvVarName from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# Remove all instances of the target path/string regardless of the operation because this not only eliminates duplicate entries, it also allows for the search order of the target entry to be changed from first to last and vice versa.&lt;br /&gt;
# If Action is &amp;quot;R&amp;quot; (remove), skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated variable to RegLoc even if the Action is &amp;quot;R&amp;quot; or the target is not found because this allows for the elimination of duplicate semicolons, spaces around semicolons, spaces preceding the first entry, and spaces following the last entry.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
; ResultVar&lt;br /&gt;
:Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
; EnvVarName&lt;br /&gt;
: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
; Action&lt;br /&gt;
: &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
; RegLoc&lt;br /&gt;
: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
; PathString&lt;br /&gt;
: A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   &lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
; NOTE: Do not substitute &#039;StrReplaceV4&#039; for this function. It will fail due to the way I call it.&lt;br /&gt;
;&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15614</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15614"/>
		<updated>2008-07-03T01:51:09Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Function Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read EnvVar from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# All instances of the target path/string are removed from the variable regardless of the operation because this not only eliminates duplicate entries, it also allows for the search order of the target entry to be changed from first to last and vice versa.&lt;br /&gt;
# If the operation is Remove, skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated variable to RegLoc even if the Action is &amp;quot;R&amp;quot; (remove) or the target is not found because this allows for the elimination of duplicate semicolons, spaces around semicolons, spaces preceding the first entry, and spaces following the last entry.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
; ResultVar&lt;br /&gt;
:Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
; EnvVarName&lt;br /&gt;
: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
; Action&lt;br /&gt;
: &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
; RegLoc&lt;br /&gt;
: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
; PathString&lt;br /&gt;
: A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   &lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
; NOTE: Do not substitute &#039;StrReplaceV4&#039; for this function. It will fail due to the way I call it.&lt;br /&gt;
;&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15613</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15613"/>
		<updated>2008-07-03T01:43:52Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Credits */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read EnvVar from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# All instances of the target path/string are removed from the variable regardless of the operation because this not only eliminates duplicate entries, it also allows for the search order of the target entry to be changed from first to last and vice versa.&lt;br /&gt;
# If the operation is Remove, skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated variable to RegLoc even if the Action is &amp;quot;R&amp;quot; (remove) or the target is not found because this allows for the elimination of duplicate semicolons, spaces around semicolons, spaces preceding the first entry, and spaces following the last entry.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
; ResultVar&lt;br /&gt;
:Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
; EnvVarName&lt;br /&gt;
: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
; Action&lt;br /&gt;
: &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
; RegLoc&lt;br /&gt;
: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
; PathString&lt;br /&gt;
: A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0:  Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   &lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
;================================================================================&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
;================================================================================&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15612</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15612"/>
		<updated>2008-07-03T01:42:17Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read EnvVar from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# All instances of the target path/string are removed from the variable regardless of the operation because this not only eliminates duplicate entries, it also allows for the search order of the target entry to be changed from first to last and vice versa.&lt;br /&gt;
# If the operation is Remove, skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated variable to RegLoc even if the Action is &amp;quot;R&amp;quot; (remove) or the target is not found because this allows for the elimination of duplicate semicolons, spaces around semicolons, spaces preceding the first entry, and spaces following the last entry.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
; ResultVar&lt;br /&gt;
:Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
; EnvVarName&lt;br /&gt;
: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
; Action&lt;br /&gt;
: &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
; RegLoc&lt;br /&gt;
: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
; PathString&lt;br /&gt;
: A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0 - Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   &lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
;================================================================================&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
;================================================================================&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15611</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15611"/>
		<updated>2008-07-03T01:38:30Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read EnvVar from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# All instances of target path/string are removed from the variable regardles of the operation because this not only eliminates duplicate entries, it also allows one to change the search order of the target entry from first to last and vice versa.&lt;br /&gt;
# If the operation is Remove, skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated variable to RegLoc even if the Action is &amp;quot;R&amp;quot; (remove) or the target is not found because this allows for the elimination of duplicate semicolons, spaces around semicolons, spaces preceding the first entry, and spaces following the last entry.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
; ResultVar&lt;br /&gt;
:Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
; EnvVarName&lt;br /&gt;
: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
; Action&lt;br /&gt;
: &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
; RegLoc&lt;br /&gt;
: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
; PathString&lt;br /&gt;
: A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0 - Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   &lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
;================================================================================&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
;================================================================================&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15610</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15610"/>
		<updated>2008-07-03T01:28:31Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Function Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read EnvVar from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# All instances of target path/string are removed from the variable regardles of the operation because this not only eliminates duplicate entries, it also allows one to change the search order of the target entry from first to last and vice versa.&lt;br /&gt;
# If the operation is Remove, skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated Envar to RegLoc. The variable is written even if the Action is &amp;quot;R&amp;quot; (remove) or the target is not found, in order to eliminate duplicate semicolons and spaces around semicolons.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
; ResultVar&lt;br /&gt;
:Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
; EnvVarName&lt;br /&gt;
: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
; Action&lt;br /&gt;
: &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
; RegLoc&lt;br /&gt;
: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
; PathString&lt;br /&gt;
: A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0 - Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   &lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
;================================================================================&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
;================================================================================&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15609</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15609"/>
		<updated>2008-07-03T01:25:24Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Function Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read EnvVar from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# All instances of target path/string are removed from the variable regardles of the operation because this not only eliminates duplicate entries, it also allows one to change the search order of the target entry from first to last and vice versa.&lt;br /&gt;
# If the operation is Remove, skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated Envar to RegLoc. The variable is written even if the Action is &amp;quot;R&amp;quot; (remove) or the target is not found, in order to eliminate duplicate semicolons and spaces around semicolons.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
; ResultVar&lt;br /&gt;
:Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
; EnvVarName&lt;br /&gt;
: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
; Action&lt;br /&gt;
: &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
; RegLoc&lt;br /&gt;
: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
; PathString&lt;br /&gt;
: A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0 - Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt;&#039; to &#039;&amp;lt;EnvVar&amp;gt;&#039;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
;================================================================================&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
;================================================================================&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15608</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15608"/>
		<updated>2008-07-03T01:23:08Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Parameters */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read EnvVar from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# All instances of target path/string are removed from the variable regardles of the operation because this not only eliminates duplicate entries, it also allows one to change the search order of the target entry from first to last and vice versa.&lt;br /&gt;
# If the operation is Remove, skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated Envar to RegLoc. The variable is written even if the Action is &amp;quot;R&amp;quot; (remove) or the target is not found, in order to eliminate duplicate semicolons and spaces around semicolons.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
; ResultVar&lt;br /&gt;
:Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
; EnvVarName&lt;br /&gt;
: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
; Action&lt;br /&gt;
: &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
; RegLoc&lt;br /&gt;
: &amp;quot;HKLM&amp;quot; = the &amp;quot;all users&amp;quot; section of the registry&lt;br /&gt;
: &amp;quot;HKCU&amp;quot; = the &amp;quot;current user&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
; PathString&lt;br /&gt;
: A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0 - Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
;================================================================================&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
;================================================================================&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15607</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15607"/>
		<updated>2008-07-03T01:21:15Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read EnvVar from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# All instances of target path/string are removed from the variable regardles of the operation because this not only eliminates duplicate entries, it also allows one to change the search order of the target entry from first to last and vice versa.&lt;br /&gt;
# If the operation is Remove, skip this step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated Envar to RegLoc. The variable is written even if the Action is &amp;quot;R&amp;quot; (remove) or the target is not found, in order to eliminate duplicate semicolons and spaces around semicolons.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
; ResultVar&lt;br /&gt;
:Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
; EnvVarName&lt;br /&gt;
: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
; Action&lt;br /&gt;
: &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
; RegLoc&lt;br /&gt;
: &amp;quot;HKLM&amp;quot; = All users section of registry, &amp;quot;&lt;br /&gt;
: &amp;quot;HKCU&amp;quot; = current user section&lt;br /&gt;
&lt;br /&gt;
; PathString&lt;br /&gt;
: A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0 - Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
;================================================================================&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
;================================================================================&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15605</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15605"/>
		<updated>2008-07-02T23:36:46Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read EnvVar from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# All instances of target path/string are removed from the variable regardles of the operation because not only duplicate entries are eliminated but also allows one to change the search order of the target from first to last and vice versa.&lt;br /&gt;
# If the operation is Remove, skip the step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated Envar to RegLoc. The variable is written even if the Action is &amp;quot;R&amp;quot; (remove) or the target is not found, in order to eliminate duplicate semicolons and spaces around semicolons.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
; ResultVar&lt;br /&gt;
:Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
; EnvVarName&lt;br /&gt;
: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
; Action&lt;br /&gt;
: &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
; RegLoc&lt;br /&gt;
: &amp;quot;HKLM&amp;quot; = All users section of registry, &amp;quot;&lt;br /&gt;
: &amp;quot;HKCU&amp;quot; = current user section&lt;br /&gt;
&lt;br /&gt;
; PathString&lt;br /&gt;
: A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0 - Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
;================================================================================&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
;================================================================================&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15604</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15604"/>
		<updated>2008-07-02T23:33:15Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Parameters */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read EnvVar from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# All instances of target path/string are removed from the variable regardles of the operation because not only duplicate entries are eliminated but also allows one to change the search order of the target from first to last and vice versa.&lt;br /&gt;
# If the operation is Remove, skip the step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated Envar to RegLoc. The variable is written even if the Action is &amp;quot;R&amp;quot; (remove) or the target is not found, in order to eliminate duplicate semicolons and spaces around semicolons.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; ResultVar&lt;br /&gt;
:Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
; EnvVarName&lt;br /&gt;
: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYVAR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
; Action&lt;br /&gt;
: &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
; RegLoc&lt;br /&gt;
: &amp;quot;HKLM&amp;quot; = All users section of registry, &amp;quot;&lt;br /&gt;
: &amp;quot;HKCU&amp;quot; = current user section&lt;br /&gt;
&lt;br /&gt;
; PathString&lt;br /&gt;
: A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0 - Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
;================================================================================&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
;================================================================================&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15603</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15603"/>
		<updated>2008-07-02T23:31:57Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Parameters */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read EnvVar from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# All instances of target path/string are removed from the variable regardles of the operation because not only duplicate entries are eliminated but also allows one to change the search order of the target from first to last and vice versa.&lt;br /&gt;
# If the operation is Remove, skip the step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated Envar to RegLoc. The variable is written even if the Action is &amp;quot;R&amp;quot; (remove) or the target is not found, in order to eliminate duplicate semicolons and spaces around semicolons.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; ResultVar&lt;br /&gt;
:Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
; EnvVarName&lt;br /&gt;
: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYAPP&amp;quot;&lt;br /&gt;
&lt;br /&gt;
; Action&lt;br /&gt;
: &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
; RegLoc&lt;br /&gt;
: &amp;quot;HKLM&amp;quot; = All users section of registry, &amp;quot;HKCU&amp;quot; = current user section&lt;br /&gt;
&lt;br /&gt;
; PathString&lt;br /&gt;
: A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0 - Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
;================================================================================&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
;================================================================================&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15602</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15602"/>
		<updated>2008-07-02T23:30:58Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Parameters */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read EnvVar from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# All instances of target path/string are removed from the variable regardles of the operation because not only duplicate entries are eliminated but also allows one to change the search order of the target from first to last and vice versa.&lt;br /&gt;
# If the operation is Remove, skip the step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated Envar to RegLoc. The variable is written even if the Action is &amp;quot;R&amp;quot; (remove) or the target is not found, in order to eliminate duplicate semicolons and spaces around semicolons.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; ResultVar&lt;br /&gt;
:Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
; EnvVarName&lt;br /&gt;
: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYAPP&amp;quot;&lt;br /&gt;
&lt;br /&gt;
; Action&lt;br /&gt;
: &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
; RegLoc&lt;br /&gt;
: &amp;quot;HKLM&amp;quot; = All users section of registry, &amp;quot;HKCU&amp;quot; = current user section&lt;br /&gt;
&lt;br /&gt;
; PathString&lt;br /&gt;
: A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0 - Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
;================================================================================&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
;================================================================================&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15601</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15601"/>
		<updated>2008-07-02T23:30:17Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Parameters */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read EnvVar from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# All instances of target path/string are removed from the variable regardles of the operation because not only duplicate entries are eliminated but also allows one to change the search order of the target from first to last and vice versa.&lt;br /&gt;
# If the operation is Remove, skip the step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated Envar to RegLoc. The variable is written even if the Action is &amp;quot;R&amp;quot; (remove) or the target is not found, in order to eliminate duplicate semicolons and spaces around semicolons.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
; ResultVar&lt;br /&gt;
:Updated environmental variable returned by the function&lt;br /&gt;
&lt;br /&gt;
; EnvVarName&lt;br /&gt;
: Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYAPP&amp;quot;&lt;br /&gt;
&lt;br /&gt;
; Action&lt;br /&gt;
: &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&lt;br /&gt;
; RegLoc&lt;br /&gt;
: &amp;quot;HKLM&amp;quot; = All users section of registry, &amp;quot;HKCU&amp;quot; = current user section&lt;br /&gt;
&lt;br /&gt;
; PathString&lt;br /&gt;
: A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0 - Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
;================================================================================&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
;================================================================================&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15600</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15600"/>
		<updated>2008-07-02T23:27:27Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Usage */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read EnvVar from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# All instances of target path/string are removed from the variable regardles of the operation because not only duplicate entries are eliminated but also allows one to change the search order of the target from first to last and vice versa.&lt;br /&gt;
# If the operation is Remove, skip the step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated Envar to RegLoc. The variable is written even if the Action is &amp;quot;R&amp;quot; (remove) or the target is not found, in order to eliminate duplicate semicolons and spaces around semicolons.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ResultVar&#039;&#039;&#039;&lt;br /&gt;
Updated environmental variable returned by the function&lt;br /&gt;
&#039;&#039;&#039;EnvVarName&#039;&#039;&#039;&lt;br /&gt;
Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYAPP&amp;quot;&lt;br /&gt;
&#039;&#039;&#039;Action&#039;&#039;&#039;&lt;br /&gt;
&amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
&#039;&#039;&#039;RegLoc&#039;&#039;&#039;&lt;br /&gt;
&amp;quot;HKLM&amp;quot; = All users section of registry, &amp;quot;HKCU&amp;quot; = current user section&lt;br /&gt;
&#039;&#039;&#039;PathString&#039;&#039;&#039;&lt;br /&gt;
A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0 - Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
;================================================================================&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
;================================================================================&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15599</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15599"/>
		<updated>2008-07-02T23:25:40Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Syntax */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read EnvVar from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# All instances of target path/string are removed from the variable regardles of the operation because not only duplicate entries are eliminated but also allows one to change the search order of the target from first to last and vice versa.&lt;br /&gt;
# If the operation is Remove, skip the step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated Envar to RegLoc. The variable is written even if the Action is &amp;quot;R&amp;quot; (remove) or the target is not found, in order to eliminate duplicate semicolons and spaces around semicolons.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
&lt;br /&gt;
 ResultVar  - Updated environmental variable returned by the function&lt;br /&gt;
 EnvVarName - Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYAPP&amp;quot;&lt;br /&gt;
 Action     - &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
 RegLoc     - &amp;quot;HKLM&amp;quot; = All users section of registry, &amp;quot;HKCU&amp;quot; = current user section&lt;br /&gt;
 PathString - A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0 - Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
;================================================================================&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
;================================================================================&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15598</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15598"/>
		<updated>2008-07-02T23:24:04Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read EnvVar from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# All instances of target path/string are removed from the variable regardles of the operation because not only duplicate entries are eliminated but also allows one to change the search order of the target from first to last and vice versa.&lt;br /&gt;
# If the operation is Remove, skip the step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated Envar to RegLoc. The variable is written even if the Action is &amp;quot;R&amp;quot; (remove) or the target is not found, in order to eliminate duplicate semicolons and spaces around semicolons.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Syntax ====&lt;br /&gt;
&lt;br /&gt;
 ResultVar  - Updated environmental variable returned by the function&lt;br /&gt;
 EnvVarName - Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYAPP&amp;quot;&lt;br /&gt;
 Action     - &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
 RegLoc     - &amp;quot;HKLM&amp;quot; = All users section of registry, &amp;quot;HKCU&amp;quot; = current user section&lt;br /&gt;
 PathString - A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0 - Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
;================================================================================&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
;================================================================================&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15597</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15597"/>
		<updated>2008-07-02T23:22:46Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read EnvVar from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# All instances of target path/string are removed from the variable regardles of the operation because not only duplicate entries are eliminated but also allows one to change the search order of the target from first to last and vice versa.&lt;br /&gt;
# If the operation is Remove, skip the step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated Envar to RegLoc. The variable is written even if the Action is &amp;quot;R&amp;quot; (remove) or the target is not found, in order to eliminate duplicate semicolons and spaces around semicolons.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Syntax ====&lt;br /&gt;
&lt;br /&gt;
 ResultVar  - Updated environmental variable returned by the function&lt;br /&gt;
 EnvVarName - Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYAPP&amp;quot;&lt;br /&gt;
 Action     - &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
 RegLoc     - &amp;quot;HKLM&amp;quot; = All users section of registry, &amp;quot;HKCU&amp;quot; = current user section&lt;br /&gt;
 PathString - A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0 - Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
;================================================================================&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
;================================================================================&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
	<entry>
		<id>https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15596</id>
		<title>Environmental Variables: append, prepend, and remove entries</title>
		<link rel="alternate" type="text/html" href="https://nsis.sourceforge.io/mediawiki/index.php?title=Environmental_Variables:_append,_prepend,_and_remove_entries&amp;diff=15596"/>
		<updated>2008-07-02T23:21:52Z</updated>

		<summary type="html">&lt;p&gt;Turnec2: /* Syntax */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageAuthor|turnec2}}&lt;br /&gt;
&lt;br /&gt;
== Function: EnvVarUpdate ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version:&#039;&#039;&#039; 1.0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dependencies:&#039;&#039;&#039; LogicLib header file (&amp;quot;LogicLib.nsh&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Append, prepend or remove a pathname or string from an environmental variable such as&lt;br /&gt;
PATH, LIB, CLASSPATH, PATHEXT, or a variable of your own. Duplicates entries, leading&lt;br /&gt;
and trailing spaces around each entry, and duplicate semicolons are removed from the&lt;br /&gt;
contents of the variable before performing the requested operation.  This step prevents&lt;br /&gt;
the corruption of the variable&#039;s contents (e.g., when removing a target pathname that&lt;br /&gt;
is a subset of another pathname). The variable can be updated in either the &amp;quot;all users&amp;quot;&lt;br /&gt;
section of the registry (HKLM) or the &amp;quot;current user&amp;quot; section (HKCU).&lt;br /&gt;
&lt;br /&gt;
The function can be called from an installer or uninstaller.  The &amp;quot;remove&amp;quot; subfunction&lt;br /&gt;
is normally not required for installers; however, it might be useful for removing&lt;br /&gt;
entries, such as pathnames associated with earlier revisions, in the event that the user &lt;br /&gt;
has failed to run the uninstaller. The string returned in ResultVar might be useful for&lt;br /&gt;
displaying to the user, writing to a log file, or verification.&lt;br /&gt;
&lt;br /&gt;
Three existing string functions are included in the function code. While these routines could have simply been added to list of dependencies, code for each is included to prevent possible failures caused by future modifications of these routines.    &lt;br /&gt;
&lt;br /&gt;
==== Design ====&lt;br /&gt;
&lt;br /&gt;
# Read EnvVar from RegLoc&lt;br /&gt;
# Remove duplicate semicolons and spaces around semicolons&lt;br /&gt;
# All instances of target path/string are removed from the variable regardles of the operation because not only duplicate entries are eliminated but also allows one to change the search order of the target from first to last and vice versa.&lt;br /&gt;
# If the operation is Remove, skip the step, or else prepend or append the target per the requested Action.&lt;br /&gt;
# Write the updated Envar to RegLoc. The variable is written even if the Action is &amp;quot;R&amp;quot; (remove) or the target is not found, in order to eliminate duplicate semicolons and spaces around semicolons.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
 ${EnvVarUpdate} &amp;quot;ResultVar&amp;quot; &amp;quot;EnvVarName&amp;quot; &amp;quot;Action&amp;quot; &amp;quot;RegLoc&amp;quot; &amp;quot;PathString&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Syntax ====&lt;br /&gt;
&lt;br /&gt;
 ResultVar  - Updated environmental variable returned by the function&lt;br /&gt;
 EnvVarName - Environmental variable name such as &amp;quot;PATH&amp;quot;, &amp;quot;LIB&amp;quot;, or &amp;quot;MYAPP&amp;quot;&lt;br /&gt;
 Action     - &amp;quot;A&amp;quot; = Append, &amp;quot;P&amp;quot; = Prepend, &amp;quot;R&amp;quot; = Remove&lt;br /&gt;
 RegLoc     - &amp;quot;HKLM&amp;quot; = All users section of registry, &amp;quot;HKCU&amp;quot; = current user section&lt;br /&gt;
 PathString - A pathname or string to add to or remove from the contents of EnvVarName&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 Push &amp;quot;EnvVarName&amp;quot;&lt;br /&gt;
 Push &amp;quot;Action&amp;quot;&lt;br /&gt;
 Push &amp;quot;RegLoc&amp;quot;&lt;br /&gt;
 Push &amp;quot;PathString&amp;quot;&lt;br /&gt;
 Call EnvVarUpdate&lt;br /&gt;
 Pop  &amp;quot;ResultVar&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;A&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Append a path to PATH in HKLM&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;PATH&amp;quot; &amp;quot;P&amp;quot; &amp;quot;HKCU&amp;quot; &amp;quot;C:\Target&amp;quot;    ; Prepend target path to PATH in HKCU&lt;br /&gt;
 ${EnvVarUpdate} $0 &amp;quot;LIB&amp;quot;  &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;     ; Remove an entry from LIB in HKLM&lt;br /&gt;
 ${un.EnvVarUpdate} $0 &amp;quot;LIB&amp;quot; &amp;quot;R&amp;quot; &amp;quot;HKLM&amp;quot; &amp;quot;C:\MyLib&amp;quot;   ; Uninstaller command&lt;br /&gt;
&lt;br /&gt;
=== Credits ===&lt;br /&gt;
&lt;br /&gt;
Version 1.0 - Cal Turney (turnec2)&lt;br /&gt;
&lt;br /&gt;
* This function was inspired by (and replaces) AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, WriteEnvStr, and un.DeleteEnvStr written by KiCHiK and updated by e-circ.  &lt;br /&gt;
&lt;br /&gt;
* Thanks to Diego Pedroso (deguix) for StrTok; Kevin English (kenglish_hi)for StrContains; and Hendri Adriaens (Smile2Me), Diego Pedroso, and Dan Fuhry (dandaman32) for StrReplace.&lt;br /&gt;
&lt;br /&gt;
=== Function Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;highlight-nsis&amp;gt;&lt;br /&gt;
!ifndef ENVVARUPDATE_FUNCTION&lt;br /&gt;
!define ENVVARUPDATE_FUNCTION&lt;br /&gt;
!verbose push&lt;br /&gt;
!verbose 3&lt;br /&gt;
!include &amp;quot;LogicLib.nsh&amp;quot;&lt;br /&gt;
!include &amp;quot;WinMessages.NSH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!define all_users_env         &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define current_user_only_env &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions ----------------------------------------&lt;br /&gt;
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define EnvVarUpdate &#039;!insertmacro &amp;quot;_EnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString&lt;br /&gt;
  Push &amp;quot;${EnvVarName}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Action}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${RegLoc}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${PathString}&amp;quot;&lt;br /&gt;
    Call un.EnvVarUpdate&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.EnvVarUpdate &#039;!insertmacro &amp;quot;_unEnvVarUpdateConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrTok &#039;!insertmacro &amp;quot;_StrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _unStrTokConstructor ResultVar String Separators ResultPart SkipEmptyParts&lt;br /&gt;
  Push &amp;quot;${String}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${Separators}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${ResultPart}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${SkipEmptyParts}&amp;quot;&lt;br /&gt;
   Call un.StrTok&lt;br /&gt;
  Pop &amp;quot;${ResultVar}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define un.StrTok &#039;!insertmacro &amp;quot;_unStrTokConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
   Call ${UN}StrContains&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrContains &#039;!insertmacro &amp;quot;_StrContainsConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro _strReplaceConstructor OUT NEEDLE NEEDLE2 HAYSTACK&lt;br /&gt;
  Push &amp;quot;${HAYSTACK}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE}&amp;quot;&lt;br /&gt;
  Push &amp;quot;${NEEDLE2}&amp;quot;&lt;br /&gt;
   Call ${UN}StrReplace&lt;br /&gt;
  Pop &amp;quot;${OUT}&amp;quot;&lt;br /&gt;
!macroend&lt;br /&gt;
!define StrReplace &#039;!insertmacro &amp;quot;_strReplaceConstructor&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
; ---------------------------------- Macro Definitions end-------------------------------------&lt;br /&gt;
&lt;br /&gt;
;----------------------------------- EnvVarUpdate start----------------------------------------&lt;br /&gt;
!define hklm_all_users     &#039;HKLM &amp;quot;SYSTEM\CurrentControlSet\Control\Session Manager\Environment&amp;quot;&#039;&lt;br /&gt;
!define hkcu_current_user  &#039;HKCU &amp;quot;Environment&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
!macro EnvVarUpdate UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}EnvVarUpdate&lt;br /&gt;
&lt;br /&gt;
  Push $0&lt;br /&gt;
  Exch 4&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  /* After this point:&lt;br /&gt;
  -------------------------&lt;br /&gt;
     $0 = ResultVar     (returned)&lt;br /&gt;
     $1 = EnvVarName    (input)&lt;br /&gt;
     $2 = Action        (input)&lt;br /&gt;
     $3 = RegLoc        (input)&lt;br /&gt;
     $4 = PathString    (input)&lt;br /&gt;
     $5 = Orig EnvVar   (read from registry)&lt;br /&gt;
     $6 = Len of $0     (temp)&lt;br /&gt;
     $7 = tempstr1      (temp)&lt;br /&gt;
     $8 = Entry counter (temp)&lt;br /&gt;
     $9 = tempstr2      (temp)&lt;br /&gt;
     $R0 = tempChar     (temp)  */&lt;br /&gt;
&lt;br /&gt;
  ; Step 1:  Read contents of EnvVarName from RegLoc&lt;br /&gt;
  ;&lt;br /&gt;
  ; Check for empty EnvVarName&lt;br /&gt;
  ${If} $1 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: EnvVarName is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for valid Action&lt;br /&gt;
  ${If}    $2 != &amp;quot;A&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;P&amp;quot;&lt;br /&gt;
  ${AndIf} $2 != &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: Invalid Action - must be A, P, or R&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ${If} $3 == HKLM&lt;br /&gt;
    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5&lt;br /&gt;
  ${Else}&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &#039;ERROR: Action is [$3] but must be &amp;quot;HKLM&amp;quot; or HKCU&amp;quot;&#039;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Check for empty PathString&lt;br /&gt;
  ${If} $4 == &amp;quot;&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;ERROR: PathString is blank&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Make sure we&#039;ve got some work to do&lt;br /&gt;
  ${If} $5 == &amp;quot;&amp;quot;&lt;br /&gt;
  ${AndIf} $2 == &amp;quot;R&amp;quot;&lt;br /&gt;
    SetErrors&lt;br /&gt;
    DetailPrint &amp;quot;$1 is empty - Nothing to remove&amp;quot;&lt;br /&gt;
    Goto EnvVarUpdate_Restore_Vars&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 2: Scrub EnvVar&lt;br /&gt;
  ;&lt;br /&gt;
  StrCpy $0 $5                             ; Copy the contents to $0&lt;br /&gt;
  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or&lt;br /&gt;
  ; after the last one are not removed here but instead in Step 3)&lt;br /&gt;
  ${If} $0 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot; ;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot; ;&amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;&amp;lt;space&amp;gt;;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;; &amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;; &amp;quot; &amp;quot;;&amp;quot; $0         ; Remove &#039;;&amp;lt;space&amp;gt;&#039;&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${StrContains} $7 &amp;quot;;;&amp;quot; $0&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;&lt;br /&gt;
        ${ExitDo}&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      ${StrReplace} $0 &amp;quot;;;&amp;quot; &amp;quot;;&amp;quot; $0&lt;br /&gt;
    ${Loop}&lt;br /&gt;
&lt;br /&gt;
    ; Remove a leading or trailing semicolon from EnvVar&lt;br /&gt;
    StrCpy  $7  $0 1 0&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
      StrCpy $0  $0 &amp;quot;&amp;quot; 1                   ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    StrLen $6 $0&lt;br /&gt;
    IntOp $6 $6 - 1&lt;br /&gt;
    StrCpy $7  $0 1 $6&lt;br /&gt;
    ${If} $7 == &amp;quot;;&amp;quot;&lt;br /&gt;
     StrCpy $0  $0 $6                      ; Change &#039;;&amp;lt;EnvVar&amp;gt; to &amp;lt;EnvVar&amp;gt;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ; DetailPrint &amp;quot;Scrubbed $1: [$0]&amp;quot;      ; Uncomment to debug&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  /* Step 3. Remove all instances of the target path/string (even if &amp;quot;A&amp;quot; or &amp;quot;P&amp;quot;)&lt;br /&gt;
     $6 = bool flag (1 = found and removed PathString)&lt;br /&gt;
     $7 = a string (e.g. path) delimited by semicolon(s)&lt;br /&gt;
     $8 = entry counter starting at 0&lt;br /&gt;
     $9 = copy of $0&lt;br /&gt;
     $R0 = tempChar      */&lt;br /&gt;
&lt;br /&gt;
  ${If} $5 != &amp;quot;&amp;quot;                           ; If EnvVar is not empty ...&lt;br /&gt;
    StrCpy $9 $0&lt;br /&gt;
    StrCpy $0 &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $8 0&lt;br /&gt;
    StrCpy $6 0&lt;br /&gt;
&lt;br /&gt;
    ${Do}&lt;br /&gt;
      ${${UN}StrTok} $7 $9 &amp;quot;;&amp;quot; $8 &amp;quot;0&amp;quot;      ; $7 = next entry, $8 = entry counter&lt;br /&gt;
&lt;br /&gt;
      ${If} $7 == &amp;quot;&amp;quot;                       ; If we&#039;ve run out of entries,&lt;br /&gt;
        ${ExitDo}                          ;    were done&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 &amp;quot;&amp;quot; 1                ;  Remove leading space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${Do}&lt;br /&gt;
        StrCpy $R0  $7 1 -1&lt;br /&gt;
        ${If} $R0 != &amp;quot; &amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf}&lt;br /&gt;
        StrCpy $7   $7 -1                  ;  Remove trailing space&lt;br /&gt;
      ${Loop}&lt;br /&gt;
      ${If} $7 == $4                       ; If string matches, remove it by not appending it&lt;br /&gt;
        StrCpy $6 1                        ; Set &#039;found&#039; flag&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 == &amp;quot;&amp;quot;                   ;    and the 1st string being added to $0,&lt;br /&gt;
        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon&lt;br /&gt;
      ${ElseIf} $7 != $4                   ; If string does NOT match&lt;br /&gt;
      ${AndIf}  $0 != &amp;quot;&amp;quot;                   ;    and this is NOT the 1st string to be added to $0,&lt;br /&gt;
        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon&lt;br /&gt;
      ${EndIf}                             ;&lt;br /&gt;
&lt;br /&gt;
      IntOp $8 $8 + 1                      ; Bump counter&lt;br /&gt;
    ${Loop}                                ; Check for duplicates until we run out of paths&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 4:  Perform the requested Action&lt;br /&gt;
  ;&lt;br /&gt;
  ${If} $2 != &amp;quot;R&amp;quot;                          ; If Append or Prepend&lt;br /&gt;
    ${If} $6 == 1                          ; And if we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target is already present in $1. It will be removed and&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;                         ; If EnvVar is (now) empty&lt;br /&gt;
      StrCpy $0 $4                         ;   just copy PathString to EnvVar&lt;br /&gt;
      ${If} $6 == 0                        ; If found flag is either 0&lt;br /&gt;
      ${OrIf} $6 == &amp;quot;&amp;quot;                     ; or blank (if EnvVarName is empty)&lt;br /&gt;
        DetailPrint &amp;quot;$1 was empty and has been updated with the target&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${ElseIf} $2 == &amp;quot;A&amp;quot;                    ;  If Append (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $0;$4                      ;     append PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;appended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was appended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${Else}                                ;  If Prepend (and EnvVar is not empty),&lt;br /&gt;
      StrCpy $0 $4;$0                      ;     prepend PathString&lt;br /&gt;
      ${If} $6 == 1&lt;br /&gt;
        DetailPrint &amp;quot;prepended to $1&amp;quot;&lt;br /&gt;
      ${Else}&lt;br /&gt;
        DetailPrint &amp;quot;Target was prepended to $1&amp;quot;&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${Else}                                  ; If Action = Remove&lt;br /&gt;
    ${If} $6 == 1                          ;   and we found the target&lt;br /&gt;
      DetailPrint &amp;quot;Target was found and removed from $1&amp;quot;&lt;br /&gt;
    ${Else}&lt;br /&gt;
      DetailPrint &amp;quot;Target was NOT found in $1 (nothing to remove)&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
    ${If} $0 == &amp;quot;&amp;quot;&lt;br /&gt;
      DetailPrint &amp;quot;$1 is now empty&amp;quot;&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change&lt;br /&gt;
  ;&lt;br /&gt;
  ClearErrors&lt;br /&gt;
  ${If} $3  == HKLM&lt;br /&gt;
    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section&lt;br /&gt;
  ${ElseIf} $3 == HKCU&lt;br /&gt;
    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section&lt;br /&gt;
  IfErrors 0 +3&lt;br /&gt;
    MessageBox MB_OK|MB_ICONEXCLAMATION &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
    DetailPrint &amp;quot;Could not write updated $1 to $3&amp;quot;&lt;br /&gt;
  IfErrors +2 0&lt;br /&gt;
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 &amp;quot;STR:Environment&amp;quot; /TIMEOUT=5000   ; &amp;quot;Export&amp;quot; our change&lt;br /&gt;
  ${EndIf}&lt;br /&gt;
&lt;br /&gt;
  EnvVarUpdate_Restore_Vars:&lt;br /&gt;
  ;&lt;br /&gt;
  ; Restore the user&#039;s variables and return ResultVar&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $3&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Push $0  ; Push my $0 (ResultVar)&lt;br /&gt;
  Exch&lt;br /&gt;
  Pop $0   ; Restore his $0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; EnvVarUpdate UN&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro EnvVarUpdate &amp;quot;un.&amp;quot;&lt;br /&gt;
;----------------------------------- EnvVarUpdate end----------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;-------------------------------------- StrTok start ------------------------------------------&lt;br /&gt;
; Written by Diego Pedroso (deguix)&lt;br /&gt;
;&lt;br /&gt;
!macro StrTok UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrTok&lt;br /&gt;
&lt;br /&gt;
/*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $0 = SkipEmptyParts (input)&lt;br /&gt;
  $1 = ResultPart (input)&lt;br /&gt;
  $2 = Separators (input)&lt;br /&gt;
  $3 = String (input)&lt;br /&gt;
  $4 = SeparatorsLen (temp)&lt;br /&gt;
  $5 = StrLen (temp)&lt;br /&gt;
  $6 = StartCharPos (temp)&lt;br /&gt;
  $7 = TempStr (temp)&lt;br /&gt;
  $8 = CurrentLoop&lt;br /&gt;
  $9 = CurrentSepChar&lt;br /&gt;
  $R0 = CurrentSepCharNum  */&lt;br /&gt;
&lt;br /&gt;
  ;Get input from user&lt;br /&gt;
  Exch $0&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $1&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $2&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Exch $3&lt;br /&gt;
  Exch 3&lt;br /&gt;
  Push $4&lt;br /&gt;
  Push $5&lt;br /&gt;
  Push $6&lt;br /&gt;
  Push $7&lt;br /&gt;
  Push $8&lt;br /&gt;
  Push $9&lt;br /&gt;
  Push $R0&lt;br /&gt;
&lt;br /&gt;
  ;Parameter defaults&lt;br /&gt;
  ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}&lt;br /&gt;
  ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}&lt;br /&gt;
  ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}&lt;br /&gt;
&lt;br /&gt;
  ;Get &amp;quot;String&amp;quot; and &amp;quot;Separators&amp;quot; length&lt;br /&gt;
  StrLen $4 $2&lt;br /&gt;
  StrLen $5 $3&lt;br /&gt;
  ;Start &amp;quot;StartCharPos&amp;quot; and &amp;quot;ResultPart&amp;quot; counters&lt;br /&gt;
  StrCpy $6 0&lt;br /&gt;
  StrCpy $8 -1&lt;br /&gt;
&lt;br /&gt;
  ;Loop until &amp;quot;ResultPart&amp;quot; is met, &amp;quot;Separators&amp;quot; is found or&lt;br /&gt;
  ;&amp;quot;String&amp;quot; reaches its end&lt;br /&gt;
  ResultPartLoop: ;&amp;quot;CurrentLoop&amp;quot; Loop&lt;br /&gt;
&lt;br /&gt;
  ;Increase &amp;quot;CurrentLoop&amp;quot; counter&lt;br /&gt;
  IntOp $8 $8 + 1&lt;br /&gt;
&lt;br /&gt;
  StrSearchLoop:&lt;br /&gt;
  ${Do} ;&amp;quot;String&amp;quot; Loop&lt;br /&gt;
    ;Remove everything before and after the searched part (&amp;quot;TempStr&amp;quot;)&lt;br /&gt;
    StrCpy $7 $3 1 $6&lt;br /&gt;
&lt;br /&gt;
    ;Verify if it&#039;s the &amp;quot;String&amp;quot; end&lt;br /&gt;
    ${If} $6 &amp;gt;= $5&lt;br /&gt;
      ;If &amp;quot;CurrentLoop&amp;quot; is what the user wants, remove the part&lt;br /&gt;
      ;after &amp;quot;TempStr&amp;quot; and itself and get out of here&lt;br /&gt;
      ${If} $8 == $1&lt;br /&gt;
      ${OrIf} $1 == `L`&lt;br /&gt;
        StrCpy $3 $3 $6&lt;br /&gt;
      ${Else} ;If not, empty &amp;quot;String&amp;quot; and get out of here&lt;br /&gt;
        StrCpy $3 ``&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
      StrCpy $R0 `End`&lt;br /&gt;
      ${ExitDo}&lt;br /&gt;
    ${EndIf}&lt;br /&gt;
&lt;br /&gt;
    ;Start &amp;quot;CurrentSepCharNum&amp;quot; counter (for &amp;quot;Separators&amp;quot; Loop)&lt;br /&gt;
    StrCpy $R0 0&lt;br /&gt;
&lt;br /&gt;
    ${Do} ;&amp;quot;Separators&amp;quot; Loop&lt;br /&gt;
      ;Use one &amp;quot;Separators&amp;quot; character at a time&lt;br /&gt;
      ${If} $R0 &amp;lt;&amp;gt; 0&lt;br /&gt;
        StrCpy $9 $2 1 $R0&lt;br /&gt;
      ${Else}&lt;br /&gt;
        StrCpy $9 $2 1&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Go to the next &amp;quot;String&amp;quot; char if it&#039;s &amp;quot;Separators&amp;quot; end&lt;br /&gt;
      ${IfThen} $R0 &amp;gt;= $4 ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
      ;Or, if &amp;quot;TempStr&amp;quot; equals &amp;quot;CurrentSepChar&amp;quot;, then...&lt;br /&gt;
      ${If} $7 == $9&lt;br /&gt;
        StrCpy $7 $3 $6&lt;br /&gt;
&lt;br /&gt;
        ;If &amp;quot;String&amp;quot; is empty because this result part doesn&#039;t&lt;br /&gt;
        ;contain data, verify if &amp;quot;SkipEmptyParts&amp;quot; is activated,&lt;br /&gt;
        ;so we don&#039;t return the output to user yet&lt;br /&gt;
&lt;br /&gt;
        ${If} $7 == ``&lt;br /&gt;
        ${AndIf} $0 = 1 ;${TRUE}&lt;br /&gt;
          IntOp $6 $6 + 1&lt;br /&gt;
          StrCpy $3 $3 `` $6&lt;br /&gt;
          StrCpy $6 0&lt;br /&gt;
          Goto StrSearchLoop&lt;br /&gt;
        ${ElseIf} $8 == $1&lt;br /&gt;
          StrCpy $3 $3 $6&lt;br /&gt;
          StrCpy $R0 &amp;quot;End&amp;quot;&lt;br /&gt;
          ${ExitDo}&lt;br /&gt;
        ${EndIf} ;If not, go to the next result part&lt;br /&gt;
        IntOp $6 $6 + 1&lt;br /&gt;
        StrCpy $3 $3 `` $6&lt;br /&gt;
        StrCpy $6 0&lt;br /&gt;
        Goto ResultPartLoop&lt;br /&gt;
      ${EndIf}&lt;br /&gt;
&lt;br /&gt;
      ;Increase &amp;quot;CurrentSepCharNum&amp;quot; counter&lt;br /&gt;
      IntOp $R0 $R0 + 1&lt;br /&gt;
    ${Loop}&lt;br /&gt;
    ${IfThen} $R0 == &amp;quot;End&amp;quot; ${|} ${ExitDo} ${|}&lt;br /&gt;
&lt;br /&gt;
    ;Increase &amp;quot;StartCharPos&amp;quot; counter&lt;br /&gt;
    IntOp $6 $6 + 1&lt;br /&gt;
  ${Loop}&lt;br /&gt;
&lt;br /&gt;
  /*After this point:&lt;br /&gt;
  ------------------------------------------&lt;br /&gt;
  $3 = ResultVar (output)*/&lt;br /&gt;
&lt;br /&gt;
  ;Return output to user&lt;br /&gt;
  Pop $R0&lt;br /&gt;
  Pop $9&lt;br /&gt;
  Pop $8&lt;br /&gt;
  Pop $7&lt;br /&gt;
  Pop $6&lt;br /&gt;
  Pop $5&lt;br /&gt;
  Pop $4&lt;br /&gt;
  Pop $0&lt;br /&gt;
  Pop $1&lt;br /&gt;
  Pop $2&lt;br /&gt;
  Exch $3&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend ; StrTok UN&lt;br /&gt;
!insertmacro StrTok &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrTok &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrTok end -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;---------------------------------------- StrContains start -------------------------------------&lt;br /&gt;
; StrContains&lt;br /&gt;
; This function does a case sensitive searches for an occurrence of a substring in a string.&lt;br /&gt;
; It returns the substring if it is found; otherwise, it returns null(&amp;quot;&amp;quot;).&lt;br /&gt;
; Usage: ${StrContains} &amp;quot;$result_var&amp;quot; &amp;quot;Needle&amp;quot; &amp;quot;Haystack&amp;quot;&lt;br /&gt;
; Written by kenglish_hi&lt;br /&gt;
; Adapted from StrReplace written by dandaman32&lt;br /&gt;
&lt;br /&gt;
Var STR_HAYSTACK&lt;br /&gt;
Var STR_NEEDLE&lt;br /&gt;
Var STR_CONTAINS_VAR_1&lt;br /&gt;
Var STR_CONTAINS_VAR_2&lt;br /&gt;
Var STR_CONTAINS_VAR_3&lt;br /&gt;
Var STR_CONTAINS_VAR_4&lt;br /&gt;
Var STR_RETURN_VAR&lt;br /&gt;
&lt;br /&gt;
!macro StrContains UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrContains&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_NEEDLE&lt;br /&gt;
  Exch&lt;br /&gt;
  Exch $STR_HAYSTACK&lt;br /&gt;
  ; Uncomment to debug&lt;br /&gt;
  ;MessageBox MB_OK &#039;STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK &#039;&lt;br /&gt;
    StrCpy $STR_RETURN_VAR &amp;quot;&amp;quot;&lt;br /&gt;
    StrCpy $STR_CONTAINS_VAR_1 -1&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE&lt;br /&gt;
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1&lt;br /&gt;
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found&lt;br /&gt;
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_RETURN_VAR $STR_NEEDLE&lt;br /&gt;
      Goto done&lt;br /&gt;
    done:&lt;br /&gt;
   Pop  $STR_HAYSTACK       ;Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the stack intact&lt;br /&gt;
   Exch $STR_RETURN_VAR&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend&lt;br /&gt;
!insertmacro StrContains &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrContains &amp;quot;un.&amp;quot;&lt;br /&gt;
;--------------------------------------- StrContains end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;--------------------------------------- StrReplace start --------------------------------------&lt;br /&gt;
;================================================================================&lt;br /&gt;
; StrReplace&lt;br /&gt;
; Replaces all occurences of a given needle within a haystack with another string&lt;br /&gt;
; Usage: ${StrReplace} &amp;quot;$result_var&amp;quot; &amp;quot;SubString&amp;quot; &amp;quot;RepString&amp;quot; &amp;quot;String&amp;quot;&lt;br /&gt;
; Written by dandaman32&lt;br /&gt;
;================================================================================&lt;br /&gt;
&lt;br /&gt;
Var STR_REPLACE_VAR_0&lt;br /&gt;
Var STR_REPLACE_VAR_1&lt;br /&gt;
Var STR_REPLACE_VAR_2&lt;br /&gt;
Var STR_REPLACE_VAR_3&lt;br /&gt;
Var STR_REPLACE_VAR_4&lt;br /&gt;
Var STR_REPLACE_VAR_5&lt;br /&gt;
Var STR_REPLACE_VAR_6&lt;br /&gt;
Var STR_REPLACE_VAR_7&lt;br /&gt;
Var STR_REPLACE_VAR_8&lt;br /&gt;
&lt;br /&gt;
!macro StrReplace UN&lt;br /&gt;
&lt;br /&gt;
Function ${UN}StrReplace&lt;br /&gt;
&lt;br /&gt;
  Exch $STR_REPLACE_VAR_2&lt;br /&gt;
  Exch 1&lt;br /&gt;
  Exch $STR_REPLACE_VAR_1&lt;br /&gt;
  Exch 2&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
    StrCpy $STR_REPLACE_VAR_3 -1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_1&lt;br /&gt;
    StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
    loop:&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_3 + 1&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_4 $STR_REPLACE_VAR_3&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_1 found&lt;br /&gt;
      StrCmp $STR_REPLACE_VAR_3 $STR_REPLACE_VAR_6 done&lt;br /&gt;
      Goto loop&lt;br /&gt;
    found:&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_5 $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_3&lt;br /&gt;
      IntOp $STR_REPLACE_VAR_8 $STR_REPLACE_VAR_3 + $STR_REPLACE_VAR_4&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_7 $STR_REPLACE_VAR_0 &amp;quot;&amp;quot; $STR_REPLACE_VAR_8&lt;br /&gt;
      StrCpy $STR_REPLACE_VAR_0 $STR_REPLACE_VAR_5$STR_REPLACE_VAR_2$STR_REPLACE_VAR_7&lt;br /&gt;
      StrLen $STR_REPLACE_VAR_6 $STR_REPLACE_VAR_0&lt;br /&gt;
      Goto loop&lt;br /&gt;
    done:&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; Prevent &amp;quot;invalid opcode&amp;quot; errors and keep the&lt;br /&gt;
  Pop $STR_REPLACE_VAR_1 ; stack as it was before the function was called&lt;br /&gt;
  Exch $STR_REPLACE_VAR_0&lt;br /&gt;
&lt;br /&gt;
FunctionEnd&lt;br /&gt;
&lt;br /&gt;
!macroend   ; StrContains UN&lt;br /&gt;
!insertmacro StrReplace &amp;quot;&amp;quot;&lt;br /&gt;
!insertmacro StrReplace &amp;quot;un.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;----------------------------------------- StrReplace end ---------------------------------------&lt;br /&gt;
&lt;br /&gt;
!verbose pop&lt;br /&gt;
!endif&lt;br /&gt;
&amp;lt;/highlight-nsis&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Disk, Path &amp;amp; File Functions]]&lt;/div&gt;</summary>
		<author><name>Turnec2</name></author>
	</entry>
</feed>