Nsis 两个应用程序的文件都安装在两个目标文件夹中

Nsis 两个应用程序的文件都安装在两个目标文件夹中,nsis,Nsis,请注意,我最初创建了两个应用程序的安装程序,第一个应用程序是主应用程序,而第二个应用程序是license manager。也就是说,我确实删除了只有一层复选框的嵌套复选框。仅供参考,我也参考了这篇文章: 我遇到的问题是,当我运行安装程序时,MyApp和FlexLM中的所有文件都安装在$PROGRAMFILES64\${PRODUCT\u NAME}文件夹和C:\${FLEX\u DIR}中。因此,当我安装两个应用程序时,看起来MyApp安装中同时执行了SEC1和SEC3,而FlexLM安装中同时

请注意,我最初创建了两个应用程序的安装程序,第一个应用程序是主应用程序,而第二个应用程序是license manager。也就是说,我确实删除了只有一层复选框的嵌套复选框。仅供参考,我也参考了这篇文章:

我遇到的问题是,当我运行安装程序时,
MyApp
FlexLM
中的所有文件都安装在
$PROGRAMFILES64\${PRODUCT\u NAME}
文件夹和
C:\${FLEX\u DIR}
中。因此,当我安装两个应用程序时,看起来MyApp安装中同时执行了
SEC1
SEC3
,而
FlexLM
安装中同时执行了SEC1和SEC3:

!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 LANG_ENGLSH "English" 
!define PRODUCT_NAME "MyApp"
!define PRODUCT_VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}.${BUILD_VERSION}"
!define SETUP_NAME "MyAppSetup.exe"

BrandingText "MyCompany"

OutFile ${SETUP_NAME}
Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"

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

SetCompressor /SOLID lzma
SetCompressorDictSize 12

Var MyAppCheckboxState
Var FlexLmCheckboxState

;Request application privileges for Windows 
RequestExecutionLevel admin

!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_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_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

;--------------------------------
;Languages

!insertmacro MUI_LANGUAGE "English"

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

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..."

;--------------------------------
; 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}

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

Section "MyApp" SEC1
  StrCpy $MyAppCheckboxState ${BST_CHECKED}
  ${If} $MyAppCheckboxState == ${BST_CHECKED}
    ##All the files in Group 1 will be installed to the same location, $INSTDIR
    SetOutPath "$INSTDIR"

    # specify files to go in output path
    File config.dat 
    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" "$PROGRAMFILES64\${PRODUCT_NAME}\${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' "{0be21143-9089-47fa-9736-c45609d13d70}"
 
    # 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" "{0be21143-9089-47fa-9736-c45609d13d70}"              
    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\uninstaller.exe$\""

    # define uninstaller name
    WriteUninstaller $INSTDIR\uninstaller.exe        

  ${EndIf}

  # messagebox mb_ok sec1
SectionEnd

Section "FlexLM" SEC3
  StrCpy $FlexLmCheckboxState ${BST_CHECKED}
  ${If} $FlexLmCheckboxState == ${BST_CHECKED}    
    ##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
    
    # define uninstaller name
    WriteUninstaller $INSTDIR\uninstaller.exe

  ${EndIf}    

  # messagebox mb_ok sec3
 
SectionEnd

;--------------------------------
;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

Section "Uninstall"  

  # Always delete uninstaller first
  Delete $INSTDIR\uninstaller.exe
 
  # now delete installed files and registry keys for MyApp
  Delete $INSTDIR\config.dat
  Delete $INSTDIR\MyApp.exe
  Delete $INSTDIR\ReleaseNotes.txt
  Delete $INSTDIR\MyCompany_LandingPage_114.bmp
  Delete $INSTDIR\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"       
        
  # now delete installed files and registry keys for FlexLM
  Delete $INSTDIR\lmdown.exe
  Delete $INSTDIR\lmflex.exe
  Delete $INSTDIR\installs.exe

  # Delete the MyApp and FlexLM directories
  RMDir $INSTDIR

SectionEnd

;--------------------------------
; 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

## 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
 
;  Loop:
;   IntOp $R0 $R0 + 1
;   SectionGetFlags $R0 $R1                 # Get section flags
;    WriteINIStr "$PLUGINSDIR\sections.ini" Sections $R0 $R1 # Save state
;    !insertmacro UnselectSection $R0               # Then unselect it
;    StrCmp $R0 ${PROG2_EndIndex} 0 Loop
 
 # 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
 
;  Loop:
;   IntOp $R0 $R0 + 1
;    !insertmacro UnselectSection $R0       # Unselect it
;    StrCmp $R0 ${PROG1_EndIndex} 0 Loop
 
; Call ResetFiles
 
 # 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"
FunctionEnd
如何仅获取要安装在$PROGRAMFILES64${PRODUCT_NAME}中的MyApp文件(即来自SEC1的文件),以及仅获取要安装在C:\FlexLM中的FlexLM文件?蒂亚

更新:

请在此处找到我的更新代码:

!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 LANG_ENGLSH "English" 
!define PRODUCT_NAME "MyApp"
!define PRODUCT_VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}.${BUILD_VERSION}"
!define SETUP_NAME "MyAppSetup.exe"

