1
votes

I use NSIS to generate executables packagers.

Currently these packaged products' content can be customized by the developer that generates the installer. For this I created several .nsh script, one per component, and some .nsi script that use components to create the executable.

I was recently asked to offer simple .zip file in addition with .exe packagers. To avoid code duplication, and make sure that the generated .zip and .exe installer share the same content, I would like to use the same .nsh scripts components to create a .zip archive instead of an executable.

I thought it could be easy as .exe generated by NSIS can be opened with 7zip, and is basically an archive, but I couldn't find how.

Do you know if it's doable?

1

1 Answers

0
votes

7-zip has reverse-engineered the NSIS format but because NSIS is script based the results are not perfect.

I would recommend that you give your installer a special extraction mode:

Setup.nsi

Name "Test"
OutFile "Test.exe"
RequestExecutionLevel user
InstallDir "c:\some\path\Test"

Page Components
Page Directory
Page InstFiles

Section "Required program files" INSTSEC_MAIN
SectionIn RO
SetOutPath $InstDir
File "/oname=$InstDir\MyApp.exe" "${__FILE__}"
SectionEnd

Section "Documentation"
SetOutPath $InstDir\Docs
File "/oname=$InstDir\Docs\Foo.txt" "${__FILE__}"
File "/oname=$InstDir\Docs\Bar.txt" "${__FILE__}"
SectionEnd

Section -Uninstaller INSTSEC_UNINST
WriteUninstaller "$InstDir\Uninst.exe"
#WriteRegStr ...
SectionEnd

Section -un.Uninstaller
Delete "$InstDir\Docs\Foo.txt"
Delete "$InstDir\Docs\Bar.txt"
RMDir "$InstDir\Docs"
Delete "$InstDir\MyApp.exe"
Delete "$InstDir\Uninst.exe"
RMDir "$InstDir"
#DeleteRegKey ...
SectionEnd

!include LogicLib.nsh
!include FileFunc.nsh
!include Sections.nsh
Function .onInit
${GetParameters} $0
ClearErrors
${GetOptions} "$0 " "/X" $1
${IfNot} ${Errors}
    SetSilent silent
    !insertmacro UnselectSection ${INSTSEC_UNINST} ; Don't include uninstaller in .zip file
${EndIf}
FunctionEnd

MakeZip.cmd

@echo off
setlocal
set OUTPUT=%~dp0test.zip
set INSTALLER=%~dp0test.exe
set SEVENZIP=7z.exe
set TMPROOT=%temp%\tmpinst%RANDOM%%RANDOM%

call "%INSTALLER%" /X /D=%TMPROOT% && (
    call "%SEVENZIP%" a "%OUTPUT%" -tzip -mx9 -r "%TMPROOT%\*"
    rmdir /S /Q "%TMPROOT%"
)

Note: If you are using RequestExecutionLevel admin in your .nsi then you need to run the batch file elevated.