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



请注意,我最初为基于https://nsis.sourceforge.io/Two_installations_in_one_installer的两个应用程序创建了一个安装程序,其中第一个应用程序是主应用程序,而第二个应用程序是许可证管理器。也就是说,我只删除了一层复选框的嵌套复选框。仅供参考,我也一直在参考这篇文章:https://www.codeproject.com/Articles/24187/Creating-an-Installer?msg=5782957#xx5782957xx

我遇到的问题是,当我运行安装程序时,所有来自MyAppFlexLM的文件都安装在$PROGRAMFILES64${PRODUCT_NAME}文件夹和C:${FLEX_DIR}中。因此,当我安装两个应用程序时,看起来SEC1SEC3都为MyApp安装执行,SEC1和SEC3都为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
;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 "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}" 
"DisplayIcon" "$PROGRAMFILES64${PRODUCT_NAME}${PRODUCT_NAME}.exe"
WriteRegStr HKLM "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}" 
"AppID" "{0be21143-9089-47fa-9736-c45609d13d70}"              
WriteRegStr HKLM "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}" 
"DisplayName" "${PRODUCT_NAME}"
WriteRegStr HKLM "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}" 
"DisplayVersion" "${PRODUCT_VERSION}"                 
WriteRegStr HKLM "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}" 
"InstallLocation" "$INSTDIR"                      
WriteRegStr HKLM "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}" 
"Publisher" "${COMPANY_NAME}"                 
WriteRegStr HKLM "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}" 
"UninstallString" "$"$INSTDIRuninstaller.exe$""
# define uninstaller name
WriteUninstaller $INSTDIRuninstaller.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 $INSTDIRuninstaller.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 $INSTDIRuninstaller.exe

# now delete installed files and registry keys for MyApp
Delete $INSTDIRconfig.dat
Delete $INSTDIRMyApp.exe
Delete $INSTDIRReleaseNotes.txt
Delete $INSTDIRMyCompany_LandingPage_114.bmp
Delete $INSTDIRMyAppLicense.txt
Delete "$SMPROGRAMSMyApp.lnk"
DeleteRegKey HKCU "SOFTWARE${PRODUCT_NAME}"
DeleteRegKey HKLM "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}"
DeleteRegKey /ifempty HKCU "SoftwareModern UI Test"       

# now delete installed files and registry keys for FlexLM
Delete $INSTDIRlmdown.exe
Delete $INSTDIRlmflex.exe
Delete $INSTDIRinstalls.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 $TEMPspltmp
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 $TEMPspltmp.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 "$PLUGINSDIRsections.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 "$PLUGINSDIRSections.ini"
Delete "$PLUGINSDIRSections.ini"
FunctionEnd

我怎么能得到只有MyApp文件要安装在$PROGRAMFILES64${PRODUCT_NAME}(即,从SEC1的文件),只有从FlexLM文件要安装在C:FlexLM?TIA。

更新:

请在这里找到我更新的代码:

!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 "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}" 
"DisplayIcon" "$PROGRAMFILES64${PRODUCT_NAME}${PRODUCT_NAME}.exe"
WriteRegStr HKLM "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}" 
"AppID" "{A0E84732-E2B2-46E5-8CA2-462B8DF92DCD}"              
WriteRegStr HKLM "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}" 
"DisplayName" "${PRODUCT_NAME}"
WriteRegStr HKLM "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}" 
"DisplayVersion" "${PRODUCT_VERSION}"                 
WriteRegStr HKLM "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}" 
"InstallLocation" "$INSTDIR"                      
WriteRegStr HKLM "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}" 
"Publisher" "${COMPANY_NAME}"                 
WriteRegStr HKLM "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}" 
"UninstallString" "$"$INSTDIRuninstaller.exe$""
# define uninstaller name
WriteUninstaller $INSTDIRuninstaller.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 $INSTDIRuninstaller.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 $INSTDIRuninstaller.exe

# now delete installed files and registry keys for MyApp
Delete $INSTDIRconfig.dat
Delete $INSTDIRMyApp.exe
Delete $INSTDIRReleaseNotes.txt
Delete $INSTDIRMyCompany_LandingPage_114.bmp
Delete $INSTDIRMyAppLicense.txt
Delete "$SMPROGRAMSMyApp.lnk"
DeleteRegKey HKCU "SOFTWARE${PRODUCT_NAME}"
DeleteRegKey HKLM "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}"
DeleteRegKey /ifempty HKCU "SoftwareModern UI Test"     

# now delete installed files and registry keys for FlexLM
Delete $INSTDIRinstalls.exe
Delete $INSTDIRlmborrow.exe
Delete $INSTDIRlmflex.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 $TEMPspltmp
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 $TEMPspltmp.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 "$PLUGINSDIRsections.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 "$PLUGINSDIRSections.ini"
Delete "$PLUGINSDIRSections.ini"

