简体   繁体   English

为什么即使只选中了一个应用程序复选框,NSIS 安装程序也会为两个应用程序安装运行两次?

[英]Why does NSIS installer run twice for two application installation even if only one app checkbox is selected?

Please note that I have been researching why the above is happening, including studying these links:请注意,我一直在研究为什么会发生上述情况,包括研究这些链接:

NSIS installer .onInit and un.onInit run twice because of UAC 由于 UAC,NSIS 安装程序 .onInit 和 un.onInit 运行两次

https://github.com/Tribler/tribler/pull/2168 https://github.com/Tribler/tribler/pull/2168

But the above UAC issue does not appear to apply to my case because I am not using that plug-in.但是上述 UAC 问题似乎不适用于我的情况,因为我没有使用该插件。 Anyways, I am just wondering, why is the entire script running twice?无论如何,我只是想知道,为什么整个脚本运行两次? I had meant initially to based it on this example script:我最初的意思是基于这个示例脚本:

https://nsis.sourceforge.io/Two_installations_in_one_installer https://nsis.sourceforge.io/Two_installations_in_one_installer

But the script design ended up getting changed a lot, including not requiring the two-layer nested checkboxes.但是脚本设计最终发生了很大变化,包括不需要两层嵌套复选框。

!include "LogicLib.nsh"
!include "Sections.nsh"
    
;Include Modern UI
!include "MUI2.nsh"

!define MAJOR_VERSION "1" 
!define MINOR_VERSION "2" 
!define PATCH_VERSION "3" 
!define BUILD_VERSION "4" 
    
!define APP_COPYRIGHT "MyApp © MyCompany 2021"
!define COMPANY_NAME "MyCompany"
!define FLEX_LM "FlexLM"        
!define FLEX_DIR "FlexSQI"            
!define PRODUCT_NAME "MyApp"
!define PRODUCT_VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}.${BUILD_VERSION}"
!define SETUP_NAME "MyAppSetup.exe"

BrandingText "${COMPANY_NAME}"

OutFile ${SETUP_NAME}
Icon "favicon.ico"
UninstallIcon "favicon.ico"
!define MUI_ICON "favicon.ico"
!define MUI_UNICON "favicon.ico"
Name "${PRODUCT_NAME}"

InstallDir "$PROGRAMFILES64\${PRODUCT_NAME}\"
InstallDirRegKey HKLM "Software\$PRODUCT_NAME" ""
ShowInstDetails hide
ShowUnInstDetails hide

SetCompressor /SOLID lzma
SetCompressorDictSize 12


;Request application privileges for Windows 
RequestExecutionLevel admin

!macro WriteSignedUninstaller Destination
!makensis '"/DGENRATINGUNINST=$%TEMP%\Uninst.exe" "${__FILE__}" "/XOutfile `$%TEMP%\tempinstaller.exe`"' = 0 ; Create fake installer
!system 'set __COMPAT_LAYER=RunAsInvoker&"$%TEMP%\tempinstaller.exe"' = 2 ; Run fake installer to generate the uninstaller
!system 'SIGNTOOL sign /f CodeSigningCertificate/MyCompany.pfx /p Test /tr http://timestamp.digicert.com /td SHA256 "$%TEMP%\Uninst.exe"' = 0 ; Change this line. As a demonstration, use !system 'echo Dummy >> "$%TEMP%\Uninst.exe"'
File "/oname=${Destination}" "$%TEMP%\Uninst.exe"
!macroend

!macro DeclareLanguages
    # Define languages that the installer has
    !insertmacro MUI_LANGUAGE "English"
!macroend

!ifndef GENRATINGUNINST
Var MyAppInstallDir
Var FlexLmInstallDir

# Installer:
############
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "MyAppLicense.txt"

!define MUI_PAGE_CUSTOMFUNCTION_PRE SelectFilesCheck
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE ComponentsLeave
!insertmacro MUI_PAGE_COMPONENTS   
 
## This is the title on the MyApp Directory page
!define MUI_DIRECTORYPAGE_TEXT_TOP "$(MUI_DIRECTORYPAGE_TEXT_TOP_A)"
!define MUI_PAGE_HEADER_TEXT "MyApp Configuration"
!define MUI_PAGE_HEADER_SUBTEXT "Select the folder in which to install MyApp."
 
