[英]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.