原文:
手头有个项目需要修改PATH变量
需要!include "EnvVarUpdate.nsh"
以下是NSIS脚本代码
; Script generated by the HM NIS Edit Script Wizard. !include "StrFunc.nsh"; HM NIS Edit Wizard helper defines!define PRODUCT_NAME "Setup_Wintech"!define PRODUCT_VERSION "2.0"!define PRODUCT_PUBLISHER "Wintech Digital Systems Technology Corp."!define PRODUCT_WEB_SITE "http://www.wintechdigital.com"!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\makensis.exe"!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"!define PRODUCT_UNINST_ROOT_KEY "HKLM"!define INSTALL_DIR_FILENAME "Wintech"; MUI 1.67 compatible ------!include "MUI.nsh"!include "LogicLib.nsh"!include "x64.nsh"!include "EnvVarUpdate.nsh"; MUI Settings!define MUI_ABORTWARNING!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\Wintech.ico"!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\Wintech.ico"; Welcome page!insertmacro MUI_PAGE_WELCOME; License page;!insertmacro MUI_PAGE_LICENSE "${NSISDIR}\License.txt"; Directory page!insertmacro MUI_PAGE_DIRECTORY; Instfiles page!insertmacro MUI_PAGE_INSTFILES; Finish page!define MUI_FINISHPAGE_RUN "$INSTDIR\bin\wlp_exe_gui.exe"!insertmacro MUI_PAGE_FINISH; Uninstaller pages!insertmacro MUI_UNPAGE_INSTFILES; Language files!insertmacro MUI_LANGUAGE "English"!echo "Testing"; MUI end ------RequestExecutionLevel adminName "${PRODUCT_NAME} ${PRODUCT_VERSION}"OutFile "dlf_setup.exe"InstallDir "$PROGRAMFILES\${INSTALL_DIR_FILENAME}"InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""ShowInstDetails showShowUnInstDetails showSection "MainSection" SEC01 ${EnvVarUpdate} $0 "PATH" "A" "HKLM" "$INSTDIR\bin" ; appends to the system path SetOutPath "$INSTDIR" SetOverwrite ifnewer File "${NSISDIR}\makensis.exe" CreateDirectory "$INSTDIR" CreateShortCut "$SMPROGRAMS\${INSTALL_DIR_FILENAME}\${INSTALL_DIR_FILENAME}.lnk" "$INSTDIR\makensis.exe" CreateShortCut "$DESKTOP\${INSTALL_DIR_FILENAME}.lnk" "$INSTDIR\makensis.exe" File "${NSISDIR}\License.txt" File /r "setup\*" ;Detect windows is 32bit or 64bit ${If} ${RunningX64}; 64bit bits go here Exec '"$INSTDIR\bin\driver\win7\Psexec.exe" -i -d -s "$INSTDIR\bin\driver\win7\install_wdf_driver.exe"' ;-i -d -s "$INSTDIR\bin\Driver\win7install_wdf_driver.exe"' ;Exec "$INSTDIR\bin\notepad2.exe" ExecWait "$INSTDIR\bin\vs2010sp1vcredist.exe" ${Else}; 32bit bits go here Exec '"$INSTDIR\bin\driver\win7\Psexec.exe" -i -d -s "$INSTDIR\bin\driver\win7\install_wdf_driver.exe"' ExecWait '"$INSTDIR\bin\vs2010sp1vcredist.exe"'${EndIf} SectionEndSection -AdditionalIcons WriteIniStr "$INSTDIR\${PRODUCT_NAME}.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}" CreateShortCut "$SMPROGRAMS\MyScript\Website.lnk" "$INSTDIR\${PRODUCT_NAME}.url" CreateShortCut "$SMPROGRAMS\MyScript\Uninstall.lnk" "$INSTDIR\uninst.exe"SectionEndSection -Post WriteUninstaller "$INSTDIR\uninst.exe" WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\makensis.exe" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\makensis.exe" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"SectionEndFunction un.onUninstSuccess HideWindow MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) 已成功地从你的计算机移除。"FunctionEndFunction un.onInit MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "你确实要完全移除 $(^Name) ,其及所有的组件?" IDYES +2 AbortFunctionEndSection Uninstall Delete "$INSTDIR\${PRODUCT_NAME}.url" Delete "$INSTDIR\uninst.exe" Delete "$INSTDIR\setup" Delete "$INSTDIR\License.txt" Delete "$INSTDIR\makensis.exe" Delete "$SMPROGRAMS\${INSTALL_DIR_FILENAME}\Uninstall.lnk" Delete "$SMPROGRAMS\${INSTALL_DIR_FILENAME}\Website.lnk" Delete "$DESKTOP\${INSTALL_DIR_FILENAME}.lnk" Delete "$SMPROGRAMS\${INSTALL_DIR_FILENAME}\${INSTALL_DIR_FILENAME}.lnk" RMDir "$SMPROGRAMS\${INSTALL_DIR_FILENAME}" RMDir "$INSTDIR" DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}" SetAutoClose trueSectionEnd
以下时EnvVarUpdate.nsh的代码,需要拷贝到NSIS的include路径下面才能用:
1 /** 2 * EnvVarUpdate.nsh 3 * : Environmental Variables: append, prepend, and remove entries 4 * 5 * WARNING: If you use StrFunc.nsh header then include it before this file 6 * with all required definitions. This is to avoid conflicts 7 * 8 * Usage: 9 * ${EnvVarUpdate} "ResultVar" "EnvVarName" "Action" "RegLoc" "PathString" 10 * 11 * Credits: 12 * Version 1.0 13 * * Cal Turney (turnec2) 14 * * Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this 15 * function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar, 16 * WriteEnvStr, and un.DeleteEnvStr 17 * * Diego Pedroso (deguix) for StrTok 18 * * Kevin English (kenglish_hi) for StrContains 19 * * Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry 20 * (dandaman32) for StrReplace 21 * 22 * Version 1.1 (compatibility with StrFunc.nsh) 23 * * techtonik 24 * 25 * http://nsis.sourceforge.net/Environmental_Variables:_append%2C_prepend%2C_and_remove_entries 26 * 27 */ 28 29 30 !ifndef ENVVARUPDATE_FUNCTION 31 !define ENVVARUPDATE_FUNCTION 32 !verbose push 33 !verbose 3 34 !include "LogicLib.nsh" 35 !include "WinMessages.NSH" 36 !include "StrFunc.nsh" 37 38 ; ---- Fix for conflict if StrFunc.nsh is already includes in main file ----------------------- 39 !macro _IncludeStrFunction StrFuncName 40 !ifndef ${StrFuncName}_INCLUDED 41 ${${StrFuncName}} 42 !endif 43 !ifndef Un${StrFuncName}_INCLUDED 44 ${Un${StrFuncName}} 45 !endif 46 !define un.${StrFuncName} "${Un${StrFuncName}}" 47 !macroend 48 49 !insertmacro _IncludeStrFunction StrTok 50 !insertmacro _IncludeStrFunction StrStr 51 !insertmacro _IncludeStrFunction StrRep 52 53 ; ---------------------------------- Macro Definitions ---------------------------------------- 54 !macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString 55 Push "${EnvVarName}" 56 Push "${Action}" 57 Push "${RegLoc}" 58 Push "${PathString}" 59 Call EnvVarUpdate 60 Pop "${ResultVar}" 61 !macroend 62 !define EnvVarUpdate '!insertmacro "_EnvVarUpdateConstructor"' 63 64 !macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString 65 Push "${EnvVarName}" 66 Push "${Action}" 67 Push "${RegLoc}" 68 Push "${PathString}" 69 Call un.EnvVarUpdate 70 Pop "${ResultVar}" 71 !macroend 72 !define un.EnvVarUpdate '!insertmacro "_unEnvVarUpdateConstructor"' 73 ; ---------------------------------- Macro Definitions end------------------------------------- 74 75 ;----------------------------------- EnvVarUpdate start---------------------------------------- 76 !define hklm_all_users 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' 77 !define hkcu_current_user 'HKCU "Environment"' 78 79 !macro EnvVarUpdate UN 80 81 Function ${UN}EnvVarUpdate 82 83 Push $0 84 Exch 4 85 Exch $1 86 Exch 3 87 Exch $2 88 Exch 2 89 Exch $3 90 Exch 91 Exch $4 92 Push $5 93 Push $6 94 Push $7 95 Push $8 96 Push $9 97 Push $R0 98 99 /* After this point:100 -------------------------101 $0 = ResultVar (returned)102 $1 = EnvVarName (input)103 $2 = Action (input)104 $3 = RegLoc (input)105 $4 = PathString (input)106 $5 = Orig EnvVar (read from registry)107 $6 = Len of $0 (temp)108 $7 = tempstr1 (temp)109 $8 = Entry counter (temp)110 $9 = tempstr2 (temp)111 $R0 = tempChar (temp) */112 113 ; Step 1: Read contents of EnvVarName from RegLoc114 ;115 ; Check for empty EnvVarName116 ${If} $1 == ""117 SetErrors118 DetailPrint "ERROR: EnvVarName is blank"119 Goto EnvVarUpdate_Restore_Vars120 ${EndIf}121 122 ; Check for valid Action123 ${If} $2 != "A"124 ${AndIf} $2 != "P"125 ${AndIf} $2 != "R"126 SetErrors127 DetailPrint "ERROR: Invalid Action - must be A, P, or R"128 Goto EnvVarUpdate_Restore_Vars129 ${EndIf}130 131 ${If} $3 == HKLM132 ReadRegStr $5 ${hklm_all_users} $1 ; Get EnvVarName from all users into $5133 ${ElseIf} $3 == HKCU134 ReadRegStr $5 ${hkcu_current_user} $1 ; Read EnvVarName from current user into $5135 ${Else}136 SetErrors137 DetailPrint 'ERROR: Action is [$3] but must be "HKLM" or HKCU"'138 Goto EnvVarUpdate_Restore_Vars139 ${EndIf}140 141 ; Check for empty PathString142 ${If} $4 == ""143 SetErrors144 DetailPrint "ERROR: PathString is blank"145 Goto EnvVarUpdate_Restore_Vars146 ${EndIf}147 148 ; Make sure we've got some work to do149 ${If} $5 == ""150 ${AndIf} $2 == "R"151 SetErrors152 DetailPrint "$1 is empty - Nothing to remove"153 Goto EnvVarUpdate_Restore_Vars154 ${EndIf}155 156 ; Step 2: Scrub EnvVar157 ;158 StrCpy $0 $5 ; Copy the contents to $0159 ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or160 ; after the last one are not removed here but instead in Step 3)161 ${If} $0 != "" ; If EnvVar is not empty ...162 ${Do}163 ${${UN}StrStr} $7 $0 " ;"164 ${If} $7 == ""165 ${ExitDo}166 ${EndIf}167 ${${UN}StrRep} $0 $0 " ;" ";" ; Remove ';'168 ${Loop}169 ${Do}170 ${${UN}StrStr} $7 $0 "; "171 ${If} $7 == ""172 ${ExitDo}173 ${EndIf}174 ${${UN}StrRep} $0 $0 "; " ";" ; Remove '; '175 ${Loop}176 ${Do}177 ${${UN}StrStr} $7 $0 ";;" 178 ${If} $7 == ""179 ${ExitDo}180 ${EndIf}181 ${${UN}StrRep} $0 $0 ";;" ";"182 ${Loop}183 184 ; Remove a leading or trailing semicolon from EnvVar185 StrCpy $7 $0 1 0186 ${If} $7 == ";"187 StrCpy $0 $0 "" 1 ; Change '; ' to ' '188 ${EndIf}189 StrLen $6 $0190 IntOp $6 $6 - 1191 StrCpy $7 $0 1 $6192 ${If} $7 == ";"193 StrCpy $0 $0 $6 ; Change '; ' to ' '194 ${EndIf}195 ; DetailPrint "Scrubbed $1: [$0]" ; Uncomment to debug196 ${EndIf}197 198 /* Step 3. Remove all instances of the target path/string (even if "A" or "P")199 $6 = bool flag (1 = found and removed PathString)200 $7 = a string (e.g. path) delimited by semicolon(s)201 $8 = entry counter starting at 0202 $9 = copy of $0203 $R0 = tempChar */204 205 ${If} $5 != "" ; If EnvVar is not empty ...206 StrCpy $9 $0207 StrCpy $0 ""208 StrCpy $8 0209 StrCpy $6 0210 211 ${Do}212 ${${UN}StrTok} $7 $9 ";" $8 "0" ; $7 = next entry, $8 = entry counter213 214 ${If} $7 == "" ; If we've run out of entries,215 ${ExitDo} ; were done216 ${EndIf} ;217 218 ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)219 ${Do}220 StrCpy $R0 $7 1221 ${If} $R0 != " "222 ${ExitDo}223 ${EndIf}224 StrCpy $7 $7 "" 1 ; Remove leading space225 ${Loop}226 ${Do}227 StrCpy $R0 $7 1 -1228 ${If} $R0 != " "229 ${ExitDo}230 ${EndIf}231 StrCpy $7 $7 -1 ; Remove trailing space232 ${Loop}233 ${If} $7 == $4 ; If string matches, remove it by not appending it234 StrCpy $6 1 ; Set 'found' flag235 ${ElseIf} $7 != $4 ; If string does NOT match236 ${AndIf} $0 == "" ; and the 1st string being added to $0,237 StrCpy $0 $7 ; copy it to $0 without a prepended semicolon238 ${ElseIf} $7 != $4 ; If string does NOT match239 ${AndIf} $0 != "" ; and this is NOT the 1st string to be added to $0,240 StrCpy $0 $0;$7 ; append path to $0 with a prepended semicolon241 ${EndIf} ;242 243 IntOp $8 $8 + 1 ; Bump counter244 ${Loop} ; Check for duplicates until we run out of paths245 ${EndIf}246 247 ; Step 4: Perform the requested Action248 ;249 ${If} $2 != "R" ; If Append or Prepend250 ${If} $6 == 1 ; And if we found the target251 DetailPrint "Target is already present in $1. It will be removed and"252 ${EndIf}253 ${If} $0 == "" ; If EnvVar is (now) empty254 StrCpy $0 $4 ; just copy PathString to EnvVar255 ${If} $6 == 0 ; If found flag is either 0256 ${OrIf} $6 == "" ; or blank (if EnvVarName is empty)257 DetailPrint "$1 was empty and has been updated with the target"258 ${EndIf}259 ${ElseIf} $2 == "A" ; If Append (and EnvVar is not empty),260 StrCpy $0 $0;$4 ; append PathString261 ${If} $6 == 1262 DetailPrint "appended to $1"263 ${Else}264 DetailPrint "Target was appended to $1"265 ${EndIf}266 ${Else} ; If Prepend (and EnvVar is not empty),267 StrCpy $0 $4;$0 ; prepend PathString268 ${If} $6 == 1269 DetailPrint "prepended to $1"270 ${Else}271 DetailPrint "Target was prepended to $1"272 ${EndIf}273 ${EndIf}274 ${Else} ; If Action = Remove275 ${If} $6 == 1 ; and we found the target276 DetailPrint "Target was found and removed from $1"277 ${Else}278 DetailPrint "Target was NOT found in $1 (nothing to remove)"279 ${EndIf}280 ${If} $0 == ""281 DetailPrint "$1 is now empty"282 ${EndIf}283 ${EndIf}284 285 ; Step 5: Update the registry at RegLoc with the updated EnvVar and announce the change286 ;287 ClearErrors288 ${If} $3 == HKLM289 WriteRegExpandStr ${hklm_all_users} $1 $0 ; Write it in all users section290 ${ElseIf} $3 == HKCU291 WriteRegExpandStr ${hkcu_current_user} $1 $0 ; Write it to current user section292 ${EndIf}293 294 IfErrors 0 +4295 MessageBox MB_OK|MB_ICONEXCLAMATION "Could not write updated $1 to $3"296 DetailPrint "Could not write updated $1 to $3"297 Goto EnvVarUpdate_Restore_Vars298 299 ; "Export" our change300 SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000301 302 EnvVarUpdate_Restore_Vars:303 ;304 ; Restore the user's variables and return ResultVar305 Pop $R0306 Pop $9307 Pop $8308 Pop $7309 Pop $6310 Pop $5311 Pop $4312 Pop $3313 Pop $2314 Pop $1315 Push $0 ; Push my $0 (ResultVar)316 Exch317 Pop $0 ; Restore his $0318 319 FunctionEnd320 321 !macroend ; EnvVarUpdate UN322 !insertmacro EnvVarUpdate ""323 !insertmacro EnvVarUpdate "un."324 ;----------------------------------- EnvVarUpdate end----------------------------------------325 326 !verbose pop327 !endif
References:
http://stackoverflow.com/questions/11272066/nsis-how-to-set-an-environment-variable-in-system-variable
http://nsis.sourceforge.net/Path_Manipulation