!define MUI_PAGE_CUSTOMFUNCTION_PRE SelectFilesA
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
 
## This is the title on the FlexLM Directory page
!define MUI_DIRECTORYPAGE_TEXT_TOP "$(MUI_DIRECTORYPAGE_TEXT_TOP_B)"
!define MUI_PAGE_HEADER_TEXT "FlexLM Configuration"
!define MUI_PAGE_HEADER_SUBTEXT "Select the folder in which to install FlexLM."
 
!define MUI_PAGE_CUSTOMFUNCTION_PRE SelectFilesB
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES

!define MUI_PAGE_CUSTOMFUNCTION_LEAVE DeleteSectionsINI
!insertmacro MUI_PAGE_FINISH

!insertmacro MUI_UNPAGE_WELCOME
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_FINISH

!insertmacro DeclareLanguages

;--------------------------------

LangString NoSectionsSelected ${LANG_ENGLSH} "You haven't selected any sections!"

LangString MUI_DIRECTORYPAGE_TEXT_TOP_A ${LANG_ENGLSH} "Setup will install \
${PRODUCT_NAME} in the following folder..."
LangString MUI_DIRECTORYPAGE_TEXT_TOP_B ${LANG_ENGLSH} "Setup will install \
${FLEX_LM} in the following folder..."

;--------------------------------
; Function
; StrContains
; This function does a case sensitive searches for an occurrence of a substring in a string. 
; It returns the substring if it is found. 
; Otherwise it returns null(""). 
; Written by kenglish_hi
; Adapted from StrReplace written by dandaman32
 
 
Var STR_HAYSTACK
Var STR_NEEDLE
Var STR_CONTAINS_VAR_1
Var STR_CONTAINS_VAR_2
Var STR_CONTAINS_VAR_3
Var STR_CONTAINS_VAR_4
Var STR_RETURN_VAR
 
Function StrContains
  Exch $STR_NEEDLE
  Exch 1
  Exch $STR_HAYSTACK
  ; Uncomment to debug
  ;MessageBox MB_OK 'STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK '
    StrCpy $STR_RETURN_VAR ""
    StrCpy $STR_CONTAINS_VAR_1 -1
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK
    loop:
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done
      Goto loop
    found:
      StrCpy $STR_RETURN_VAR $STR_NEEDLE
      Goto done
    done:
   Pop $STR_NEEDLE ;Prevent "invalid opcode" errors and keep the
   Exch $STR_RETURN_VAR  
FunctionEnd
 
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK
  Push `${HAYSTACK}`
  Push `${NEEDLE}`
  Call StrContains
  Pop `${OUT}`
!macroend
 
!define StrContains '!insertmacro "_StrContainsConstructor"'

;--------------------------------
; Start sections

Section "MyApp" SEC1
    ${StrContains} $0 "MyApp" "$INSTDIR"
    StrCmp $0 "" notfoundMyApp
      StrCpy $MyAppInstallDir "$INSTDIR"
      Goto installMyApp
    installMyApp:   
  
    ##All the files in Group 1 will be installed to the same location, $INSTDIR
    SetOutPath "$INSTDIR"
    
    !insertmacro WriteSignedUninstaller "$InstDir\Uninst.exe"

    File MyApp.exe
    File ReleaseNotes.txt
    File MyCompany_LandingPage_114.bmp
    File MyAppLicense.txt  
  
    # create a shortcut named "new shortcut" in the start menu programs directory
    CreateShortcut "$SMPROGRAMS\${PRODUCT_NAME}.lnk" "$InstDir\${PRODUCT_NAME}.exe" 

    # Add application to registry  
    ClearErrors
    WriteRegStr HKCU "SOFTWARE\${PRODUCT_NAME}" 'Company Name' "${COMPANY_NAME}"
    WriteRegStr HKCU "SOFTWARE\${PRODUCT_NAME}" 'Version' "${PRODUCT_VERSION}"
    WriteRegStr HKCU "SOFTWARE\${PRODUCT_NAME}" 'AppID' "{A0E84732-E2B2-46E5-8CA2-462B8DF92DCD}"
 
    # Add program to Add/Remove programs 
    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
                   "DisplayIcon" "$PROGRAMFILES64\${PRODUCT_NAME}\${PRODUCT_NAME}.exe"
    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
                   "AppID" "{A0E84732-E2B2-46E5-8CA2-462B8DF92DCD}"              
    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
                   "DisplayName" "${PRODUCT_NAME}"
    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
                   "DisplayVersion" "${PRODUCT_VERSION}"                 
    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
                   "InstallLocation" "$INSTDIR"                      
    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
                   "Publisher" "${COMPANY_NAME}"                 
    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
                     "UninstallString" "$\"$INSTDIR\Uninst.exe$\""
      
    notfoundMyApp:  

    ; Do nothing                     
