2012-12-08 133 views
2

我們目前使用NSIS打包Bitfighter爲Windows,和(有時)手動創建一個單獨的存檔可移植運行遊戲。我希望簡化流程,使構建便攜版本變得更容易,從而鼓勵我們定期進行。使用NSIS創建正常安裝和便攜式安裝

我們創建了便攜式安裝當前的辦法是正常安裝遊戲(使用NSIS生成的安裝程序),然後壓縮安裝文件夾,並添加一個名爲標記的文件「隨身攜帶」。我想繞過安裝步驟,並直接構建便攜式歸檔。

這與NSIS安裝程序相結合的主要優點是,它會簡化構建過程,並且將使我們能夠保持被列入文件的一個列表。

有沒有人做過類似的事情?


最後,我用公認的答案的變化,並用NSIS!IFDEF指令使用相同的代碼庫建立兩個安裝程序。通過指定/ DPORTALBE,我將得到一個便攜式安裝程序。

該代碼可在我們的Google Code repository中找到。

回答

3

爲什麼不把正常模式和便攜模式結合在一個安裝程序中?

!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 

如果你想,你很可能創建一個設置,可以生成壓縮文件:mysetup.exe /GENERATEPORTABLEPKG=c:\path\to\7z.exe然後設置將文件解壓使用ExecWait調用7zip的再清理並退出...

+0

所以第一個解決方案,我得到的,並且是一個想法,我hand't充分考慮。第二個似乎沒有解決我提出的問題(或者至少試圖構成:-),這是如何從一個腳本創建兩個安裝程序,或者至少從單個文件規範創建兩個安裝程序,以便不發散安裝。或者我錯過了什麼?我也很好奇,爲什麼你指定一個便攜式應用程序的卸載程序? – Watusimoto

+0

它安裝爲普通應用程序或(提取)便攜式應用程序,foobar2000安裝程序就像這樣工作,例如... – Anders

0

注意:我發佈了一個基於使用7Zip的解決方案來從安裝程序中提取文件並構建一個可移植的存檔。不幸的是,我發現,無論出於什麼原因,7Zip都沒有看到安裝程序中的每個文件,因此它創建的zip文件缺少一些文件。因爲它不可靠(並且可能會巧妙地失敗),所以我刪除了代碼。

相關問題