diff --git a/Help/release/dev/cpack-sign-uninstaller.rst b/Help/release/dev/cpack-sign-uninstaller.rst new file mode 100644 index 0000000000..ff2b402d81 --- /dev/null +++ b/Help/release/dev/cpack-sign-uninstaller.rst @@ -0,0 +1,5 @@ +cpack-sign_uninstaller +---------------------- + +* The :module:`CPackNSIS` module learned to sign the uninstaller + when using :variable:`CPACK_NSIS_SIGN_UNINSTALLER` variable. diff --git a/Modules/CPackNSIS.cmake b/Modules/CPackNSIS.cmake index 18d1871571..37fedf335c 100644 --- a/Modules/CPackNSIS.cmake +++ b/Modules/CPackNSIS.cmake @@ -133,6 +133,10 @@ # "doc/cmake-@CMake_VERSION_MAJOR@.@CMake_VERSION_MINOR@/cmake.html" # "CMake Help" "https://cmake.org" "CMake Web Site") # +# .. variable:: CPACK_NSIS_SIGN_UNINSTALLER +# +# Specify a command to use for signing the uninstaller. The command will +# be invoked a path to the uninstaller as its only argument. #FIXME we should put NSIS specific code here #FIXME but I'm not doing it because I'm not able to test it... diff --git a/Modules/NSIS.template.in b/Modules/NSIS.template.in index 9001888da1..ffa62771bf 100644 --- a/Modules/NSIS.template.in +++ b/Modules/NSIS.template.in @@ -29,6 +29,33 @@ ;-------------------------------- ;General +!ifdef INNER + OutFile "$%TEMP%\tempinstaller.exe" + SetCompress off ; for speed +!else + ; 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 $\"@CPACK_TEMPORARY_DIRECTORY@/../project.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" = 2 + + ; That will have written an uninstaller binary for us. Now we sign it with your + ; favourite code signing tool. + + !tempfile INCEXIST + !system 'if exist "@CPACK_NSIS_SIGN_UNINSTALLER@" echo !define HAVE_SIGN_UNINST > "${INCEXIST}"' + !include "${INCEXIST}" + !delfile "${INCEXIST}" + !ifdef HAVE_SIGN_UNINST + !system '"@CPACK_NSIS_SIGN_UNINSTALLER@" "$%TEMP%\Uninstall.exe"' = 0 + !endif + + ; Good. Now we can carry on writing the real installer. ;Name and file Name "@CPACK_NSIS_PACKAGE_NAME@" @@ -36,6 +63,7 @@ ;Set compression SetCompressor @CPACK_NSIS_COMPRESSOR@ +!endif ;Require administrator access RequestExecutionLevel admin @@ -559,8 +587,10 @@ FunctionEnd !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_FINISH +!ifdef INNER !insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_INSTFILES +!endif ;-------------------------------- ;Languages @@ -642,7 +672,10 @@ Section "-Core installation" WriteRegStr SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "" $INSTDIR ;Create uninstaller - WriteUninstaller "$INSTDIR\Uninstall.exe" +!ifndef INNER + ; this packages the signed uninstaller + File "$%TEMP%\Uninstall.exe" +!endif Push "DisplayName" Push "@CPACK_NSIS_DISPLAY_NAME@" Call ConditionalAddToRegisty @@ -801,6 +834,7 @@ FunctionEnd ;-------------------------------- ;Uninstaller Section +!ifdef INNER Section "Uninstall" ReadRegStr $START_MENU SHCTX \ "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "StartMenu" @@ -886,6 +920,7 @@ Section "Uninstall" Call un.RemoveFromPath doNotRemoveFromPath: SectionEnd +!endif ;-------------------------------- ; determine admin versus local install @@ -898,6 +933,14 @@ SectionEnd ; "Program Files" for AllUsers, "My Documents" for JustMe... 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%\Uninstall.exe" + Quit ; just bail out quickly when running the "inner" installer +!endif StrCmp "@CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL@" "ON" 0 inst ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "UninstallString"