SectionEnd

Section /o "FlexLM" SEC3 
    ${StrContains} $0 "Flex" "$INSTDIR"
    StrCmp $0 "" notfoundFlex
      StrCpy $FlexLmInstallDir "$INSTDIR"
      Goto installFlex
    installFlex:      

    ##All the files in Group 2 will be installed to the same location, $INSTDIR
    SetOutPath "$INSTDIR"
    File installs.exe
    File lmdown.exe
    File lmflex.exe
    
    notfoundFlex:
        ; Do nothing
SectionEnd
    
;--------------------------------
; Settings

!define PROG1_InstDir    "$PROGRAMFILES64\${PRODUCT_NAME}"
!define PROG1_StartIndex ${SEC1}
!define PROG1_EndIndex   ${SEC1}
 
!define PROG2_InstDir "C:\${FLEX_DIR}\"
!define PROG2_StartIndex ${SEC3}
!define PROG2_EndIndex   ${SEC3}

;--------------------------------
;Descriptions

  ;Language strings
  LangString DESC_SecMyApp ${LANG_ENGLISH} "MyAppTM software is an easy-to-use suite of tools."
  LangString DESC_SecFlexLM ${LANG_ENGLISH} "FlexSQI contains all the files necessary to implement the FlexLM license server."

  ;Assign language strings to sections
  !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN    
    !insertmacro MUI_DESCRIPTION_TEXT ${SEC1} $(DESC_SecMyApp)
    !insertmacro MUI_DESCRIPTION_TEXT ${SEC3} $(DESC_SecFlexLM)
  !insertmacro MUI_FUNCTION_DESCRIPTION_END


;--------------------------------
; Please don`t modify below here unless you`re a NSIS 'wiz-kid'
 

      
  ## Create $PLUGINSDIR 
Function .onInit
  InitPluginsDir

  SetOutPath $TEMP
  File /oname=spltmp.bmp "MyCompany_LandingPage_114.bmp"

  splash::show 2000 $TEMP\spltmp

  Pop $0 ; $0 has '1' if the user closed the splash screen early,
  ; '0' if everything closed normally, and '-1' if some error occurred.

  Delete $TEMP\spltmp.bmp  
FunctionEnd
 
## If user goes back to this page from 1st Directory page
## we need to put the sections back to how they were before
Var IfBack
Function SelectFilesCheck
 StrCmp $IfBack 1 0 NoCheck
  Call ResetFiles
 NoCheck:
FunctionEnd
 
## Also if no sections are selected, warn the user!
Function ComponentsLeave
Push $R0
Push $R1
 
 Call IsPROG1Selected
  Pop $R0
 Call IsPROG2Selected
  Pop $R1
 StrCmp $R0 1 End
 StrCmp $R1 1 End
  Pop $R1
  Pop $R0
 MessageBox MB_OK|MB_ICONEXCLAMATION "$(NoSectionsSelected)"
 Abort
 
End:
Pop $R1
Pop $R0
FunctionEnd
 
Function IsPROG1Selected
Push $R0
 
 StrCpy $R0 ${PROG1_StartIndex} # Group 1 start
 
   SectionGetFlags 0 $R0            # Get section flags
    IntOp $R0 $R0 & ${SF_SELECTED}
    StrCmp $R0 ${SF_SELECTED} 0 +3      # If section is selected, done
     StrCpy $R0 1
 
Exch $R0
FunctionEnd
 
Function IsPROG2Selected
Push $R1
 
 StrCpy $R1 ${PROG2_StartIndex}    # Group 2 start
 
   IntOp $R1 $R1 + 1
   SectionGetFlags 1 $R1            # Get section flags
    IntOp $R1 $R1 & ${SF_SELECTED}
    StrCmp $R1 ${SF_SELECTED} 0 +3      # If section is selected, done
     StrCpy $R1 1
 
