Talk:Path Manipulation: Difference between revisions

From NSIS Wiki
Jump to navigationJump to search
No edit summary
 
(9 intermediate revisions by 5 users not shown)
Line 68: Line 68:
::AddToEnvVar was added later by someone else.
::AddToEnvVar was added later by someone else.
::Both functions already read from the registry key itself before writing the new value. They only check in the global value to make sure the value doesn't already exist. I don't see the problem with that.--[[User:Kichik|kichik]] 04:12, 22 December 2006 (PST)
::Both functions already read from the registry key itself before writing the new value. They only check in the global value to make sure the value doesn't already exist. I don't see the problem with that.--[[User:Kichik|kichik]] 04:12, 22 December 2006 (PST)
:::i had a problem, when install goes right after uninstall, ReadEnvStr reads some cached values, and goes to AddToPath_done label. i changed it to ReadRegStr which seems to read actual values. [[User:Mojo|Mojo]] 06:12, 23 December 2006 (PST)
<highlight-nsis>ReadEnvStr $1 PATH
Push "$1;"
Push "$0;"
Call StrStr
Pop $2
StrCmp $2 "" "" AddToPath_done</highlight-nsis>
::::That's a very specific case. It happens because running processes don't update their environment. You should manually update as shown in [[Setting Environment Variables to Active Installer Process]]. Your alternative solution may miss variables defined elsewhere. --[[User:Kichik|kichik]] 01:18, 24 December 2006 (PST)
== Why not use the WordAdd Function? ==
Hi:
  It seemed the WordAdd can do it.
  I modifed the AddToPath and RemoveFromPath:
; AddToPath - Adds the given dir to the search path.
;        Input - head of the stack
Function AddToPath
    Exch $0
    Push $1
    Push $2
    #delete ";" "/" and "\"
        #;
        StrCpy $1 $0 1 -1
        StrCmp $1 ";" 0 +2
            StrCpy $0 $0 -1
        #"/" and "\"
        StrCpy $1 $0 1 -1
        StrCmp $1 "\" +2 +3
        StrCmp $1 "/" 0  +2
            StrCpy $0 $0 -1
    #path
    IfFileExists "$0\*.*" "" AddToPath_done
    DetailPrint "Adding $1 to $0"
    ReadRegStr $1 ${WriteEnvStr_RegKey} "PATH"
    ${WordAdd} $1 ";" "+$0" $2
    WriteRegExpandStr ${WriteEnvStr_RegKey} "PATH" $2
    SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
AddToPath_done:
    Pop $2
    Pop $1
    Pop $0
FunctionEnd
!macro RemoveFromPath UN
; RemoveFromPath - Remove a given dir from the path
;    Input: head of the stack
Function ${UN}RemoveFromPath
    Exch $0
    Push $1
    Push $2
    DetailPrint "Removing $0 from Path"
    ReadRegStr $1 ${WriteEnvStr_RegKey} "PATH"
    ${WordAdd} $1 ";" "-$0" $2
    WriteRegExpandStr ${WriteEnvStr_RegKey} "PATH" $2
    SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
    Pop $2
    Pop $1
    Pop $0
FunctionEnd
!macroend
!insertmacro RemoveFromPath ""
== Problem when handling path1;path2 ==
When I add path1;path2 i.e. multiple paths f.i.;
${EnvVarUpdate} $0 "PYTHONPATH" "P" "HKLM" "path1;path2"
EnvVarUpdate always thinks the path to be added is not there yet so
it keeps adding the paths resulting in a growing path.
Workaround is to add paths one by one but that leeds to additional code
in my case.
== String size limitation ==
Please note that NSIS default build has a string limit of 1024 characters.
If the PATH is bigger, this function will '''replace''' the whole PATH instead of just appending to it.
Temporarily you can use the large strings build of NSIS to avoid this problem.
--[[User:Shmektse|Shmektse]] 13:25, 20 June 2010 (UTC)
I recommend changing
StrCmp $1 "" AddToPath_NTdoIt
to
StrCmp $1 "" AddToPath_NTdone
The path should never be empty, if it is it's going to be the bug, it's much better to not add something to the path than to clear the existing content.

Latest revision as of 01:44, 26 July 2012

Hi,

Here is a problem I fought with a long time.

The directory you want to add to path must exist before you call AddToPath. If it doesn't exists the path environment variable doesn't change, and you get no error message.

/Pontus Bergendahl




The stack manipulation in this article should be checked... I've always found it confusing to deal with, so I usually end up adding a lot of comments that keep track of the stack.

For the AddToEnvVar function, I end up with this:

      -- Beginning of function.  A and B are the ValueToAdd and EnvVarNames respectively --
             Stack: A B
 
Exch $1      Stack: 1 B
Exch         Stack: B 1
Exch $0      Stack: 0 1
Push $2      Stack: 2 0 1
Push $3      Stack: 3 2 0 1
Push $4      Stack: 4 3 2 0 1
 
      -- Put haystack (C) and needle (D) on stack --
Push "$2;"   Stack: C 4 3 2 0 1
Push "$1;"   Stack: D C 4 3 2 0 1
      -- StrStr is called, pops top two, pushes result (E) --
             Stack: E 4 3 2 0 1