# FlexLM libs 
;MessageBox MB_OK "DeleteSectionsINI #1 MyAppInstallDir is $MyAppInstallDir"
Delete $MyAppInstallDirinstalls.exe
Delete $MyAppInstallDirlmborrow.exe

# QI Pro files 
;MessageBox MB_OK "DeleteSectionsINI #1 FlexLmInstallDir is $FlexLmInstallDir"
Delete $FlexLmInstallDirconfig.dat
Delete $FlexLmInstallDirMyApp.exe
Delete $FlexLmInstallDirReleaseNotes.txt
Delete $FlexLmInstallDirMyApp_LandingPage_114.bmp
Delete $FlexLmInstallDirMyAppLicense.txt

FunctionEnd

我刚刚测试了来自Wiki的代码,它工作得很好。你在SelectFilesA/B中注释掉了循环,所以难怪在你的例子中section逻辑被打破了。

你还有其他一些问题:

StrCpy $MyAppCheckboxState ${BST_CHECKED}
${If} $MyAppCheckboxState == ${BST_CHECKED}

这没有意义,它总是为真!

同样,CreateShortcut "$SMPROGRAMS${PRODUCT_NAME}.lnk" "$PROGRAMFILES64${PRODUCT_NAME}${PRODUCT_NAME}.exe"是错误的,它应该是CreateShortcut "$SMPROGRAMS${PRODUCT_NAME}.lnk" "$InstDir${PRODUCT_NAME}.exe"

UPDATE 2:

这是我的最终解决方案——非常感谢@Anders。这可能不是最理想或最优雅的解决方案,但它可以满足我的需要。我试着把这个添加到我的问题中,但由于某种原因,SO不让我这么做。
!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 "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}" 
"DisplayIcon" "$PROGRAMFILES64${PRODUCT_NAME}${PRODUCT_NAME}.exe"
WriteRegStr HKLM "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}" 
"AppID" "{A0E84732-E2B2-46E5-8CA2-462B8DF92DCD}"              
WriteRegStr HKLM "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}" 
"DisplayName" "${PRODUCT_NAME}"
WriteRegStr HKLM "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}" 
"DisplayVersion" "${PRODUCT_VERSION}"                 
WriteRegStr HKLM "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}" 
"InstallLocation" "$INSTDIR"                      
WriteRegStr HKLM "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}" 
"Publisher" "${COMPANY_NAME}"                 
WriteRegStr HKLM "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}" 
"UninstallString" "$"$INSTDIRuninstaller.exe$""
# define uninstaller name
WriteUninstaller $INSTDIRuninstaller.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 $INSTDIRuninstaller.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 $INSTDIRuninstaller.exe

# now delete installed files and registry keys for MyApp
Delete $INSTDIRconfig.dat
Delete $INSTDIRMyApp.exe
Delete $INSTDIRReleaseNotes.txt
Delete $INSTDIRMyCompany_LandingPage_114.bmp
Delete $INSTDIRMyAppLicense.txt
Delete "$SMPROGRAMSMyApp.lnk"
DeleteRegKey HKCU "SOFTWARE${PRODUCT_NAME}"
DeleteRegKey HKLM "SoftwareMicrosoftWindowsCurrentVersionUninstall${PRODUCT_NAME}"
DeleteRegKey /ifempty HKCU "SoftwareModern UI Test"     

# now delete installed files and registry keys for FlexLM
Delete $INSTDIRinstalls.exe
Delete $INSTDIRlmborrow.exe
Delete $INSTDIRlmflex.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 $TEMPspltmp
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 $TEMPspltmp.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 "$PLUGINSDIRsections.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 "$PLUGINSDIRSections.ini"
Delete "$PLUGINSDIRSections.ini"

# FlexLM libs 
;MessageBox MB_OK "DeleteSectionsINI #1 MyAppInstallDir is $MyAppInstallDir"
Delete $MyAppInstallDirinstalls.exe
Delete $MyAppInstallDirlmborrow.exe

# QI Pro files 
;MessageBox MB_OK "DeleteSectionsINI #1 FlexLmInstallDir is $FlexLmInstallDir"
Delete $FlexLmInstallDirconfig.dat
Delete $FlexLmInstallDirMyApp.exe
Delete $FlexLmInstallDirReleaseNotes.txt
Delete $FlexLmInstallDirMyApp_LandingPage_114.bmp
Delete $FlexLmInstallDirMyAppLicense.txt

FunctionEnd

相关内容

  • 没有找到相关文章

最新更新