Exch $R1
FunctionEnd
 
## This will set all sections to how they were on the components page
## originally
Function ResetFiles
Push $R0
Push $R1
 StrCpy $R0 ${PROG2_StartIndex}    # Group 2 start
 
  Loop:
   IntOp $R0 $R0 + 1
   ReadINIStr "$R1" "$PLUGINSDIR\sections.ini" Sections $R0 # Get sec flags
    SectionSetFlags $R0 $R1               # Re-set flags for this sec
    StrCmp $R0 ${PROG2_EndIndex} 0 Loop
 
Pop $R1
Pop $R0
FunctionEnd
 
## Here we are selecting first sections to install
## by unselecting all the others!
Function SelectFilesA
 # If user clicks Back now, we will know to reselect Group 2`s sections for
 # Components page
 StrCpy $IfBack 1
 
 # We need to save the state of the Group 2 Sections
 # for the next InstFiles page
Push $R0
Push $R1
 
 StrCpy $R0 ${PROG2_StartIndex} # Group 2 start
 
 # Don`t install prog 1?
 Call IsPROG1Selected
 Pop $R0
 StrCmp $R0 1 +4
  Pop $R1
  Pop $R0
  Abort
 
 # Set current $INSTDIR to PROG1_InstDir define
 StrCpy $INSTDIR "${PROG1_InstDir}"
 
Pop $R1
Pop $R0
FunctionEnd
 
## Here we need to unselect all Group 1 sections
## and then re-select those in Group 2 (that the user had selected on
## Components page)
Function SelectFilesB
Push $R0
;Push $R1
 
 StrCpy $R0 ${PROG1_StartIndex}    # Group 1 start
 
 # Don't install prog 2?
 Call IsPROG2Selected
 Pop $R0
 StrCmp $R0 1 +4
  Pop $R1
  Pop $R0
  Abort
 
 # Set current $INSTDIR to PROG2_InstDir define
 StrCpy $INSTDIR "${PROG2_InstDir}"
 
;Pop $R1
Pop $R0
FunctionEnd

## Here we are deleting the temp INI file at the end of installation
Function DeleteSectionsINI
  FlushINI "$PLUGINSDIR\Sections.ini"
  Delete "$PLUGINSDIR\Sections.ini"
 
  # FlexLM libs 
  ;MessageBox MB_OK "DeleteSectionsINI #1 MyAppInstallDir is $MyAppInstallDir"
  Delete $MyAppInstallDir\installs.exe
  Delete $MyAppInstallDir\lmdown.exe
  Delete $MyAppInstallDir\lmflex.exe
  Delete $MyAppInstallDir\MyAppLicense.txt
  Delete $MyAppInstallDir\MyCompany_LandingPage_114.bmp
  
  # MyApp files 
  Delete $FlexLmInstallDir\config.dat
  Delete $FlexLmInstallDir\MyApp.exe
  Delete $FlexLmInstallDir\ReleaseNotes.txt
  Delete $FlexLmInstallDir\MyCompany_LandingPage_114.bmp
  Delete $FlexLmInstallDir\MyAppLicense.txt
  Delete $FlexLmInstallDir\vcruntime140_1.dll 
    
FunctionEnd


!else
# Uninstaller:
##############
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro DeclareLanguages

!verbose push 2
SilentInstall Silent
Section
WriteUninstaller "${GENRATINGUNINST}"
Quit
SectionEnd
!verbose pop

Section -Uninstall
  # now delete installed files and registry keys for MyApp
  ReadRegStr $0 HKCU "SOFTWARE\${COMPANY_NAME}" "InstallLocation"
  DeleteRegKey HKCU "SOFTWARE\${COMPANY_NAME}"
  Delete $0\config.dat
  Delete $0\MyApp.exe
  Delete $0\ReleaseNotes.txt  
  Delete $0\MyCompany_LandingPage_114.bmp
  Delete $0\MyAppLicense.txt
  Delete "$SMPROGRAMS\MyApp.lnk"
  DeleteRegKey HKCU "SOFTWARE\${PRODUCT_NAME}"
  DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
  DeleteRegKey /ifempty HKCU "Software\Modern UI Test" 

  # Final cleanup 
  RMDir $0
  Delete "$InstDir\Uninst.exe"
  RMDir "$InstDir"