BrandingText "MyCompany"

OutFile ${SETUP_NAME}
Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"

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

SetCompressor /SOLID lzma
SetCompressorDictSize 12

Var MyAppCheckboxState
Var FlexLmCheckboxState
Var MyAppInstallDir
Var FlexLmInstallDir

;Request application privileges for Windows 
RequestExecutionLevel admin

!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_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_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

;--------------------------------
;Languages

!insertmacro MUI_LANGUAGE "English"

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

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..."

;--------------------------------
; 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}

;--------------------------------
; 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
  ${If} ${SectionIsSelected} ${SEC1}
    ##All the files in Group 1 will be installed to the same location, $INSTDIR
    SetOutPath "$INSTDIR"
    ;MessageBox MB_OK "SEC1 #1 INSTDIR is $INSTDIR"
    ${StrContains} $0 "MyQpp" "$INSTDIR"
    ;MessageBox MB_OK "SEC1 #2 0 is $0"
    StrCmp $0 "" notfoundMyApp
      StrCpy $MyAppInstallDir "$INSTDIR"
      ;MessageBox MB_OK "SEC1 #3 MyAppInstallDir is $MyAppInstallDir"
      Goto doneMyApp
    notfoundMyApp:
      ;MessageBox MB_OK 'Did not find MyApp string'
    doneMyApp:  

    ${StrContains} $0 "Flex" "$INSTDIR"
    StrCmp $0 "" notfoundFlex
      StrCpy $FlexLmInstallDir "$INSTDIR"
      ;MessageBox MB_OK "SEC1 #4 FlexLmInstallDir is $FlexLmInstallDir"
      Goto doneFlex
    notfoundFlex:
      ;MessageBox MB_OK 'Did not find Flex string'    

    # specify files to go in output path
    File config.dat 
    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\uninstaller.exe$\""

    # define uninstaller name
    WriteUninstaller $INSTDIR\uninstaller.exe        
    doneFlex:   
  ${EndIf}

  # messagebox mb_ok sec1
SectionEnd

