Path Manipulation: Difference between revisions
m (Adding new author and category links.) |
|||
Line 28: | Line 28: | ||
The functions in the flesh: | The functions in the flesh: | ||
<highlight-nsis>!verbose 3 | <highlight-nsis>!ifndef _AddToPath_nsh | ||
!define _AddToPath_nsh | |||
!verbose 3 | |||
!include "WinMessages.NSH" | !include "WinMessages.NSH" | ||
!verbose 4 | !verbose 4 | ||
!ifndef WriteEnvStr_RegKey | |||
!ifdef ALL_USERS | |||
!define WriteEnvStr_RegKey \ | |||
'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' | |||
!else | |||
!define WriteEnvStr_RegKey 'HKCU "Environment"' | |||
!endif | |||
!endif | |||
; AddToPath - Adds the given dir to the search path. | ; AddToPath - Adds the given dir to the search path. | ||
Line 84: | Line 96: | ||
AddToPath_NT: | AddToPath_NT: | ||
ReadRegStr $1 | ReadRegStr $1 ${WriteEnvStr_RegKey} "PATH" | ||
StrCpy $2 $1 1 -1 # copy last char | StrCpy $2 $1 1 -1 # copy last char | ||
StrCmp $2 ";" 0 +2 # if last char == ; | StrCmp $2 ";" 0 +2 # if last char == ; | ||
Line 91: | Line 103: | ||
StrCpy $0 "$1;$0" | StrCpy $0 "$1;$0" | ||
AddToPath_NTdoIt: | AddToPath_NTdoIt: | ||
WriteRegExpandStr | WriteRegExpandStr ${WriteEnvStr_RegKey} "PATH" $0 | ||
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 | SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 | ||
Line 152: | Line 164: | ||
unRemoveFromPath_NT: | unRemoveFromPath_NT: | ||
ReadRegStr $1 | ReadRegStr $1 ${WriteEnvStr_RegKey} "PATH" | ||
StrCpy $5 $1 1 -1 # copy last char | StrCpy $5 $1 1 -1 # copy last char | ||
StrCmp $5 ";" +2 # if last char != ; | StrCmp $5 ";" +2 # if last char != ; | ||
Line 174: | Line 186: | ||
StrCpy $3 $3 -1 # remove last char | StrCpy $3 $3 -1 # remove last char | ||
WriteRegExpandStr | WriteRegExpandStr ${WriteEnvStr_RegKey} "PATH" $3 | ||
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 | SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 | ||
Line 186: | Line 198: | ||
Pop $0 | Pop $0 | ||
FunctionEnd | FunctionEnd | ||
!ifndef IsNT_KiCHiK | |||
!define IsNT_KiCHiK | |||
########################################### | ########################################### | ||
Line 218: | Line 233: | ||
!insertmacro IsNT "" | !insertmacro IsNT "" | ||
!insertmacro IsNT "un." | !insertmacro IsNT "un." | ||
!endif ; IsNT_KiCHiK | |||
; StrStr | ; StrStr | ||
Line 263: | Line 280: | ||
!macroend | !macroend | ||
!insertmacro StrStr "" | !insertmacro StrStr "" | ||
!insertmacro StrStr "un."</highlight-nsis> | !insertmacro StrStr "un." | ||
!endif ; _AddToPath_nsh | |||
</highlight-nsis> | |||
[[Category:Disk, Path & File Functions]] | [[Category:Disk, Path & File Functions]] |
Revision as of 00:17, 30 July 2005
Author: KiCHiK (talk, contrib) |
Description
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.
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.
Changes on 9x machines will take place after a reboot. These functions set the reboot flag if the path variable was changed on 9x.
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 this forum thread.
Usage Example
Section "Add to path" Push $INSTDIR Call AddToPath SectionEnd # ... Section "uninstall" # ... Push $INSTDIR Call un.RemoveFromPath # ... SectionEnd
The Functions
The functions in the flesh:
!ifndef _AddToPath_nsh !define _AddToPath_nsh !verbose 3 !include "WinMessages.NSH" !verbose 4 !ifndef WriteEnvStr_RegKey !ifdef ALL_USERS !define WriteEnvStr_RegKey \ 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' !else !define WriteEnvStr_RegKey 'HKCU "Environment"' !endif !endif ; AddToPath - Adds the given dir to the search path. ; Input - head of the stack ; Note - Win9x systems requires reboot Function AddToPath Exch $0 Push $1 Push $2 Push $3 # don't add if the path doesn't exist IfFileExists "$0\*.*" "" AddToPath_done ReadEnvStr $1 PATH Push "$1;" Push "$0;" Call StrStr Pop $2 StrCmp $2 "" "" AddToPath_done Push "$1;" Push "$0\;" Call StrStr Pop $2 StrCmp $2 "" "" AddToPath_done GetFullPathName /SHORT $3 $0 Push "$1;" Push "$3;" Call StrStr Pop $2 StrCmp $2 "" "" AddToPath_done Push "$1;" Push "$3\;" Call StrStr Pop $2 StrCmp $2 "" "" AddToPath_done Call IsNT Pop $1 StrCmp $1 1 AddToPath_NT ; Not on NT StrCpy $1 $WINDIR 2 FileOpen $1 "$1\autoexec.bat" a FileSeek $1 -1 END FileReadByte $1 $2 IntCmp $2 26 0 +2 +2 # DOS EOF FileSeek $1 -1 END # write over EOF FileWrite $1 "$\r$\nSET PATH=%PATH%;$3$\r$\n" FileClose $1 SetRebootFlag true Goto AddToPath_done AddToPath_NT: ReadRegStr $1 ${WriteEnvStr_RegKey} "PATH" StrCpy $2 $1 1 -1 # copy last char StrCmp $2 ";" 0 +2 # if last char == ; StrCpy $1 $1 -1 # remove last char StrCmp $1 "" AddToPath_NTdoIt StrCpy $0 "$1;$0" AddToPath_NTdoIt: WriteRegExpandStr ${WriteEnvStr_RegKey} "PATH" $0 SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 AddToPath_done: Pop $3 Pop $2 Pop $1 Pop $0 FunctionEnd ; RemoveFromPath - Remove a given dir from the path ; Input: head of the stack Function un.RemoveFromPath Exch $0 Push $1 Push $2 Push $3 Push $4 Push $5 Push $6 IntFmt $6 "%c" 26 # DOS EOF Call un.IsNT Pop $1 StrCmp $1 1 unRemoveFromPath_NT ; Not on NT StrCpy $1 $WINDIR 2 FileOpen $1 "$1\autoexec.bat" r GetTempFileName $4 FileOpen $2 $4 w GetFullPathName /SHORT $0 $0 StrCpy $0 "SET PATH=%PATH%;$0" Goto unRemoveFromPath_dosLoop unRemoveFromPath_dosLoop: FileRead $1 $3 StrCpy $5 $3 1 -1 # read last char StrCmp $5 $6 0 +2 # if DOS EOF StrCpy $3 $3 -1 # remove DOS EOF so we can compare StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoopRemoveLine StrCmp $3 "$0$\n" unRemoveFromPath_dosLoopRemoveLine StrCmp $3 "$0" unRemoveFromPath_dosLoopRemoveLine StrCmp $3 "" unRemoveFromPath_dosLoopEnd FileWrite $2 $3 Goto unRemoveFromPath_dosLoop unRemoveFromPath_dosLoopRemoveLine: SetRebootFlag true Goto unRemoveFromPath_dosLoop unRemoveFromPath_dosLoopEnd: FileClose $2 FileClose $1 StrCpy $1 $WINDIR 2 Delete "$1\autoexec.bat" CopyFiles /SILENT $4 "$1\autoexec.bat" Delete $4 Goto unRemoveFromPath_done unRemoveFromPath_NT: ReadRegStr $1 ${WriteEnvStr_RegKey} "PATH" StrCpy $5 $1 1 -1 # copy last char StrCmp $5 ";" +2 # if last char != ; StrCpy $1 "$1;" # append ; Push $1 Push "$0;" Call un.StrStr ; Find `$0;` in $1 Pop $2 ; pos of our dir StrCmp $2 "" unRemoveFromPath_done ; else, it is in path # $0 - path to add # $1 - path var StrLen $3 "$0;" StrLen $4 $2 StrCpy $5 $1 -$4 # $5 is now the part before the path to remove StrCpy $6 $2 "" $3 # $6 is now the part after the path to remove StrCpy $3 $5$6 StrCpy $5 $3 1 -1 # copy last char StrCmp $5 ";" 0 +2 # if last char == ; StrCpy $3 $3 -1 # remove last char WriteRegExpandStr ${WriteEnvStr_RegKey} "PATH" $3 SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 unRemoveFromPath_done: Pop $6 Pop $5 Pop $4 Pop $3 Pop $2 Pop $1 Pop $0 FunctionEnd !ifndef IsNT_KiCHiK !define IsNT_KiCHiK ########################################### # Utility Functions # ########################################### ; IsNT ; no input ; output, top of the stack = 1 if NT or 0 if not ; ; Usage: ; Call IsNT ; Pop $R0 ; ($R0 at this point is 1 or 0) !macro IsNT un Function ${un}IsNT Push $0 ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion StrCmp $0 "" 0 IsNT_yes ; we are not NT. Pop $0 Push 0 Return IsNT_yes: ; NT!!! Pop $0 Push 1 FunctionEnd !macroend !insertmacro IsNT "" !insertmacro IsNT "un." !endif ; IsNT_KiCHiK ; StrStr ; input, top of stack = string to search for ; top of stack-1 = string to search in ; output, top of stack (replaces with the portion of the string remaining) ; modifies no other variables. ; ; Usage: ; Push "this is a long ass string" ; Push "ass" ; Call StrStr ; Pop $R0 ; ($R0 at this point is "ass string") !macro StrStr un Function ${un}StrStr Exch $R1 ; st=haystack,old$R1, $R1=needle Exch ; st=old$R1,haystack Exch $R2 ; st=old$R1,old$R2, $R2=haystack Push $R3 Push $R4 Push $R5 StrLen $R3 $R1 StrCpy $R4 0 ; $R1=needle ; $R2=haystack ; $R3=len(needle) ; $R4=cnt ; $R5=tmp loop: StrCpy $R5 $R2 $R3 $R4 StrCmp $R5 $R1 done StrCmp $R5 "" done IntOp $R4 $R4 + 1 Goto loop done: StrCpy $R1 $R2 "" $R4 Pop $R5 Pop $R4 Pop $R3 Pop $R2 Exch $R1 FunctionEnd !macroend !insertmacro StrStr "" !insertmacro StrStr "un." !endif ; _AddToPath_nsh