SectionEnd

!endif

Here is a Github link to the source code that now builds: https://github.com/john1726/NsisInstal.git这是现在构建的源代码的 Github 链接: https : //github.com/john1726/NsisInstal.git

Here is the full build log:这是完整的构建日志:

https://pastebin.com/rM2WjYm0 https://pastebin.com/rM2WjYm0

Does anyone have any suggestions?有没有人有什么建议? TIA. TIA。

The section is executed twice because you never deselect the section after "its" instfiles page.该部分执行两次,因为您永远不会在“其”instfiles 页面之后取消选择该部分。 The code on the wiki does !insertmacro UnselectSection but you have removed this from your code. wiki 上的代码执行!insertmacro UnselectSection但您已将其从代码中删除。 You have also removed the call to WriteINIStr !您还删除了对WriteINIStr的调用!

There is no reason to have two instfiles pages, it just makes things terribly complicated.没有理由有两个 instfiles 页面,它只会让事情变得非常复杂。

If you use two directory pages and just one instfiles page you don't have to manipulate the sections at all:如果您使用两个目录页面和一个 instfiles 页面,则根本不必操作这些部分:

!include "LogicLib.nsh"
!include "MUI2.nsh"


Var App1Dir
Var App2Dir

Function .onInit
StrCpy $App1Dir $ProgramFiles\App1
StrCpy $App2Dir $ProgramFiles\App2
FunctionEnd


!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "${__FILE__}"

!define MUI_PAGE_CUSTOMFUNCTION_LEAVE ComponentsLeave
!insertmacro MUI_PAGE_COMPONENTS   
 
!define MUI_DIRECTORYPAGE_TEXT_TOP "$(MUI_DIRECTORYPAGE_TEXT_TOP_A)"
!define MUI_PAGE_HEADER_TEXT "MyApp Configuration"
!define MUI_PAGE_HEADER_SUBTEXT "Select the folder in which to install MyApp."
!define MUI_PAGE_CUSTOMFUNCTION_PRE onFirstDirPre
!define MUI_DIRECTORYPAGE_VARIABLE $App1Dir
!insertmacro MUI_PAGE_DIRECTORY
 
!define MUI_DIRECTORYPAGE_TEXT_TOP "$(MUI_DIRECTORYPAGE_TEXT_TOP_B)"
!define MUI_PAGE_HEADER_TEXT "FlexLM Configuration"
!define MUI_PAGE_HEADER_SUBTEXT "Select the folder in which to install FlexLM."
!define MUI_PAGE_CUSTOMFUNCTION_PRE onLastDirPre
!define MUI_DIRECTORYPAGE_VARIABLE $App2Dir
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH

!insertmacro MUI_LANGUAGE "English"

LangString MUI_DIRECTORYPAGE_TEXT_TOP_A ${LANG_ENGLiSH} "Setup will install \
${PRODUCT_NAME} in the following folder..."
LangString MUI_DIRECTORYPAGE_TEXT_TOP_B ${LANG_ENGLiSH} "Setup will install \
${FLEX_LM} in the following folder..."


Section App1 SID_APP1
StrCpy $InstDir $App1Dir
SetOutPath $InstDir
; File ...
MessageBox '' "Installing App1 to $InstDir"
SectionEnd

Section /o App2 SID_APP2
StrCpy $InstDir $App2Dir
SetOutPath $InstDir
; File ...
MessageBox '' "Installing App2 to $InstDir"
SectionEnd


Function onFirstDirPre
${IfNot} ${SectionIsSelected} ${SID_APP1}
  Abort ; skip page
${EndIf}
${IfNot} ${SectionIsSelected} ${SID_APP2}
  GetDlgItem $0 $hwndParent 1
  SendMessage $0 ${WM_SETTEXT} "" "STR:$(^InstallBtn)"
${EndIf}
FunctionEnd

Function onLastDirPre
${IfNot} ${SectionIsSelected} ${SID_APP2}
  Abort ; skip page
${EndIf}
FunctionEnd

