Archive: Signing an uninstaller when script runs on a networked drive...


Signing an uninstaller when script runs on a networked drive...
I'm using a slightly modified version of http://nsis.sourceforge.net/Signing_an_Uninstaller

When I run my script on a local drive, it works fine...

However, when we build the installer for our release builds, it runs on a networked location. In this scenario, the following line fails

!system '$\"${NSISDIR}\makensis.exe$\" /DWRITE_TEMP_UNINSTALLER_FOR_SIGNING .\${__FILE__}' = 0

With the error:

Can't open script ".\my_script.nsi"
!system: returned 1, aborting
Error in script "\\networklocation\my_script.nsi" on line 135 -- aborting creation process

My only guess is that I need to fully path the script location but I can't for the life of me find any NSIS functions to know the path where my script is located (I'm sure one exists but my google-fu is weak)...

ideas?

-edit- just found this further up in the execution log which pretty much confirms my suspicions...but I don't know how to fix it:

!system: ""C:\Program Files\NSIS\makensis.exe" /DWRITE_TEMP_UNINSTALLER_FOR_SIGNING my_script.nsi"
'\\networklocation\'
CMD.EXE was started with the above path as the current directory.
UNC paths are not supported. Defaulting to Windows directory.


I could not really reproduce this problem, maybe because I'm on XP or that I have the UNC reghack for cmd.exe. Or maybe you have something in your script or cmd.exe autorun that changes the working directory.

Anyway, you know the filename the first time you call makensis, if the parent is a batch file you can get the full path there and pass it in as a define.

You can try to pipe it in:

!system 'type .\${__FILE__}|$\"${NSISDIR}\makensis.exe$\" /DWRITE_TEMP_UNINSTALLER_FOR_SIGNING -' = 0
There is no easy way to get the full path in NSIS but you can do something like this:
!tempfile temp
!system 'for %A in (".\${__FILE__}") do echo %~fA > "${temp}"' = 0
!searchparse /file "${temp}" "" myfullpath
!delfile "${temp}"
!echo "self=${myfullpath}"

Anders, thanks for looking into this. What is the UNC registry hack that you are using? I'm guessing that is why you aren't seeing the issue.

I'm not scripting the install (yet) from a batch file. Instead I'm using HM NIS Edit 2.0.3 to compile the script.

Right now I've reverted to using the script on the wiki to get it to work (none of my modifications) and having very little luck.

So repo steps would be:

1) create script with the following:

!ifdef INNER
!echo "Inner invocation" ; just to see what's going on
OutFile "$%TEMP%\tempinstaller.exe" ; not really important where this is
SetCompress off ; for speed
!else
!echo "Outer invocation"

; Call makensis again, defining INNER. This writes an installer for us which, when
; it is invoked, will just write the uninstaller to some location, and then exit.
; Be sure to substitute the name of this script here.

!system "$\"${NSISDIR}\makensis$\" /DINNER ${__FILE__}" = 0

; So now run that installer we just created as %TEMP%\tempinstaller.exe. Since it
; calls quit the return value isn't zero.

!system "$%TEMP%\tempinstaller.exe" = 2

; That will have written an uninstaller binary for us. Now we sign it with your
; favourite code signing tool.

!system "SIGNCODE <signing options> $%TEMP%\uninstaller.exe" = 0

; Good. Now we can carry on writing the real installer.

OutFile "my_real_installer.exe"
SetCompressor /SOLID lzma
!endif

Function .onInit
!ifdef INNER

; If INNER is defined, then we aren't supposed to do anything except write out
; the installer. This is better than processing a command line option as it means
; this entire code path is not present in the final (real) installer.

WriteUninstaller "$%TEMP%\uninstaller.exe"
Quit ; just bail out quickly when running the "inner" installer
!endif

FunctionEnd


Section "Files" ; or whatever


; where you would normally put WriteUninstaller ${INSTDIR}\uninstaller.exe put instead:

!ifndef INNER
SetOutPath ${INSTDIR}

; this packages the signed uninstaller

File $%TEMP%\uninstaller.exe
!endif

SectionEnd

!ifdef INNER
Section "Uninstall"

; your normal uninstaller section or sections (they're not needed in the "outer"
; installer and will just cause warnings because there is no WriteInstaller command)

SectionEnd
!endif


2) place this script on a networked location (I believe anything not on the local PC will work)

3) try to compile the script and you should get the same error in my initial post.

I tried your idea of writing the path to a temp file but it doesn't work with the same failure scenario (C:\Windows\<script filename> gets written to the temp file since the !system command redirects to windows directory).

For now, I've found a workaround of mapping a drive to the network location (which seems to work fine but has the added overhead of either using a batch file to map the drive on the fly or a manual pre-build environment setup step)