Section "FlexLM" SEC3
  ${If} ${SectionIsSelected} ${SEC3}
    ##All the files in Group 2 will be installed to the same location, $INSTDIR
    SetOutPath "$INSTDIR"

    ;MessageBox MB_OK "SEC3 #1 INSTDIR is $INSTDIR"

    ;MessageBox MB_OK "SEC1 #1 INSTDIR is $INSTDIR"
    ${StrContains} $0 "Pro" "$INSTDIR"
    ;MessageBox MB_OK "SEC1 #2 0 is $0"
    StrCmp $0 "" notfoundMyApp
      StrCpy $MyAppInstallDir "$INSTDIR"
      ;MessageBox MB_OK "SEC1 #3 MyAppInstallDir is $MyAppInstallDir"
      Goto doneMyApp
    notfoundMyApp:
      ;MessageBox MB_OK 'Did not find MyApp string'

    ${StrContains} $0 "Flex" "$INSTDIR"
    StrCmp $0 "" notfoundFlex
      StrCpy $FlexLmInstallDir "$INSTDIR"
      ;MessageBox MB_OK "SEC1 #4 FlexLmInstallDir is $FlexLmInstallDir"
      Goto doneFlex
    notfoundFlex:
      ;MessageBox MB_OK 'Did not find Flex string'
    doneFlex:     

    File installs.exe
    File lmdown.exe
    File lmflex.exe
    
    # define uninstaller name
    WriteUninstaller $INSTDIR\uninstaller.exe
    doneQI: 
  ${EndIf}    

  # messagebox mb_ok sec3
 
SectionEnd

;--------------------------------
;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

Section "Uninstall"  

  # Always delete uninstaller first
  Delete $INSTDIR\uninstaller.exe
 
  # now delete installed files and registry keys for MyApp
  Delete $INSTDIR\config.dat
  Delete $INSTDIR\MyApp.exe
  Delete $INSTDIR\ReleaseNotes.txt
  Delete $INSTDIR\MyCompany_LandingPage_114.bmp
  Delete $INSTDIR\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"     
        
  # now delete installed files and registry keys for FlexLM
  Delete $INSTDIR\installs.exe
  Delete $INSTDIR\lmborrow.exe
  Delete $INSTDIR\lmflex.exe

  # Delete the MyApp and FlexLM directories
  RMDir $INSTDIR

SectionEnd

;--------------------------------
; 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

## 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
 
;  Loop:
;   IntOp $R0 $R0 + 1
;   SectionGetFlags $R0 $R1                 # Get section flags
;    WriteINIStr "$PLUGINSDIR\sections.ini" Sections $R0 $R1 # Save state
;    !insertmacro UnselectSection $R0               # Then unselect it
;    StrCmp $R0 ${PROG2_EndIndex} 0 Loop
 
 # 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
 
;  Loop:
;   IntOp $R0 $R0 + 1
;    !insertmacro UnselectSection $R0       # Unselect it
;    StrCmp $R0 ${PROG1_EndIndex} 0 Loop
 
; Call ResetFiles
 
 # 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\lmborrow.exe
  
  # QI Pro files 
  ;MessageBox MB_OK "DeleteSectionsINI #1 FlexLmInstallDir is $FlexLmInstallDir"
  Delete $FlexLmInstallDir\config.dat
  Delete $FlexLmInstallDir\MyApp.exe
  Delete $FlexLmInstallDir\ReleaseNotes.txt
  Delete $FlexLmInstallDir\MyApp_LandingPage_114.bmp
  Delete $FlexLmInstallDir\MyAppLicense.txt
   
FunctionEnd

我刚刚测试了维基上的代码,效果非常好。您在
SelectFilesA
/
B
中注释掉了循环,因此难怪您的示例中的部分逻辑被破坏

您还有一些其他问题:

StrCpy $MyAppCheckboxState ${BST_CHECKED}
${If} $MyAppCheckboxState == ${BST_CHECKED}
这毫无意义,这永远是真的

另外,
CreateShortcut“$SMPROGRAMS\${PRODUCT\u NAME}.lnk”“$PROGRAMFILES64\${PRODUCT\u NAME}\${PRODUCT\u NAME}.exe”
是错误的,它应该是
CreateShortcut“$SMPROGRAMS\${PRODUCT\u NAME}.lnk”“$InstDir\${PRODUCT\u NAME}.exe”
更新2:

这是我的最终解决方案——非常感谢。它可能不是最理想或最优雅的解决方案,但它能满足我的需要。我试着把这个添加到我的问题中,但出于某种原因,所以不让我这么做