Function ComponentsLeave
StrCpy $0 0
StrCpy $1 ""
loop:
    ClearErrors
    SectionGetText $0 $2
    IfErrors end
    ${If} ${SectionIsSelected} $0
    ${AndIf} $2 != ""
        StrCpy $1 1
    ${EndIf}
    IntOp $0 $0 + 1
    Goto loop
end:
${If} $1 == ""
  MessageBox mb_iconstop "Must select at least one!"
  Abort ; stay on page
${EndIf}
FunctionEnd

Here is the final script that I ended up using which also contains an uninstaller, cleans up registry settings on uninstall, and added a splash bitmap, etc.这是我最终使用的最终脚本,其中还包含一个卸载程序,在卸载时清理注册表设置,并添加了一个启动位图等。

https://github.com/john1726/NsisInstal.git https://github.com/john1726/NsisInstal.git

Here is the actual code:这是实际的代码:

!include "LogicLib.nsh"
    
;Include Modern UI
!include "MUI2.nsh"
!include "Sections.nsh"

!define MAJOR_VERSION "1" 
!define MINOR_VERSION "2" 
!define PATCH_VERSION "3" 
!define BUILD_VERSION "4" 
    
!define APP_COPYRIGHT "MyApp © MyCompany 2021"
!define COMPANY_NAME "MyCompany"
!define FLEX_LM "FlexLM"        
!define FLEX_DIR "FlexSQI"            
!define PRODUCT_NAME "MyApp"
!define PRODUCT_VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}.${BUILD_VERSION}"
!define SETUP_NAME "MyAppSetup.exe"

BrandingText "${COMPANY_NAME}"

OutFile ${SETUP_NAME}
Icon "favicon.ico"
UninstallIcon "favicon.ico"
!define MUI_ICON "favicon.ico"
!define MUI_UNICON "favicon.ico"
Name "${PRODUCT_NAME}"

InstallDir "$PROGRAMFILES64\${PRODUCT_NAME}\"
InstallDirRegKey HKLM "Software\$PRODUCT_NAME" ""
ShowInstDetails hide
ShowUnInstDetails hide

SetCompressor /SOLID lzma
SetCompressorDictSize 12

;Request application privileges for Windows 
RequestExecutionLevel admin

!macro WriteSignedUninstaller Destination
!makensis '"/DGENRATINGUNINST=$%TEMP%\Uninst.exe" "${__FILE__}" "/XOutfile `$%TEMP%\tempinstaller.exe`"' = 0 ; Create fake installer
!system 'set __COMPAT_LAYER=RunAsInvoker&"$%TEMP%\tempinstaller.exe"' = 2 ; Run fake installer to generate the uninstaller
!system 'SIGNTOOL sign /f CodeSigningCertificate/MyCompany.pfx /p Test /tr http://timestamp.digicert.com /td SHA256 "$%TEMP%\Uninst.exe"' = 0 ; Change this line. As a demonstration, use !system 'echo Dummy >> "$%TEMP%\Uninst.exe"'
File "/oname=${Destination}" "$%TEMP%\Uninst.exe"
!macroend

!macro DeclareLanguages
    # Define languages that the installer has
    !insertmacro MUI_LANGUAGE "English"
!macroend

!ifndef GENRATINGUNINST
Var MyAppInstallDir
Var FlexLmInstallDir

## Create $PLUGINSDIR 
Function .onInit
  StrCpy $MyAppInstallDir "$PROGRAMFILES64\${PRODUCT_NAME}\"
  StrCpy $FlexLmInstallDir "C:\${FLEX_DIR}\"

  InitPluginsDir

  SetOutPath $TEMP
  File /oname=spltmp.bmp "MyCompany_LandingPage_114.bmp"

  splash::show 2000 $TEMP\spltmp

  Pop $0 ; $0 has '1' if the user closed the splash screen early,
  ; '0' if everything closed normally, and '-1' if some error occurred.

  Delete $TEMP\spltmp.bmp  
FunctionEnd

# Installer:
############
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "MyAppLicense.txt"

!define MUI_PAGE_CUSTOMFUNCTION_LEAVE ComponentsLeave
!insertmacro MUI_PAGE_COMPONENTS   
 
