Repair path names with ..
you have a path with relative path parts, such as
\\ ; does nothing \.\ ; stay in same folder \..\ ; go up a folder
And you need the absolute path, then you can use the "GetFullPathName" command in NSIS to get the absolute path. For example:
Section Test GetFullPathName $0 "c:\program files\myApp\somedir\subdir\..\somefile.ext" ; $0 will now contain "c:\program files\myApp\somedir\somefile.ext" SectionEnd
Note 1: if you specify a filename, that file has to exist or the result is null.It is therefore recommended that if you need the absolute path without necessarily having the file in existence, that you strip the filename from the path.
Note 2: this command is limited to a 256-character string, even if the resulting absolute path is shorter than 256 characters.
Note 3: if the string being fed does not start with an absolute reference, it will be treated as if relative to the current working folder, and the absolute path result will reflect this. E.g.
Section Test GetFullPathName $0 "FooBar\" ; $0 may now contain "c:\test\Foobar\" if the installer was executed in "c:\test\" SectionEnd
If any of the above notes may preclude you from using this Command, try the below Function instead.
Section "Rel2Abs" Push "c:\Alpha\\\Bravo\\Charlie..charles\\.\delta\\echo\\..\..\foxtrot\\..\Golf\\.\Hotel\\.\india\\..\\\\juliet\\..\kilo\\\..\Li.....ma\\.\..Mike\\\November\\.\oscar\\..\Papa\\\Quebec..\\\\\\\\Romeo\\sierra\\..\tang.o\\uniform\\victor\\..\whiskey\\..\\x-ray\\yankee\\..\..\.\..\..\Zu.lu\\file.ext" Call Abs2Rel Pop $0 MessageBox MB_OK "Expected:$\tc:\Alpha\Bravo\Charlie..charles\Golf\Hotel\Li.....ma\..Mike\November\Papa\Quebec..\Romeo\Zu.lu\file.ext$\r$\nResult:$\t$\t$0" SectionEnd Function Abs2Rel ; Stack -> ; <relative path> ; This and the stuff in the column below is just to keep track of the stack before and after the function so that it's clean at the end. Exch $R0 ; R0 ; $R0 now holds the relative path Push $0 ; 0 R0 ; $0 will hold the absolute path as it is being built Push $1 ; 1 0 R0 ; $1 will hold the length of the relative path Push $2 ; 2 1 0 R0 ; $2 will hold a counter for running along the path Push $3 ; 3 2 1 0 R0 ; $3 will hold a substring of the paths to test against StrCpy $0 $R0 1 0 ; Start by getting the first character of the relative path into the absolute path var StrLen $1 $R0 ; Get the length of the relative path StrCpy $2 0 ; And start the counter off at zero ; example path at this point ; c:\Alpha\\\Bravo\\Charlie..charles\\.\delta\\echo\\..\..\foxtrot\\..\Golf\\.\Hotel\\.\india\\..\\\\juliet\\..\kilo\\\..\Li.....ma\\.\..Mike\\\November\\.\oscar\\..\Papa\\\Quebec..\\\\\\\\Romeo\\sierra\\..\tang.o\\uniform\\victor\\..\whiskey\\..\\x-ray\\yankee\\..\..\.\..\..\Zu.lu\\file.ext ; double ; This section will get rid of all double backslashes. _loop_double: ; top of the loop IntOp $2 $2 + 1 ; increase the counter IntCmp $2 $1 0 0 _sameDir ; if the counter exceeds the relative path's length, move on StrCpy $3 $R0 2 $2 ; get two characters from the relative pah, starting at the position of the counter StrCmp $3 "\\" _loop_double ; if it's a double backslash, just go back to the top of the loop StrCpy $3 $R0 1 $2 ; otherwise, get a single character from the relative path, starting at the position of the counter StrCpy $0 "$0$3" ; and add that character to the absolute path being built goto _loop_double ; then go back to the top of the loop ; example path at this point ; c:\Alpha\Bravo\Charlie..charles\.\delta\echo\..\..\foxtrot\..\Golf\.\Hotel\.\india\..\juliet\..\kilo\..\Li.....ma\.\..Mike\November\.\oscar\..\Papa\Quebec..\Romeo\sierra\..\tang.o\uniform\victor\..\whiskey\..\x-ray\yankee\..\..\.\..\..\Zu.lu\file.ext _sameDir: ; This section will get rid of all \.\ occurrences. StrCpy $R0 $0 ; First, copy the working copy absolute path into the relative path var. We won't need the original anymore. StrCpy $0 $R0 1 0 ; Again, get the first character StrLen $1 $R0 ; Get the length StrCpy $2 0 ; Start the counter at zero _loop_sameDir: ; top of the loop IntOp $2 $2 + 1 ; increase the counter IntCmp $2 $1 0 0 _dirup ; if the counter exceeds the relative path's length, move on StrCpy $3 $R0 3 $2 ; get three characters from the relative path, starting at the position of the counter StrCmp $3 "\.\" 0 +3 ; if that's \.\ , then we'll have to... IntOp $2 $2 + 1 ; increase the counter by 1 to stop going over the period. goto _loop_sameDir ; and go back to the top of the loop StrCpy $3 $R0 1 $2 ; otherwise, get a single character from the relative path, starting at the position of the counter StrCpy $0 "$0$3" ; and add that character to the absolute path being built goto _loop_sameDir ; then go back to the top of the loop ; example path at this point ; c:\Alpha\Bravo\Charlie..charles\delta\echo\..\..\foxtrot\..\Golf\Hotel\india\..\juliet\..\kilo\..\Li.....ma\..Mike\November\oscar\..\Papa\Quebec..\Romeo\sierra\..\tang.o\uniform\victor\..\whiskey\..\x-ray\yankee\..\..\..\..\Zu.lu\file.ext _dirup: ; This section will deal with \..\ occurrences, removing them -and- the parent folder StrCpy $R0 $0 ; this StrCpy $0 $R0 1 0 ; should StrLen $1 $R0 ; look StrCpy $2 0 ; familar Push "Rel2Abs" ; push a tag to the top of the stack. We'll be doing some popping further down and want to make sure we don't exceed the stack/etc. _loop_dirup: ; more IntOp $2 $2 + 1 ; familiar IntCmp $2 $1 0 0 _loop_cleanStack ; things StrCpy $3 $R0 1 $2 ; get a single character from the relative path, starting at the position of the counter StrCpy $0 "$0$3" ; add that character to the absolute path being built StrCmp $3 "\" 0 _loop_dirup ; if the character was a backslash, continue - otherwise, go back to the top of the stack StrCpy $3 $0 4 -4 ; get -four- characters from the relative path, starting at the position of the counter StrCmp $3 "\..\" 0 _subDir ; if those four were \..\, continue to process this as going up a dir - otherwise we're just going down a dir Pop $0 ; Get the top of the stack into our absolute path. Say the stack looked like "c:\test\", "c:\test\hello\", and we just encountered "c:\test\hello\,,\", then this will be "c:\test\hello\" StrCmp $0 "Rel2Abs" _error ; If the value is our tag, then we just went up the stack too far, and the path this function was fed is invalid, so error out. Pop $0 ; Get the top of the stack in our absolute path. Going with the previous example, this value will now be "c:\test\", and as such as we just moved up a dir. StrCmp $0 "Rel2Abs" _error ; If the value is our tag, then we just went up the stack too far, and the path this function was fed is invalid, so error out. Push $0 ; Push this value back onto the stack because we'll need it on there. goto _loop_dirup ; And go back to the top of the loop _subDir: ; Otherwise we went down a dir Push $0 ; So we'll just push this absolute path so far onto the stacak. goto _loop_dirup ; and go back to the top of the loop ; example path at this point ; c:\Alpha\Bravo\Charlie..charles\Golf\Hotel\Li.....ma\..Mike\November\Papa\Quebec..\Romeo\Zu.lu\file.ext _loop_cleanStack: ; At this point we already have our relative path - but there's a bunch of bits stuck on the stack Pop $1 ; So we pop the stack StrCmp $1 "Rel2Abs" 0 _loop_cleanStack ; and as long as the value isn't our tag, we'll keep on popping StrCpy $R0 $0 ; Once it is, we're done entirely - copy the absolute path into $R0 for end-function stack purposes goto _end ; goto the end (skip over the error) _error: ; This is where we went if the path being fed was mangled or we ran into our tag early otherwise StrCpy $R0 "-1" ; we'll just set the return value to -1 _end: ; end of the function, time to restore variables off the stack and push the result onto it. ; Stack -> ; 3 2 1 0 R0 Pop $3 ; 2 1 0 R0 Pop $2 ; 1 0 R0 Pop $1 ; 0 R0 Pop $0 ; R0 Exch $R0 ; <absolute path> FunctionEnd