!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 LANG_ENGLSH "English" 
!define PRODUCT_NAME "MyApp"
!define PRODUCT_VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}.${BUILD_VERSION}"
!define SETUP_NAME "MyAppSetup.exe"

BrandingText "MyCompany"

OutFile ${SETUP_NAME}
Name "${PRODUCT_NAME}"

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

SetCompressor /SOLID lzma
SetCompressorDictSize 12

Var MyAppInstallDir
Var FlexLmInstallDir

;Request application privileges for Windows 
RequestExecutionLevel admin

!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_SUBTEXT "Please choose 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_SUBTEXT "Please choose 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

;--------------------------------
;Languages

!insertmacro MUI_LANGUAGE "English"

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

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..."

;--------------------------------
; 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}

;--------------------------------
; 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
    ;MessageBox MB_OK "SEC1 #1 INSTDIR is $INSTDIR"
    ${StrContains} $0 "MyApp" "$INSTDIR"
    ;MessageBox MB_OK "SEC1 #2 0 is $0"
    StrCmp $0 "" notfoundMyApp
      StrCpy $MyAppInstallDir "$INSTDIR"
      ;MessageBox MB_OK "SEC1 #3 MyAppInstallDir is $MyAppInstallDir"
      Goto doneMyApp
    notfoundMyApp:
      ;MessageBox MB_OK 'Did not find MyApp string'
    doneMyApp:  

    ${StrContains} $0 "Flex" "$INSTDIR"
    StrCmp $0 "" notfoundFlex
      StrCpy $FlexLmInstallDir "$INSTDIR"
      ;MessageBox MB_OK "SEC1 #4 FlexLmInstallDir is $FlexLmInstallDir"
      Goto doneFlex
    notfoundFlex:
      ;MessageBox MB_OK 'Did not find Flex string'    

    ##All the files in Group 1 will be installed to the same location, $INSTDIR
    SetOutPath "$INSTDIR"

    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\uninstaller.exe$\""

    # define uninstaller name
    WriteUninstaller $INSTDIR\uninstaller.exe        
    doneFlex:   

  # messagebox mb_ok sec1
SectionEnd

Section "FlexLM" SEC3
    ;MessageBox MB_OK "SEC3 #1 INSTDIR is $INSTDIR"

    ;MessageBox MB_OK "SEC1 #1 INSTDIR is $INSTDIR"
    ${StrContains} $0 "Pro" "$INSTDIR"
    ;MessageBox MB_OK "SEC1 #2 0 is $0"
    StrCmp $0 "" notfoundMyApp
      StrCpy $MyAppInstallDir "$INSTDIR"
      ;MessageBox MB_OK "SEC1 #3 MyAppInstallDir is $MyAppInstallDir"
      Goto doneMyApp
    notfoundMyApp:
      ;MessageBox MB_OK 'Did not find MyApp string'

    ${StrContains} $0 "Flex" "$INSTDIR"
    StrCmp $0 "" notfoundFlex
      StrCpy $FlexLmInstallDir "$INSTDIR"
      ;MessageBox MB_OK "SEC1 #4 FlexLmInstallDir is $FlexLmInstallDir"
      Goto doneFlex
    notfoundFlex:
      ;MessageBox MB_OK 'Did not find Flex string'
    doneFlex:     

    ##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
    
    # define uninstaller name
    WriteUninstaller $INSTDIR\uninstaller.exe
    doneQI: 

  # messagebox mb_ok sec3
 
SectionEnd

;--------------------------------
;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

Section "Uninstall"  

  # Always delete uninstaller first
  Delete $INSTDIR\uninstaller.exe
 
  # now delete installed files and registry keys for MyApp
  Delete $INSTDIR\config.dat
  Delete $INSTDIR\MyApp.exe
  Delete $INSTDIR\ReleaseNotes.txt
  Delete $INSTDIR\MyCompany_LandingPage_114.bmp
  Delete $INSTDIR\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"     
        
  # now delete installed files and registry keys for FlexLM
  Delete $INSTDIR\installs.exe
  Delete $INSTDIR\lmborrow.exe
  Delete $INSTDIR\lmflex.exe

  # Delete the MyApp and FlexLM directories
  RMDir $INSTDIR