## This is the title on the MyApp Directory page
!define MUI_DIRECTORYPAGE_TEXT_TOP "$(MUI_DIRECTORYPAGE_TEXT_TOP_A)"
!define MUI_PAGE_HEADER_TEXT "MyApp Configuration"
!define MUI_PAGE_HEADER_SUBTEXT "Select the folder in which to install MyApp."
!define MUI_PAGE_CUSTOMFUNCTION_PRE onFirstDirPre
!define MUI_DIRECTORYPAGE_VARIABLE $MyAppInstallDir
!insertmacro MUI_PAGE_DIRECTORY

## This is the title on the FlexLM Directory page 
!define MUI_DIRECTORYPAGE_TEXT_TOP "$(MUI_DIRECTORYPAGE_TEXT_TOP_B)"
!define MUI_PAGE_HEADER_TEXT "FlexLM Configuration"
!define MUI_PAGE_HEADER_SUBTEXT "Select the folder in which to install FlexLM."
!define MUI_PAGE_CUSTOMFUNCTION_PRE onLastDirPre
!define MUI_DIRECTORYPAGE_VARIABLE $FlexLmInstallDir
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES

!define MUI_PAGE_CUSTOMFUNCTION_LEAVE DeleteSectionsINI
!insertmacro MUI_PAGE_FINISH
!insertmacro DeclareLanguages

;--------------------------------


LangString MUI_DIRECTORYPAGE_TEXT_TOP_A ${LANG_ENGLiSH} "Setup will install \
${PRODUCT_NAME} in the following folder..."
LangString MUI_DIRECTORYPAGE_TEXT_TOP_B ${LANG_ENGLiSH} "Setup will install \
${FLEX_LM} in the following folder..."


Section App1 SID_APP1
    StrCpy $InstDir $MyAppInstallDir
    SetOutPath $InstDir
    !insertmacro WriteSignedUninstaller "$InstDir\Uninst.exe"

    File MyApp.exe
    File ReleaseNotes.txt
    File MyCompany_LandingPage_114.bmp
    File MyAppLicense.txt  
  
    # create a shortcut named "new shortcut" in the start menu programs directory
    CreateShortcut "$SMPROGRAMS\${PRODUCT_NAME}.lnk" "$InstDir\${PRODUCT_NAME}.exe" 

    # Add application to registry  
    ClearErrors
    WriteRegStr HKCU "SOFTWARE\${COMPANY_NAME}" 'Contact' "https://www.mycompany.com/contact"
    WriteRegStr HKCU "SOFTWARE\${COMPANY_NAME}" 'Company Name' "${COMPANY_NAME}"
    WriteRegStr HKCU "SOFTWARE\${COMPANY_NAME}" 'DisplayName' "${PRODUCT_NAME}"
    WriteRegStr HKCU "SOFTWARE\${COMPANY_NAME}" 'DisplayVersion' "${PRODUCT_VERSION}"
    WriteRegStr HKCU "SOFTWARE\${COMPANY_NAME}" 'AppID' "{A0E84732-E2B2-46E5-8CA2-462B8DF92DCD}"
    WriteRegStr HKCU "SOFTWARE\${COMPANY_NAME}" 'HelpLink' "http://www.myproduct.com/MyApp/HelpDocs/index.htm"
    WriteRegStr HKCU "SOFTWARE\${COMPANY_NAME}" 'URLInfoAbout' "https://www.mycompany.com/myapp"
    WriteRegStr HKCU "SOFTWARE\${COMPANY_NAME}" 'InstallLocation' "$MyAppInstallDir"    
    WriteRegStr HKCU "SOFTWARE\${COMPANY_NAME}" 'Publisher' "${COMPANY_NAME}"
 
    # Add program to Add/Remove programs 
    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
                   "DisplayIcon" "$PROGRAMFILES64\${PRODUCT_NAME}\${PRODUCT_NAME}.exe"
    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
                   "AppID" "{A0E84732-E2B2-46E5-8CA2-462B8DF92DCD}"              
    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
                   "DisplayName" "${PRODUCT_NAME}"
    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
                   "DisplayVersion" "${PRODUCT_VERSION}"                 
    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
                   "InstallLocation" "$INSTDIR"                      
    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
                   "Publisher" "${COMPANY_NAME}"                 
    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
                     "UninstallString" "$\"$INSTDIR\Uninst.exe$\""
    ;MessageBox '' "Installing App1 to $InstDir"