Pop $3       Stack: 4 3 2 0 1
 
      -- Put haystack (C) and needle (D) on stack --
Push "$2;"   Stack: C 4 3 2 0 1
Push "$1\;"  Stack: D C 4 3 2 0 1
      -- StrStr is called, pops top two, pushes result (E) --
             Stack: E 4 3 2 0 1
Pop $3       Stack: 4 3 2 0 1
 
      -- IsNT is called, pushes result (F) --
             Stack: F 4 3 2 0 1
 
Pop $2       Stack: 4 3 2 0 1
Pop $4       Stack: 3 2 0 1
Pop $3       Stack: 2 0 1
Pop $2       Stack: 0 1
 
      -- The problem should be clear now --
 
Pop $1       Stack: 1 
Pop $0       Stack: -empty-

Let me know if I'm mistaken.. if not, the wiki should be edited (I'd do it now, but I want to be sure I didn't goof up, first)

You're correct. It seems the last two Pop commands are mixed. $0 should be popped first. The best test is setting $0-$9 with 0-9 (StrCpy $0 $$0, StrCpy $1 $$1, etc.) and checking them after the function returns. That test indeed shows they are mixed. Thanks, fixed. --kichik 14:03, 30 June 2006 (PDT)

  • why AddToPath is not calling AddToEnvVar, if they are equvalent? Mojo 05:05, 19 December 2006 (PST)
  • i had problems with setting variables in installer and cleaning up in uninstaller, until i changed
  ;ReadEnvStr $2 $0
  ReadRegStr $2 ${WriteEnvStr_RegKey} $0
i think, function should read and write from/to one source. same for AddToPath. Mojo 05:05, 19 December 2006 (PST)
AddToEnvVar was added later by someone else.
Both functions already read from the registry key itself before writing the new value. They only check in the global value to make sure the value doesn't already exist. I don't see the problem with that.--kichik 04:12, 22 December 2006 (PST)
i had a problem, when install goes right after uninstall, ReadEnvStr reads some cached values, and goes to AddToPath_done label. i changed it to ReadRegStr which seems to read actual values. Mojo 06:12, 23 December 2006 (PST)
ReadEnvStr $1 PATH
Push "$1;"
Push "$0;"
Call StrStr
Pop $2
StrCmp $2 "" "" AddToPath_done
That's a very specific case. It happens because running processes don't update their environment. You should manually update as shown in Setting Environment Variables to Active Installer Process. Your alternative solution may miss variables defined elsewhere. --kichik 01:18, 24 December 2006 (PST)

Why not use the WordAdd Function?

Hi:

 It seemed the WordAdd can do it.
 I modifed the AddToPath and RemoveFromPath:
AddToPath - Adds the given dir to the search path.
Input - head of the stack

Function AddToPath

   Exch $0
   Push $1
   Push $2
   #delete ";" "/" and "\"
       #;
       StrCpy $1 $0 1 -1
       StrCmp $1 ";" 0 +2
           StrCpy $0 $0 -1
       #"/" and "\"
       StrCpy $1 $0 1 -1
       StrCmp $1 "\" +2 +3
       StrCmp $1 "/" 0  +2
           StrCpy $0 $0 -1
   #path
   IfFileExists "$0\*.*" "" AddToPath_done
   DetailPrint "Adding $1 to $0"
   ReadRegStr $1 ${WriteEnvStr_RegKey} "PATH"
   ${WordAdd} $1 ";" "+$0" $2
   WriteRegExpandStr ${WriteEnvStr_RegKey} "PATH" $2
   SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000

AddToPath_done:

   Pop $2
   Pop $1
   Pop $0

FunctionEnd

!macro RemoveFromPath UN

RemoveFromPath - Remove a given dir from the path
Input
head of the stack

Function ${UN}RemoveFromPath

   Exch $0
   Push $1
   Push $2
   DetailPrint "Removing $0 from Path"
   ReadRegStr $1 ${WriteEnvStr_RegKey} "PATH"
   ${WordAdd} $1 ";" "-$0" $2
   WriteRegExpandStr ${WriteEnvStr_RegKey} "PATH" $2
   SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
   Pop $2
   Pop $1
   Pop $0

FunctionEnd !macroend !insertmacro RemoveFromPath ""

Problem when handling path1;path2

When I add path1;path2 i.e. multiple paths f.i.; ${EnvVarUpdate} $0 "PYTHONPATH" "P" "HKLM" "path1;path2"

EnvVarUpdate always thinks the path to be added is not there yet so it keeps adding the paths resulting in a growing path.

Workaround is to add paths one by one but that leeds to additional code in my case.

String size limitation

Please note that NSIS default build has a string limit of 1024 characters. If the PATH is bigger, this function will replace the whole PATH instead of just appending to it. Temporarily you can use the large strings build of NSIS to avoid this problem.

--Shmektse 13:25, 20 June 2010 (UTC)

I recommend changing

StrCmp $1 "" AddToPath_NTdoIt

to

StrCmp $1 "" AddToPath_NTdone

The path should never be empty, if it is it's going to be the bug, it's much better to not add something to the path than to clear the existing content.