Signing an Uninstaller: Difference between revisions
From NSIS Wiki
Jump to navigationJump to search
No edit summary |
No edit summary |
||
Line 12: | Line 12: | ||
!else | !else | ||
!echo "Outer invocation" | !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. | |||
!system "$\"${NSISDIR}\makensis$\" /DINNER <name_of_script>.nsi" = 0 | !system "$\"${NSISDIR}\makensis$\" /DINNER <name_of_script>.nsi" = 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 /z" = 2 | !system "$%TEMP%\tempinstaller.exe /z" = 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 | !system "SIGNCODE <signing options> $%TEMP%\uninstaller.exe" = 0 | ||
; Good. Now we can carry on writing the real installer. | |||
OutFile "my_real_installer.exe" | OutFile "my_real_installer.exe" | ||
SetCompressor /SOLID lzma | SetCompressor /SOLID lzma | ||
Line 23: | Line 38: | ||
Function .onInit | Function .onInit | ||
!ifdef INNER | !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" | WriteUninstaller "$%TEMP%\uninstaller.exe" | ||
Quit ; just bail out quickly when running the "inner" installer | Quit ; just bail out quickly when running the "inner" installer | ||
Line 39: | Line 59: | ||
!ifndef INNER | !ifndef INNER | ||
SetOutPath $INSTDIR | SetOutPath ${INSTDIR} | ||
; this packages the signed uninstaller | |||
File $%TEMP%\uninstaller.exe | File $%TEMP%\uninstaller.exe | ||
!endif | !endif | ||
Line 49: | Line 72: | ||
Section "Uninstall" | Section "Uninstall" | ||
; your normal uninstaller section or sections (they're not needed in the "outer" installer | ; 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 | SectionEnd |
Revision as of 17:02, 19 April 2007
Especially under Windows Vista, installer/uninstaller binaries need to be signed to avoid alarming looking dialog boxes with dire warnings about "unknown publishers" etc.
This presents a difficulty in that the uninstaller binary would normally never be present on your development/packaging machine, only being written onto the target machine at install time. So how can you sign it?
The answer is to run the installer on the development machine in a special mode which *only* writes the uninstaller to some known location, then sign that binary in the usual way, and finally package the signed uninstaller using a normal File command rather than WriteUninstaller.
!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. !system "$\"${NSISDIR}\makensis$\" /DINNER <name_of_script>.nsi" = 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 /z" = 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 ...[the rest of your normal .onInit]... 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