installation - 使用 NSIS 创建普通安装和可移植安装

标签 installation nsis portable-applications

我们目前打包Bitfighter对于使用 NSIS 的 Windows,并且(有时)手动创建一个单独的存档以便可移植地运行游戏。我希望简化流程,使构建可移植版本变得更容易,从而鼓励我们定期这样做。

我们当前创建可移植安装的方式是正常安装游戏(使用 NSIS 构建的安装程序),然后压缩安装文件夹,并添加一个名为“portable”的标记文件。我想绕过安装步骤,直接构建可移植存档。

将其与 NSIS 安装程序相结合的主要优点是,它将简化构建过程,并允许我们维护要包含的文件的单个列表。

有人做过这样的事吗?


最后,我使用了已接受答案的变体,并使用 NSIS !ifdef 指令使用相同的代码库构建两个安装程序。通过指定/DPORTALBE,我将获得一个可移植安装程序。

代码可以在我们的 Google Code repository 中找到.

最佳答案

为什么不在一个安装程序中结合正常模式和可移植模式?

!define NAME "foobarbaz"
!define UNINSTKEY "${NAME}" ; Using a GUID here is not a bad idea
!define DEFAULTNORMALDESTINATON "$ProgramFiles\${NAME}"
!define DEFAULTPORTABLEDESTINATON "$Desktop\${NAME}"
Name "${NAME}"
Outfile "${NAME} setup.exe"
RequestExecutionlevel highest
SetCompressor LZMA

Var NormalDestDir
Var PortableDestDir
Var PortableMode

!include LogicLib.nsh
!include FileFunc.nsh
!include MUI2.nsh

!insertmacro MUI_PAGE_WELCOME
Page Custom PortableModePageCreate PortableModePageLeave
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE English


Function .onInit
StrCpy $NormalDestDir "${DEFAULTNORMALDESTINATON}"
StrCpy $PortableDestDir "${DEFAULTPORTABLEDESTINATON}"

${GetParameters} $9

ClearErrors
${GetOptions} $9 "/?" $8
${IfNot} ${Errors}
    MessageBox MB_ICONINFORMATION|MB_SETFOREGROUND "\
      /PORTABLE : Extract application to USB drive etc$\n\
      /S : Silent install$\n\
      /D=%directory% : Specify destination directory$\n"
    Quit
${EndIf}

ClearErrors
${GetOptions} $9 "/PORTABLE" $8
${IfNot} ${Errors}
    StrCpy $PortableMode 1
    StrCpy $0 $PortableDestDir
${Else}
    StrCpy $PortableMode 0
    StrCpy $0 $NormalDestDir
    ${If} ${Silent}
        Call RequireAdmin
    ${EndIf}
${EndIf}

${If} $InstDir == ""
    ; User did not use /D to specify a directory, 
    ; we need to set a default based on the install mode
    StrCpy $InstDir $0
${EndIf}
Call SetModeDestinationFromInstdir
FunctionEnd


Function RequireAdmin
UserInfo::GetAccountType
Pop $8
${If} $8 != "admin"
    MessageBox MB_ICONSTOP "You need administrator rights to install ${NAME}"
    SetErrorLevel 740 ;ERROR_ELEVATION_REQUIRED
    Abort
${EndIf}
FunctionEnd


Function SetModeDestinationFromInstdir
${If} $PortableMode = 0
    StrCpy $NormalDestDir $InstDir
${Else}
    StrCpy $PortableDestDir $InstDir
${EndIf}
FunctionEnd


Function PortableModePageCreate
Call SetModeDestinationFromInstdir ; If the user clicks BACK on the directory page we will remember their mode specific directory
!insertmacro MUI_HEADER_TEXT "Install Mode" "Choose how you want to install ${NAME}."
nsDialogs::Create 1018
Pop $0
${NSD_CreateLabel} 0 10u 100% 24u "Select install mode:"
Pop $0
${NSD_CreateRadioButton} 30u 50u -30u 8u "Normal install"
Pop $1
${NSD_CreateRadioButton} 30u 70u -30u 8u "Portable"
Pop $2
${If} $PortableMode = 0
    SendMessage $1 ${BM_SETCHECK} ${BST_CHECKED} 0
${Else}
    SendMessage $2 ${BM_SETCHECK} ${BST_CHECKED} 0
${EndIf}
nsDialogs::Show
FunctionEnd

Function PortableModePageLeave
${NSD_GetState} $1 $0
${If} $0 <> ${BST_UNCHECKED}
    StrCpy $PortableMode 0
    StrCpy $InstDir $NormalDestDir
    Call RequireAdmin
${Else}
    StrCpy $PortableMode 1
    StrCpy $InstDir $PortableDestDir
${EndIf}
FunctionEnd



Section
SetOutPath "$InstDir"
;File "source\myapp.exe"

${If} $PortableMode = 0
    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINSTKEY}" "DisplayName" "${NAME}"
    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINSTKEY}" "UninstallString" '"$INSTDIR\uninstall.exe"'
    WriteUninstaller "$INSTDIR\uninstall.exe"
${Else}
    ; Create the file the application uses to detect portable mode
    FileOpen $0 "$INSTDIR\portable.dat" w
    FileWrite $0 "PORTABLE"
    FileClose $0
${EndIf}
SectionEnd


Section Uninstall
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINSTKEY}"
Delete "$INSTDIR\uninstall.exe"
;Delete "$INSTDIR\myapp.exe"
RMDir "$InstDir"
SectionEnd

或者没有 GUI 支持的简单版本:

!include LogicLib.nsh
!include FileFunc.nsh
!include Sections.nsh

Section
SetOutPath "$InstDir"
;File "source\myapp.exe"
SectionEnd

Section "" SID_CREATEUNINSTALLER
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINSTKEY}" "DisplayName" "${NAME}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINSTKEY}" "UninstallString" '"$INSTDIR\uninstall.exe"'
WriteUninstaller "$INSTDIR\uninstall.exe"
SectionEnd

Section Uninstall
;...
SectionEnd

Function .onInit
${GetParameters} $9
ClearErrors
${GetOptions} $9 "/PORTABLE" $8
${IfNot} ${Errors}
    SetSilent silent
    ${If} $InstDir == ""
        StrCpy $InstDir "$Desktop\${NAME}"
    ${EndIf}
    !insertmacro UnselectSection ${SID_CREATEUNINSTALLER}
    SetOutPath $InstDir
    WriteIniStr "$InstDir\Config.ini" "Install" "Portable" "yes" ; Mark as portable install
${EndIf}
FunctionEnd

如果您愿意,您可以创建一个可以生成 zip 文件的安装程序:mysetup.exe/GENERATEPORTABLEPKG=c:\path\to\7z.exe 然后安装程序将解压文件,使用 ExecWait 调用 7zip,然后清理并退出...

关于installation - 使用 NSIS 创建普通安装和可移植安装,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13777988/

相关文章:

c# - 可移植独立C#编译器

c++ - 为 C++ 设置 Qt 的初学者指南

c++ - 使用 pcap 开发可移植网络分析器应用程序

c++ - Linux c++ 可移植二进制问题

nsis - 在 IF ELSE block 中有 InstallDir

NSIS-根据FileExists定义InstallDir

nsis - 如何检查 nsis 中 installdir 上的可用空间?

linux - createrepo 使用 --split 选项进行多 CD 分发

c - 禁用 -dkms 错误

php - 如何使用PHP像安装包一样部署站点