SectionEnd

;--------------------------------
; 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

## Here we are selecting first sections to install
## by unselecting all the others!
Function SelectFilesA
  ${If} ${SectionIsSelected} ${SEC1}
    ;MessageBox MB_OK "SEC1 #1 INSTDIR is $INSTDIR"
  ${Else}  
      Abort
  ${EndIf}  
 
 # 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
 
;  Loop:
;   IntOp $R0 $R0 + 1
;   SectionGetFlags $R0 $R1                 # Get section flags
;    WriteINIStr "$PLUGINSDIR\sections.ini" Sections $R0 $R1 # Save state
;    !insertmacro UnselectSection $R0               # Then unselect it
;    StrCmp $R0 ${PROG2_EndIndex} 0 Loop
 
 # 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
  ${If} ${SectionIsSelected} ${SEC3}
    ;MessageBox MB_OK "SEC1 #3 INSTDIR is $INSTDIR"
  ${Else}  
      Abort
  ${EndIf} 

Push $R0
;Push $R1
 
 StrCpy $R0 ${PROG1_StartIndex}    # Group 1 start
 
;  Loop:
;   IntOp $R0 $R0 + 1
;    !insertmacro UnselectSection $R0       # Unselect it
;    StrCmp $R0 ${PROG1_EndIndex} 0 Loop
 
; Call ResetFiles
 
 # 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\lmborrow.exe
  
  # QI Pro files 
  ;MessageBox MB_OK "DeleteSectionsINI #1 FlexLmInstallDir is $FlexLmInstallDir"
  Delete $FlexLmInstallDir\config.dat
  Delete $FlexLmInstallDir\MyApp.exe
  Delete $FlexLmInstallDir\ReleaseNotes.txt
  Delete $FlexLmInstallDir\MyApp_LandingPage_114.bmp
  Delete $FlexLmInstallDir\MyAppLicense.txt
   
FunctionEnd

前几天我建议您不要使用多个InstFiles页面,现在我们可以了,也许在一个安装程序脚本中安装两个应用程序不是最佳做法,但也就是说,NSIS网站上有一个脚本示例,它在一个安装程序脚本中安装两个应用程序,那么,这难道不意味着这实际上是由Nullsoft支持的吗?看,这是一个维基,任何人都可以编辑。多个InstFiles页面可以正常工作,只是因为该场景没有被特别阻止,但它确实需要您手动处理部分。我认为最好的调试方法是在每个InstFiles页面之前添加一个components页面,并找出为什么部分的状态不正确。我仍然不明白为什么你坚持要有两个InstFiles页面。有两个目录页和一个InstFiles页非常简单…我注释掉循环的原因是,最初复选框嵌套在两个级别中,但我只需要一个复选框级别。感谢您指出有关${BST_CHECKED}的问题。然后如何获取复选框是否选中的值?抱歉,我不熟悉NSIS脚本当我看这里时,我看到您可以使用${NSD_GetState}获得复选框状态,但我不知道MUI_页面_组件中复选框的名称/句柄,而在SO链接中,复选框称为$hwndCheckbox,因为它是显式创建的。组件页面不使用复选框,它是一个树状视图,但您可以随时使用
${If}${SectionIsSelected}${SEC1}
进行检查。如果您只需要一个级别,请删除分区组。谢谢。如果我决定取消选择“MyApp”怎么办?然后,如果我使用
${if}${SectionIsSelected}${SEC1}
它仍然会显示目录选择对话框并创建MyApp目录,尽管它是空的。如何使此目录选择对话框不显示?在第一个目录页的MUI_页面_CUSTOMFUNCTION_预回调函数中,如果调用了
Abort
,则跳过该页。