SectionEnd

Section /o App2 SID_APP2
    StrCpy $InstDir $FlexLmInstallDir
    SetOutPath $InstDir
    File installs.exe
    File lmdown.exe
    File lmflex.exe
    ; MessageBox '' "Installing App2 to $InstDir"
SectionEnd


Function onFirstDirPre
${IfNot} ${SectionIsSelected} ${SID_APP1}
  Abort ; skip page
${EndIf}
${IfNot} ${SectionIsSelected} ${SID_APP2}
  GetDlgItem $0 $hwndParent 1
  SendMessage $0 ${WM_SETTEXT} "" "STR:$(^InstallBtn)"
${EndIf}
FunctionEnd

Function onLastDirPre
${IfNot} ${SectionIsSelected} ${SID_APP2}
  Abort ; skip page
${EndIf}
FunctionEnd

Function ComponentsLeave
StrCpy $0 0
StrCpy $1 ""
loop:
    ClearErrors
    SectionGetText $0 $2
    IfErrors end
    ${If} ${SectionIsSelected} $0
    ${AndIf} $2 != ""
        StrCpy $1 1
    ${EndIf}
    IntOp $0 $0 + 1
    Goto loop
end:
${If} $1 == ""
  MessageBox mb_iconstop "You haven't selected any sections!"
  Abort ; stay on page
${EndIf}
FunctionEnd

## Here we are deleting the temp INI file at the end of installation
Function DeleteSectionsINI
  FlushINI "$INSTDIR\Sections.ini"
  Delete "$INSTDIR\Sections.ini"

  Delete $MyAppInstallDir\MyCompany_LandingPage_114.bmp
FunctionEnd

!else
# Uninstaller:
##############
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro DeclareLanguages

!verbose push 2
SilentInstall Silent
Section
WriteUninstaller "${GENRATINGUNINST}"
Quit
SectionEnd
!verbose pop

Section -Uninstall
  # now delete installed files and registry keys for MyApp
  ReadRegStr $0 HKCU "SOFTWARE\${COMPANY_NAME}" "InstallLocation"
  ;MessageBox MB_OK 'Uninstall InstallLocation = $0'
  Delete $0\config.dat
  Delete $0\MyApp.exe
  Delete $0\ReleaseNotes.txt  
  Delete $0\MyCompany_LandingPage_114.bmp
  Delete $0\MyAppLicense.txt
  Delete "$SMPROGRAMS\MyApp.lnk"
  DeleteRegKey HKCU "SOFTWARE\${COMPANY_NAME}\${PRODUCT_NAME}"  
  DeleteRegKey HKCU "SOFTWARE\${COMPANY_NAME}"    
  DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
  DeleteRegKey /ifempty HKCU "Software\Modern UI Test" 

  # Final cleanup 
  Delete "$InstDir\Uninst.exe"
  RMDir $0
  RMDir "$InstDir"
SectionEnd

!endif

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 NSIS安装程序:安装前在目录页面上运行功能 - NSIS Installer: Run a function at the directory page before installation NSIS 无法运行驱动程序安装程序批处理文件 - NSIS failing to run driver installer batch file NSIS版本不会在Windows上安装Electron应用程序。 安装程序无提示退出并产生1620错误 - NSIS build does not install the Electron application on Windows. The installer exits silently and produces a 1620 error Windows 安装程序必须写入注册表(与 NSIS 一起安装的编译的 python 应用程序) - It is necessary for a windows installer to write to registary (compiled python app installed with NSIS) 按钮插件在 MUI NSIS 安装程序中不能用于多个按钮 - button plugin not working for more than one button in MUI NSIS Installer 为什么我的 Visual & Installer 菜单中没有 Inno Setup 和 NSIS? - Why aren't Inno Setup and NSIS in my Visual & Installer menu? Android 系统安装程序应用程序“未安装应用程序”为什么? 这个日志在哪里? - Android System Installer App "Application Not Installed" why? where is log for this? NSIS:安装应用程序以始终以管理员身份运行 - NSIS: Installing an Application to always Run as Administrator NSIS:以兼容模式运行安装子文件 - NSIS: Run sub-file of Installation in compatibility mode 在安装程序中将所选语言设置为应用程序的默认语言 - Set the selected language in an installer as the default language of the application
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM