Используйте NSIS для создания как обычной установки, так и переносимой установки

В настоящее время мы упаковываем Bitfighter для Windows с помощью NSIS и (иногда) вручную создаем отдельный архив для переносимого запуска игры. Я надеюсь упростить процесс, чтобы упростить создание переносимой версии, тем самым побуждая нас делать это регулярно.

В настоящее время мы создаем наши переносные установки, чтобы установить игру обычным образом (с помощью установщика, созданного NSIS), затем заархивировать папку установки и добавить файл-маркер под названием «переносимый». Я бы хотел пропустить этап установки и напрямую создать переносимый архив.

Основным преимуществом объединения этого с установщиком NSIS является то, что он оптимизирует процесс сборки и позволит нам поддерживать единый список файлов, которые нужно включить.

Кто-нибудь когда-нибудь делал что-нибудь подобное?


В конце концов, я использовал вариант принятого ответа и использовал директивы NSIS! Ifdef для создания двух установщиков с использованием одной и той же кодовой базы. Указав / DPORTALBE, я получу портативный установщик.

Код можно найти в нашем репозитории Google Code < / а>.


person Watusimoto    schedule 08.12.2012    source источник


Ответы (2)


Почему бы не объединить в одном установщике обычный и переносной режимы?

!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

Или простая версия без поддержки графического интерфейса:

!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, а затем очистить и выйти ...

person Anders    schedule 08.12.2012
comment
Итак, первое решение, которое я получаю, я не полностью рассматривал. Второй, похоже, не решает проблему, которую я поставил (или, по крайней мере, пытался поставить :-), а именно, как создать два установщика из одного скрипта или, по крайней мере, из одной спецификации файла, чтобы не иметь расходящихся установщики. Или я что-то упустил? Мне также любопытно, почему вы указали деинсталлятор для портативного приложения? - person Watusimoto; 09.12.2012
comment
Он устанавливается как обычное приложение ИЛИ (извлекает) портативное приложение, например, установщик foobar2000 работает так ... - person Anders; 09.12.2012

ПРИМЕЧАНИЕ. Я опубликовал решение, основанное на использовании 7Zip для извлечения файлов из установщика и создания переносимого архива. К сожалению, я обнаружил, что по какой-то причине 7Zip не видит все файлы в установщике, поэтому в создаваемом им zip-файле не хватало нескольких файлов. Поскольку это ненадежно (и может незаметно выйти из строя), я удалил код.

person Watusimoto    schedule 08.12.2012