mirror of
https://github.com/saltstack/salt.git
synced 2025-04-10 23:01:39 +00:00
2213 lines
80 KiB
NSIS
2213 lines
80 KiB
NSIS
# This file must be UNICODE
|
|
|
|
!define PRODUCT_NAME "Salt Minion"
|
|
!define PRODUCT_PUBLISHER "SaltStack, Inc"
|
|
!define PRODUCT_WEB_SITE "http://saltproject.io"
|
|
!define PRODUCT_CALL_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\salt-call.exe"
|
|
!define PRODUCT_CP_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\salt-cp.exe"
|
|
!define PRODUCT_KEY_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\salt-key.exe"
|
|
!define PRODUCT_MASTER_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\salt-master.exe"
|
|
!define PRODUCT_MINION_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\salt-minion.exe"
|
|
!define PRODUCT_RUN_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\salt-run.exe"
|
|
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
|
|
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
|
|
|
|
# Request admin rights
|
|
RequestExecutionLevel admin
|
|
|
|
# Import Libraries
|
|
!include "FileFunc.nsh"
|
|
!include "LogicLib.nsh"
|
|
!include "MoveFileFolder.nsh"
|
|
!include "MUI2.nsh"
|
|
!include "nsDialogs.nsh"
|
|
!include "StrFunc.nsh"
|
|
!include "WinMessages.nsh"
|
|
!include "WinVer.nsh"
|
|
!include "x64.nsh"
|
|
${StrLoc}
|
|
${StrRep}
|
|
${StrStrAdv}
|
|
|
|
# Required by MoveFileFolder.nsh
|
|
!insertmacro Locate
|
|
|
|
# Get salt version from CLI argument /DSaltVersion
|
|
!ifdef SaltVersion
|
|
!define PRODUCT_VERSION "${SaltVersion}"
|
|
!else
|
|
!define PRODUCT_VERSION "Undefined Version"
|
|
!endif
|
|
|
|
# Get architecture from CLI argument /DPythonArchitecture
|
|
# Should be x64, AMD64, or x86
|
|
!ifdef PythonArchitecture
|
|
!define PYTHON_ARCHITECTURE "${PythonArchitecture}"
|
|
!else
|
|
# Default
|
|
!define PYTHON_ARCHITECTURE "x64"
|
|
!endif
|
|
|
|
# Get Estimated Size from CLI argument /DEstimatedSize
|
|
!ifdef EstimatedSize
|
|
!define ESTIMATED_SIZE "${EstimatedSize}"
|
|
!else
|
|
# Default
|
|
!define ESTIMATED_SIZE 0
|
|
!endif
|
|
|
|
# x64 and AMD64 are AMD64, all others are x86
|
|
!if "${PYTHON_ARCHITECTURE}" == "x64"
|
|
!define CPUARCH "AMD64"
|
|
!else if "${PYTHON_ARCHITECTURE}" == "AMD64"
|
|
!define CPUARCH "AMD64"
|
|
!else
|
|
!define CPUARCH "x86"
|
|
!endif
|
|
|
|
!define BUILD_TYPE "Python 3"
|
|
!define OUTFILE "Salt-Minion-${PRODUCT_VERSION}-Py3-${CPUARCH}-Setup.exe"
|
|
|
|
VIProductVersion "1.0.0.0" # This actually updates File Version
|
|
VIAddVersionKey FileVersion "1.0.0.0" # This doesn't seem to do anything, but you'll get a warning without it
|
|
VIAddVersionKey "ProductName" "${PRODUCT_NAME}"
|
|
VIAddVersionKey "LegalTrademarks" "${PRODUCT_NAME} is a trademark of ${PRODUCT_PUBLISHER}"
|
|
VIAddVersionKey "LegalCopyright" "© ${PRODUCT_PUBLISHER}"
|
|
VIAddVersionKey "FileDescription" "${PRODUCT_NAME} Installer"
|
|
VIAddVersionKey "ProductVersion" "${PRODUCT_VERSION}"
|
|
|
|
################################################################################
|
|
# Early defines
|
|
################################################################################
|
|
|
|
!define Trim "!insertmacro Trim"
|
|
!macro Trim ResultVar String
|
|
Push "${String}"
|
|
!ifdef __UNINSTALL__
|
|
Call un.Trim
|
|
!else
|
|
Call Trim
|
|
!endif
|
|
Pop "${ResultVar}"
|
|
!macroend
|
|
|
|
# Part of the Explode function for Strings
|
|
!define Explode "!insertmacro Explode"
|
|
!macro Explode Length Separator String
|
|
Push "${Separator}"
|
|
Push "${String}"
|
|
Call Explode
|
|
Pop "${Length}"
|
|
!macroend
|
|
|
|
# Variables for Logging
|
|
Var LogFile
|
|
Var TimeStamp
|
|
Var cmdLineParams
|
|
Var logFileHandle
|
|
Var msg
|
|
|
|
# Followed this: https://nsis.sourceforge.io/StrRep
|
|
!define LogMsg '!insertmacro LogMsg'
|
|
!macro LogMsg _msg
|
|
Push "${_msg}"
|
|
!ifdef __UNINSTALL__
|
|
Call un.LogMsg
|
|
!else
|
|
Call LogMsg
|
|
!endif
|
|
!macroend
|
|
!macro Func_LogMsg un
|
|
Function ${un}LogMsg
|
|
Pop $msg
|
|
${If} $TimeStamp == ""
|
|
${GetTime} "" "L" $0 $1 $2 $3 $4 $5 $6
|
|
StrCpy $TimeStamp "$2-$1-$0_$4-$5-$6"
|
|
${EndIf}
|
|
${If} $LogFile == ""
|
|
!ifdef __UNINSTALL__
|
|
StrCpy $LogFile "$TEMP\SaltInstaller\$TimeStamp-uninstall.log"
|
|
!else
|
|
StrCpy $LogFile "$TEMP\SaltInstaller\$TimeStamp-install.log"
|
|
!endif
|
|
${IfNot} ${FileExists} "$TEMP\SaltInstaller\*.*"
|
|
CreateDirectory "$TEMP\SaltInstaller"
|
|
${EndIf}
|
|
${EndIf}
|
|
${Trim} $msg $msg
|
|
DetailPrint "$msg"
|
|
FileOpen $logFileHandle "$LogFile" a
|
|
FileSeek $logFileHandle 0 END
|
|
FileWrite $logFileHandle "$msg$\r$\n"
|
|
FileClose $logFileHandle
|
|
FunctionEnd
|
|
!macroend
|
|
!insertmacro Func_LogMsg ""
|
|
!insertmacro Func_LogMsg "un."
|
|
|
|
|
|
###############################################################################
|
|
# Configure Pages, Ordering, and Configuration
|
|
###############################################################################
|
|
!define MUI_ABORTWARNING
|
|
!define MUI_ICON "salt.ico"
|
|
!define MUI_UNICON "salt.ico"
|
|
!define MUI_WELCOMEFINISHPAGE_BITMAP "panel.bmp"
|
|
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "panel.bmp"
|
|
|
|
|
|
# Welcome page
|
|
!insertmacro MUI_PAGE_WELCOME
|
|
|
|
# License page
|
|
!insertmacro MUI_PAGE_LICENSE "LICENSE.txt"
|
|
|
|
# Install location page
|
|
!define MUI_PAGE_CUSTOMFUNCTION_SHOW pageCheckExistingInstall
|
|
!insertmacro MUI_PAGE_DIRECTORY
|
|
|
|
# Configure Minion page
|
|
Page custom pageMinionConfig pageMinionConfig_Leave
|
|
|
|
# Instfiles page
|
|
!insertmacro MUI_PAGE_INSTFILES
|
|
|
|
# Finish page (Customized)
|
|
!define MUI_PAGE_CUSTOMFUNCTION_SHOW pageFinish_Show
|
|
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE pageFinish_Leave
|
|
!insertmacro MUI_PAGE_FINISH
|
|
|
|
# Uninstaller pages
|
|
!insertmacro MUI_UNPAGE_INSTFILES
|
|
|
|
# Language files
|
|
!insertmacro MUI_LANGUAGE "English"
|
|
|
|
|
|
###############################################################################
|
|
# Custom Dialog Box Variables
|
|
###############################################################################
|
|
Var Dialog
|
|
Var Label
|
|
Var MinionStart_ChkBox
|
|
Var MinionStartDelayed_ChkBox
|
|
Var MasterHost_Cfg
|
|
Var MasterHost_TxtBox
|
|
Var MasterHost
|
|
Var MinionName_Cfg
|
|
Var MinionName_TxtBox
|
|
Var MinionName
|
|
Var ExistingConfigFound
|
|
Var ConfigType_DropList
|
|
Var ConfigType
|
|
Var CustomConfig_TxtBox
|
|
Var CustomConfig_Btn
|
|
Var CustomConfig
|
|
Var CustomConfigWarning_Lbl
|
|
Var ExistingConfigWarning_Lbl
|
|
Var DefaultConfigWarning_Lbl
|
|
Var MoveExistingConfig_ChkBox
|
|
Var MoveExistingConfig
|
|
Var StartMinion
|
|
Var StartMinionDelayed
|
|
Var DeleteInstallDir
|
|
Var DeleteRootDir
|
|
Var ConfigWriteMinion
|
|
Var ConfigWriteMaster
|
|
# For new method installation
|
|
Var RegInstDir
|
|
Var RegRootDir
|
|
Var RootDir
|
|
Var SysDrive
|
|
Var ExistingInstallation
|
|
Var CustomLocation
|
|
|
|
|
|
###############################################################################
|
|
# Directory Picker Dialog Box
|
|
###############################################################################
|
|
Function pageCheckExistingInstall
|
|
# If this is an Existing Installation we want to disable the directory
|
|
# picker functionality
|
|
# https://nsis-dev.github.io/NSIS-Forums/html/t-166727.html
|
|
# Use the winspy tool (https://sourceforge.net/projects/winspyex/) to get
|
|
# the Control ID for the items you want to disable
|
|
# The Control ID is in the Details tab
|
|
# It is a Hex value that needs to be converted to an integer
|
|
${If} $ExistingInstallation == 1
|
|
# 32770 is Class name used by all NSIS dialog boxes
|
|
FindWindow $R0 "#32770" "" $HWNDPARENT
|
|
# 1019 is the Destination Folder text field (0x3FB)
|
|
GetDlgItem $R1 $R0 1019
|
|
EnableWindow $R1 0
|
|
# 1001 is the Browse button (0x3E9)
|
|
GetDlgItem $R1 $R0 1001
|
|
EnableWindow $R1 0
|
|
# Disabling the Location Picker causes the buttons to behave incorrectly
|
|
# Esc and Enter don't work. Nor can you use Alt+N and Alt+B. Setting
|
|
# the focus to the Next button seems to fix this
|
|
# Set focus on Next button (0x1)
|
|
# Next=1, cancel=2, back=3
|
|
GetDlgItem $R1 $HWNDPARENT 1
|
|
SendMessage $HWNDPARENT ${WM_NEXTDLGCTL} $R1 1
|
|
${EndIf}
|
|
FunctionEnd
|
|
|
|
|
|
###############################################################################
|
|
# Minion Settings Dialog Box
|
|
###############################################################################
|
|
Function pageMinionConfig
|
|
|
|
# Set Page Title and Description
|
|
!insertmacro MUI_HEADER_TEXT "Minion Settings" "Set the Minion Master and ID"
|
|
nsDialogs::Create 1018
|
|
Pop $Dialog
|
|
|
|
${If} $Dialog == error
|
|
Abort
|
|
${EndIf}
|
|
|
|
# Master IP or Hostname Dialog Control
|
|
${NSD_CreateLabel} 0 0 100% 9u "&Master IP or Hostname:"
|
|
Pop $Label
|
|
|
|
${NSD_CreateText} 0 10u 100% 12u $MasterHost
|
|
Pop $MasterHost_TxtBox
|
|
|
|
# Minion ID Dialog Control
|
|
${NSD_CreateLabel} 0 30u 100% 9u "Minion &Name:"
|
|
Pop $Label
|
|
|
|
${NSD_CreateText} 0 40u 100% 12u $MinionName
|
|
Pop $MinionName_TxtBox
|
|
|
|
# Config Drop List
|
|
${NSD_CreateDropList} 0 60u 25% 36u ""
|
|
Pop $ConfigType_DropList
|
|
${NSD_CB_AddString} $ConfigType_DropList "Default Config"
|
|
${NSD_CB_AddString} $ConfigType_DropList "Custom Config"
|
|
${NSD_OnChange} $ConfigType_DropList pageMinionConfig_OnChange
|
|
|
|
# Add Existing Config Warning Label
|
|
${NSD_CreateLabel} 0 75u 100% 50u \
|
|
"The values above are taken from an existing configuration found in \
|
|
`$RootDir\conf\minion`.$\n\
|
|
$\n\
|
|
Clicking `Install` will leave the existing config unchanged."
|
|
Pop $ExistingConfigWarning_Lbl
|
|
CreateFont $0 "Arial" 10 500 /ITALIC
|
|
SendMessage $ExistingConfigWarning_Lbl ${WM_SETFONT} $0 1
|
|
SetCtlColors $ExistingConfigWarning_Lbl 0xBB0000 transparent
|
|
|
|
# Add Checkbox to move root_dir
|
|
${NSD_CreateCheckBox} 0 125u 100% 10u \
|
|
"Move &existing root directory (C:\salt) to %ProgramData%\Salt."
|
|
Pop $MoveExistingConfig_ChkBox
|
|
CreateFont $0 "Arial" 10 500
|
|
SendMessage $MoveExistingConfig_ChkBox ${WM_SETFONT} $0 1
|
|
${If} $MoveExistingConfig == 1
|
|
${NSD_Check} $MoveExistingConfig_ChkBox
|
|
${EndIf}
|
|
|
|
# Add Default Config Warning Label
|
|
${NSD_CreateLabel} 0 75u 100% 60u "Clicking `Install` will backup the \
|
|
existing minion config file and minion.d directories. The values \
|
|
above will be used in the new default config.$\n\
|
|
$\n\
|
|
NOTE: If Master IP is set to `salt` and Minion Name is set to \
|
|
`hostname` no changes will be made."
|
|
Pop $DefaultConfigWarning_Lbl
|
|
CreateFont $0 "Arial" 10 500 /ITALIC
|
|
SendMessage $DefaultConfigWarning_Lbl ${WM_SETFONT} $0 1
|
|
SetCtlColors $DefaultConfigWarning_Lbl 0xBB0000 transparent
|
|
|
|
# Add Custom Config File Selector and Warning Label
|
|
${NSD_CreateText} 26% 60u 64% 12u $CustomConfig
|
|
Pop $CustomConfig_TxtBox
|
|
${NSD_CreateButton} 91% 60u 9% 12u "..."
|
|
Pop $CustomConfig_Btn
|
|
${NSD_OnClick} $CustomConfig_Btn pageCustomConfigBtn_OnClick
|
|
|
|
${If} $ExistingConfigFound == 0
|
|
${NSD_CreateLabel} 0 75u 100% 60u \
|
|
"Values entered above will be used in the custom config.$\n\
|
|
$\n\
|
|
NOTE: If Master IP is set to `salt` and Minion Name is set to \
|
|
`hostname` no changes will be made."
|
|
${Else}
|
|
${NSD_CreateLabel} 0 75u 100% 60u \
|
|
"Clicking `Install` will backup the existing minion config \
|
|
file and minion.d directories. The values above will be used in \
|
|
the custom config.$\n\
|
|
$\n\
|
|
NOTE: If Master IP is set to `salt` and Minion Name is set to \
|
|
`hostname` no changes will be made."
|
|
${Endif}
|
|
Pop $CustomConfigWarning_Lbl
|
|
CreateFont $0 "Arial" 10 500 /ITALIC
|
|
SendMessage $CustomConfigWarning_Lbl ${WM_SETFONT} $0 1
|
|
SetCtlColors $CustomConfigWarning_Lbl 0xBB0000 transparent
|
|
|
|
# If existing config found, add the Existing Config option to the Drop List
|
|
# If not, hide the Default Warning
|
|
${If} $ExistingConfigFound == 1
|
|
${NSD_CB_AddString} $ConfigType_DropList "Existing Config"
|
|
${Else}
|
|
ShowWindow $DefaultConfigWarning_Lbl ${SW_HIDE}
|
|
${Endif}
|
|
|
|
${NSD_CB_SelectString} $ConfigType_DropList $ConfigType
|
|
${NSD_SetText} $CustomConfig_TxtBox $CustomConfig
|
|
|
|
Call pageMinionConfig_OnChange
|
|
|
|
nsDialogs::Show
|
|
|
|
FunctionEnd
|
|
|
|
|
|
Function pageMinionConfig_OnChange
|
|
|
|
# You have to pop the top handle to keep the stack clean
|
|
Pop $R0
|
|
|
|
# Assign the current checkbox state to the variable
|
|
${NSD_GetText} $ConfigType_DropList $ConfigType
|
|
|
|
# Update Dialog
|
|
${Switch} $ConfigType
|
|
${Case} "Existing Config"
|
|
# Enable Master/Minion and set values
|
|
EnableWindow $MasterHost_TxtBox 0
|
|
EnableWindow $MinionName_TxtBox 0
|
|
${NSD_SetText} $MasterHost_TxtBox $MasterHost_Cfg
|
|
${NSD_SetText} $MinionName_TxtBox $MinionName_Cfg
|
|
# Hide Custom File Picker
|
|
ShowWindow $CustomConfig_TxtBox ${SW_HIDE}
|
|
ShowWindow $CustomConfig_Btn ${SW_HIDE}
|
|
# Hide Warnings
|
|
ShowWindow $DefaultConfigWarning_Lbl ${SW_HIDE}
|
|
ShowWindow $CustomConfigWarning_Lbl ${SW_HIDE}
|
|
# Show Existing Warning
|
|
ShowWindow $ExistingConfigWarning_Lbl ${SW_SHOW}
|
|
${If} $RootDir == "C:\salt"
|
|
ShowWindow $MoveExistingConfig_ChkBox ${SW_SHOW}
|
|
${Else}
|
|
ShowWindow $MoveExistingConfig_ChkBox ${SW_HIDE}
|
|
${EndIf}
|
|
${Break}
|
|
${Case} "Custom Config"
|
|
# Enable Master/Minion and set values
|
|
EnableWindow $MasterHost_TxtBox 1
|
|
EnableWindow $MinionName_TxtBox 1
|
|
${NSD_SetText} $MasterHost_TxtBox $MasterHost
|
|
${NSD_SetText} $MinionName_TxtBox $MinionName
|
|
# Show Custom File Picker
|
|
ShowWindow $CustomConfig_TxtBox ${SW_SHOW}
|
|
ShowWindow $CustomConfig_Btn ${SW_SHOW}
|
|
# Hide Warnings
|
|
ShowWindow $DefaultConfigWarning_Lbl ${SW_HIDE}
|
|
ShowWindow $ExistingConfigWarning_Lbl ${SW_HIDE}
|
|
ShowWindow $MoveExistingConfig_ChkBox ${SW_HIDE}
|
|
# Show Custom Warning
|
|
ShowWindow $CustomConfigWarning_Lbl ${SW_SHOW}
|
|
${Break}
|
|
${Case} "Default Config"
|
|
# Enable Master/Minion and set values
|
|
EnableWindow $MasterHost_TxtBox 1
|
|
EnableWindow $MinionName_TxtBox 1
|
|
${NSD_SetText} $MasterHost_TxtBox $MasterHost
|
|
${NSD_SetText} $MinionName_TxtBox $MinionName
|
|
# Hide Custom File Picker
|
|
ShowWindow $CustomConfig_TxtBox ${SW_HIDE}
|
|
ShowWindow $CustomConfig_Btn ${SW_HIDE}
|
|
# Hide Warnings
|
|
ShowWindow $ExistingConfigWarning_Lbl ${SW_HIDE}
|
|
ShowWindow $MoveExistingConfig_ChkBox ${SW_HIDE}
|
|
ShowWindow $CustomConfigWarning_Lbl ${SW_HIDE}
|
|
# Show Default Warning, if there is an existing config
|
|
${If} $ExistingConfigFound == 1
|
|
ShowWindow $DefaultConfigWarning_Lbl ${SW_SHOW}
|
|
${Endif}
|
|
${Break}
|
|
${EndSwitch}
|
|
|
|
FunctionEnd
|
|
|
|
# File Picker Definitions
|
|
!define OFN_FILEMUSTEXIST 0x00001000
|
|
!define OFN_DONTADDTOREC 0x02000000
|
|
!define OPENFILENAME_SIZE_VERSION_400 76
|
|
!define OPENFILENAME 'i,i,i,i,i,i,i,i,i,i,i,i,i,i,&i2,&i2,i,i,i,i'
|
|
Function pageCustomConfigBtn_OnClick
|
|
|
|
Pop $0
|
|
System::Call '*(&t${NSIS_MAX_STRLEN})i.s' # Allocate OPENFILENAME.lpstrFile buffer
|
|
System::Call '*(${OPENFILENAME})i.r0' # Allocate OPENFILENAME struct
|
|
System::Call '*$0(${OPENFILENAME})(${OPENFILENAME_SIZE_VERSION_400}, \
|
|
$hwndparent, , , , , , sr1, ${NSIS_MAX_STRLEN} , , , , \
|
|
t"Select Custom Config File", \
|
|
${OFN_FILEMUSTEXIST} | ${OFN_DONTADDTOREC})'
|
|
|
|
# Populate file name field
|
|
${NSD_GetText} $CustomConfig_TxtBox $2
|
|
System::Call "*$1(&t${NSIS_MAX_STRLEN}r2)" ; Set lpstrFile to the old path (if any)
|
|
|
|
# Open the dialog
|
|
System::Call 'COMDLG32::GetOpenFileName(ir0)i.r2'
|
|
|
|
# Get file name field
|
|
${If} $2 <> 0
|
|
System::Call "*$1(&t${NSIS_MAX_STRLEN}.r2)"
|
|
${NSD_SetText} $CustomConfig_TxtBox $2
|
|
${EndIf}
|
|
|
|
# Free resources
|
|
System::Free $1
|
|
System::Free $0
|
|
|
|
FunctionEnd
|
|
|
|
|
|
Function pageMinionConfig_Leave
|
|
|
|
# Save the State
|
|
${NSD_GetText} $MasterHost_TxtBox $MasterHost
|
|
${NSD_GetText} $MinionName_TxtBox $MinionName
|
|
${NSD_GetText} $ConfigType_DropList $ConfigType
|
|
${NSD_GetText} $CustomConfig_TxtBox $CustomConfig
|
|
${NSD_GetState} $MoveExistingConfig_ChkBox $MoveExistingConfig
|
|
|
|
# Abort if config file not found
|
|
${If} $ConfigType == "Custom Config"
|
|
IfFileExists "$CustomConfig" done 0
|
|
MessageBox MB_OK|MB_ICONEXCLAMATION \
|
|
"File not found: $CustomConfig" \
|
|
/SD IDOK
|
|
Abort
|
|
${EndIf}
|
|
|
|
${If} $MoveExistingConfig == 1
|
|
|
|
# This makes the $APPDATA variable point to the ProgramData folder
|
|
# instead of the current user's roaming AppData folder
|
|
SetShellVarContext all
|
|
|
|
# Get directory status
|
|
# We don't want to overwrite data in the new location, so it needs to
|
|
# either be empty or not found. Otherwise, warn and abort
|
|
${DirState} "$APPDATA\Salt Project\Salt" $R0 # 0=Empty, 1=full, -1=Not Found
|
|
StrCmp $R0 "1" 0 done # Move files if directory empty or missing
|
|
MessageBox MB_OKCANCEL \
|
|
"The $APPDATA\Salt Project\Salt directory is not empty.$\n\
|
|
These files will need to be moved manually." \
|
|
/SD IDOK IDCANCEL cancel
|
|
# OK: We're continuing without moving existing config
|
|
StrCpy $MoveExistingConfig 0
|
|
Goto done
|
|
|
|
cancel:
|
|
# Cancel: We're unchecking the checkbox and returning the user to
|
|
# the dialog box
|
|
# Abort just returns the user back to the dialog box
|
|
${NSD_UNCHECK} $MoveExistingConfig_ChkBox
|
|
Abort
|
|
|
|
${EndIf}
|
|
|
|
done:
|
|
|
|
FunctionEnd
|
|
|
|
|
|
###############################################################################
|
|
# Custom Finish Page
|
|
###############################################################################
|
|
Function pageFinish_Show
|
|
|
|
# Imports so the checkboxes will show up
|
|
!define SWP_NOSIZE 0x0001
|
|
!define SWP_NOMOVE 0x0002
|
|
!define HWND_TOP 0x0000
|
|
|
|
# Create Start Minion Checkbox
|
|
${NSD_CreateCheckbox} 120u 90u 100% 12u "&Start salt-minion"
|
|
Pop $MinionStart_ChkBox
|
|
SetCtlColors $MinionStart_ChkBox "" "ffffff"
|
|
# This command required to bring the checkbox to the front
|
|
System::Call "User32::SetWindowPos(i, i, i, i, i, i, i) b ($MinionStart_ChkBox, ${HWND_TOP}, 0, 0, 0, 0, ${SWP_NOSIZE}|${SWP_NOMOVE})"
|
|
|
|
# Create Start Minion Delayed ComboBox
|
|
${NSD_CreateCheckbox} 130u 102u 100% 12u "&Delayed Start"
|
|
Pop $MinionStartDelayed_ChkBox
|
|
SetCtlColors $MinionStartDelayed_ChkBox "" "ffffff"
|
|
# This command required to bring the checkbox to the front
|
|
System::Call "User32::SetWindowPos(i, i, i, i, i, i, i) b ($MinionStartDelayed_ChkBox, ${HWND_TOP}, 0, 0, 0, 0, ${SWP_NOSIZE}|${SWP_NOMOVE})"
|
|
|
|
# Load current settings for Minion
|
|
${If} $StartMinion == 1
|
|
${NSD_Check} $MinionStart_ChkBox
|
|
${EndIf}
|
|
|
|
# Load current settings for Minion Delayed
|
|
${If} $StartMinionDelayed == 1
|
|
${NSD_Check} $MinionStartDelayed_ChkBox
|
|
${EndIf}
|
|
|
|
FunctionEnd
|
|
|
|
|
|
Function pageFinish_Leave
|
|
|
|
# Assign the current checkbox states
|
|
${NSD_GetState} $MinionStart_ChkBox $StartMinion
|
|
${NSD_GetState} $MinionStartDelayed_ChkBox $StartMinionDelayed
|
|
|
|
FunctionEnd
|
|
|
|
|
|
###############################################################################
|
|
# Installation Settings
|
|
###############################################################################
|
|
Name "${PRODUCT_NAME} ${PRODUCT_VERSION} (${BUILD_TYPE})"
|
|
OutFile "${OutFile}"
|
|
InstallDir "C:\Program Files\Salt Project\Salt"
|
|
InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
|
|
ShowInstDetails show
|
|
ShowUnInstDetails show
|
|
|
|
|
|
Section -copy_prereqs
|
|
# Copy prereqs to the Plugins Directory
|
|
# These files are downloaded by build_pkg.bat
|
|
# This directory gets removed upon completion
|
|
SetOutPath "$PLUGINSDIR\"
|
|
File /r "..\..\prereqs\"
|
|
SectionEnd
|
|
|
|
|
|
# Check and install Visual C++ redist 2022 packages
|
|
# Hidden section (-) to install VCRedist
|
|
Section -install_vcredist_2022
|
|
|
|
${DisableX64FSRedirection}
|
|
|
|
Var /GLOBAL VcRedistName
|
|
# Determine which architecture needs to be installed
|
|
${if} ${runningx64}
|
|
strcpy $VcRedistName "vcredist_x64_2022"
|
|
${else}
|
|
strcpy $VcRedistName "vcredist_x86_2022"
|
|
${endif}
|
|
detailPrint "Selected $VcRedistName installer"
|
|
|
|
# Check for the presence of vcruntime140.dll
|
|
IfFileExists "$WINDIR\System32\vcruntime140.dll" file_found
|
|
|
|
file_not_found:
|
|
detailPrint "$VcRedistName not found"
|
|
# Install
|
|
Call InstallVCRedist
|
|
Goto end_of_section
|
|
|
|
file_found:
|
|
detailPrint "$VcRedistName found, install will continue"
|
|
|
|
end_of_section:
|
|
|
|
${EnableX64FSRedirection}
|
|
|
|
SectionEnd
|
|
|
|
|
|
Function InstallVCRedist
|
|
detailPrint "System requires $VcRedistName"
|
|
MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 \
|
|
"$VcRedistName is currently not installed. Would you like to install?" \
|
|
/SD IDYES IDYES InstallVcRedist
|
|
|
|
detailPrint "$VcRedistName not installed"
|
|
detailPrint ">>>Installation aborted by user<<<"
|
|
MessageBox MB_ICONEXCLAMATION \
|
|
"$VcRedistName not installed. Aborted by user.$\n$\n\
|
|
Installer will now close." \
|
|
/SD IDOK
|
|
Quit
|
|
|
|
InstallVcRedist:
|
|
|
|
# If an output variable is specified ($0 in the case below), ExecWait
|
|
# sets the variable with the exit code (and only sets the error flag if
|
|
# an error occurs; if an error occurs, the contents of the user
|
|
# variable are undefined).
|
|
# http://nsis.sourceforge.net/Reference/ExecWait
|
|
ClearErrors
|
|
detailPrint "Installing $VcRedistName..."
|
|
ExecWait '"$PLUGINSDIR\$VcRedistName.exe" /install /quiet /norestart' $0
|
|
|
|
IfErrors 0 CheckVcRedistErrorCode
|
|
|
|
detailPrint "An error occurred during installation of $VcRedistName"
|
|
MessageBox MB_OK|MB_ICONEXCLAMATION \
|
|
"$VcRedistName failed to install. Try installing the package \
|
|
manually.$\n$\n\
|
|
The installer will now close." \
|
|
/SD IDOK
|
|
Quit
|
|
|
|
CheckVcRedistErrorCode:
|
|
# Check for Reboot Error Code (3010)
|
|
${If} $0 == 3010
|
|
detailPrint "$VcRedistName installed but requires a restart to complete."
|
|
detailPrint "Reboot and run Salt install again"
|
|
MessageBox MB_OK|MB_ICONINFORMATION \
|
|
"$VcRedistName installed but requires a restart to complete." \
|
|
/SD IDOK
|
|
|
|
# Check for any other errors
|
|
${ElseIfNot} $0 == 0
|
|
detailPrint "An error occurred during installation of $VcRedistName"
|
|
detailPrint "Error: $0"
|
|
MessageBox MB_OK|MB_ICONEXCLAMATION \
|
|
"$VcRedistName failed to install. Try installing the package \
|
|
mnually.$\n\
|
|
ErrorCode: $0$\n\
|
|
The installer will now close." \
|
|
/SD IDOK
|
|
${EndIf}
|
|
|
|
FunctionEnd
|
|
|
|
|
|
Section "Install" Install01
|
|
|
|
${If} $MoveExistingConfig == 1
|
|
${LogMsg} "Moving existing config to $APPDATA\Salt Project\Salt"
|
|
|
|
# This makes the $APPDATA variable point to the ProgramData folder
|
|
# instead of the current user's roaming AppData folder
|
|
${LogMsg} "Set context to all users"
|
|
SetShellVarContext all
|
|
|
|
# Make sure the target directory exists
|
|
${LogMsg} "Creating rootdir in ProgramData"
|
|
CreateDirectory "$APPDATA\Salt Project\Salt"
|
|
|
|
# Take ownership of the C:\salt directory
|
|
${LogMsg} "Taking ownership: $RootDir"
|
|
nsExec::ExecToStack "takeown /F $RootDir /R"
|
|
pop $0 # ExitCode
|
|
pop $1 # StdOut
|
|
${If} $0 == 0
|
|
${LogMsg} "Success"
|
|
${Else}
|
|
${LogMsg} "Failed$\r$\nExitCode: $0$\r$\nStdOut: $1"
|
|
${EndIf}
|
|
# Move the C:\salt directory to the new location
|
|
StrCpy $switch_overwrite 0
|
|
${If} ${FileExists} "$RootDir\conf\*.*"
|
|
${LogMsg} "Moving $RootDir\conf to $APPDATA"
|
|
!insertmacro MoveFolder "$RootDir\conf" "$APPDATA\Salt Project\Salt\conf" "*.*"
|
|
${EndIf}
|
|
${If} ${FileExists} "$RootDir\srv\*.*"
|
|
${LogMsg} "Moving $RootDir\srv to $APPDATA"
|
|
!insertmacro MoveFolder "$RootDir\srv" "$APPDATA\Salt Project\Salt\srv" "*.*"
|
|
${EndIf}
|
|
${If} ${FileExists} "$RootDir\var\*.*"
|
|
${LogMsg} "Moving $RootDir\var to $APPDATA"
|
|
!insertmacro MoveFolder "$RootDir\var" "$APPDATA\Salt Project\Salt\var" "*.*"
|
|
${EndIf}
|
|
# Make RootDir the new location
|
|
StrCpy $RootDir "$APPDATA\Salt Project\Salt"
|
|
${EndIf}
|
|
|
|
${If} $ConfigType != "Existing Config"
|
|
Call BackupExistingConfig
|
|
${EndIf}
|
|
|
|
# Install files to the Installation Directory
|
|
${LogMsg} "Setting outpath to $INSTDIR"
|
|
SetOutPath "$INSTDIR\"
|
|
${LogMsg} "Setting Overwrite off"
|
|
SetOverwrite off
|
|
${LogMsg} "Copying files"
|
|
File /r "..\..\buildenv\"
|
|
|
|
# Set up Root Directory
|
|
${LogMsg} "Creating directory structure"
|
|
CreateDirectory "$RootDir\conf\pki\minion"
|
|
CreateDirectory "$RootDir\conf\minion.d"
|
|
CreateDirectory "$RootDir\var\cache\salt\minion\extmods\grains"
|
|
CreateDirectory "$RootDir\var\cache\salt\minion\proc"
|
|
CreateDirectory "$RootDir\var\log\salt"
|
|
CreateDirectory "$RootDir\var\run"
|
|
|
|
${LogMsg} "Setting permissions on RootDir"
|
|
nsExec::ExecToStack 'icacls "$RootDir" /inheritance:r /grant:r "*S-1-5-32-544":(OI)(CI)F /grant:r "*S-1-5-18":(OI)(CI)F'
|
|
pop $0 # ExitCode
|
|
pop $1 # StdOut
|
|
${If} $0 == 0
|
|
${LogMsg} "Success"
|
|
${Else}
|
|
${LogMsg} "Failed$\r$\nExitCode: $0$\r$\nStdOut: $1"
|
|
${EndIf}
|
|
|
|
SectionEnd
|
|
|
|
|
|
Function .onInit
|
|
# This function gets executed before any other. This is where we will
|
|
# detect existing installations and config to be used by the installer
|
|
|
|
${LogMsg} "Running ${OUTFILE}"
|
|
|
|
# Make sure we do not allow 32-bit Salt on 64-bit systems
|
|
# This is the system the installer is running on
|
|
${If} ${RunningX64}
|
|
# This is the Python architecture the installer was built with
|
|
${If} ${CPUARCH} == "x86"
|
|
StrCpy $msg "Detected 64-bit Operating system.$\n\
|
|
Please install the 64-bit version of Salt on this operating system."
|
|
${LogMsg} $msg
|
|
MessageBox MB_OK|MB_ICONEXCLAMATION $msg /SD IDOK
|
|
${LogMsg} "Aborting"
|
|
Abort
|
|
${EndIf}
|
|
${Else}
|
|
# This is the Python architecture the installer was built with
|
|
${If} ${CPUARCH} == "AMD64"
|
|
StrCpy $msg "Detected 32-bit Operating system.$\n\
|
|
Please install the 32-bit version of Salt on this operating system."
|
|
${LogMsg} $msg
|
|
MessageBox MB_OK|MB_ICONEXCLAMATION $msg /SD IDOK
|
|
${LogMsg} "Aborting"
|
|
Abort
|
|
${EndIf}
|
|
${EndIf}
|
|
|
|
InitPluginsDir
|
|
Call parseInstallerCommandLineSwitches
|
|
|
|
# Uninstall msi-installed salt
|
|
# Source: https://nsis-dev.github.io/NSIS-Forums/html/t-303468.html
|
|
!define upgradecode {FC6FB3A2-65DE-41A9-AD91-D10A402BD641} # Salt upgrade code
|
|
StrCpy $0 0
|
|
${LogMsg} "Looking for MSI installation"
|
|
loop:
|
|
System::Call 'MSI::MsiEnumRelatedProducts(t "${upgradecode}",i0,i r0,t.r1)i.r2'
|
|
${If} $2 = 0
|
|
# Now $1 contains the product code
|
|
${LogMsg} product:$1
|
|
push $R0
|
|
StrCpy $R0 $1
|
|
Call UninstallMSI
|
|
pop $R0
|
|
IntOp $0 $0 + 1
|
|
goto loop
|
|
${Endif}
|
|
|
|
# If a custom config is passed on the CLI, verify its existence before
|
|
# continuing so we don't uninstall an existing installation and then fail
|
|
# NOTE: This handles custom config for silent installations where the
|
|
# NOTE: custom config is passed on the CLI. The GUI has its own checking
|
|
# NOTE: when the user selects a custom config.
|
|
${If} $ConfigType == "Custom Config"
|
|
${LogMsg} "Verifying custom config"
|
|
${If} ${FileExists} "$CustomConfig"
|
|
${LogMsg} "Found full path to custom config: $CustomConfig"
|
|
Goto checkExistingInstallation
|
|
${EndIf}
|
|
${If} ${FileExists} "$EXEDIR\$CustomConfig"
|
|
${LogMsg} "Found custom config with the install binary: $CustomConfig"
|
|
Goto checkExistingInstallation
|
|
${EndIf}
|
|
${LogMsg} "Custom config not found. Aborting"
|
|
Abort
|
|
${EndIf}
|
|
|
|
checkExistingInstallation:
|
|
# Check for existing installation
|
|
${LogMsg} "Checking for existing installation"
|
|
|
|
# The NSIS installer is a 32bit application and will use the WOW6432Node
|
|
# in the registry by default. We need to look in the 64 bit location on
|
|
# 64 bit systems
|
|
${If} ${RunningX64}
|
|
|
|
${LogMsg} "Setting registry context to 64-bit"
|
|
# https://nsis.sourceforge.io/Docs/Chapter4.html#setregview
|
|
SetRegView 64 # View the 64 bit portion of the registry
|
|
|
|
${LogMsg} "Reading uninstall string"
|
|
ReadRegStr $R0 HKLM \
|
|
"Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
|
|
"UninstallString"
|
|
|
|
# Puts the nullsoft installer back to its default
|
|
${LogMsg} "Setting registry context to 32-bit"
|
|
SetRegView 32 # Set it back to the 32 bit portion of the registry
|
|
|
|
${Else}
|
|
|
|
${LogMsg} "Reading uninstall string"
|
|
ReadRegStr $R0 HKLM \
|
|
"Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
|
|
"UninstallString"
|
|
|
|
${EndIf}
|
|
|
|
# If it's empty it's not installed
|
|
StrCmp $R0 "" skipUninstall
|
|
|
|
# Set InstDir to the parent directory so that we can uninstall it
|
|
${GetParent} $R0 $INSTDIR
|
|
|
|
${LogMsg} "Found existing installation at $R0"
|
|
|
|
# Found existing installation, prompt to uninstall
|
|
StrCpy $msg "${PRODUCT_NAME} is already installed.$\n\
|
|
Click `OK` to remove the existing installation."
|
|
${LogMsg} $msg
|
|
MessageBox MB_OKCANCEL|MB_USERICON $msg /SD IDOK IDOK uninst
|
|
${LogMsg} "Aborting"
|
|
Abort
|
|
|
|
uninst:
|
|
|
|
# Get current Silent status
|
|
${LogMsg} "Getting current silent setting"
|
|
StrCpy $R0 0
|
|
${If} ${Silent}
|
|
StrCpy $R0 1
|
|
${EndIf}
|
|
|
|
# Turn on Silent mode
|
|
${LogMsg} "Setting to silent mode"
|
|
SetSilent silent
|
|
|
|
# Don't remove all directories when upgrading (old method)
|
|
${LogMsg} "Setting uninstaller to not delete the install dir"
|
|
StrCpy $DeleteInstallDir 0
|
|
|
|
# Don't remove RootDir when upgrading (new method)
|
|
${LogMsg} "Setting uninstaller to not delete the root dir"
|
|
StrCpy $DeleteRootDir 0
|
|
|
|
# Uninstall silently
|
|
Call uninstallSalt
|
|
|
|
${LogMsg} "Resetting silent setting to original"
|
|
# Set it back to Normal mode, if that's what it was before
|
|
${If} $R0 == 0
|
|
SetSilent normal
|
|
${EndIf}
|
|
|
|
skipUninstall:
|
|
|
|
Call getExistingInstallation
|
|
|
|
Call getExistingMinionConfig
|
|
|
|
${If} $ExistingConfigFound == 0
|
|
${AndIf} $ConfigType == "Existing Config"
|
|
${LogMsg} "Existing config not found, using Default config"
|
|
StrCpy $ConfigType "Default Config"
|
|
${EndIf}
|
|
|
|
FunctionEnd
|
|
|
|
|
|
Function BackupExistingConfig
|
|
|
|
${If} $ExistingConfigFound == 1 # If existing config found
|
|
${AndIfNot} $ConfigType == "Existing Config" # If not using Existing Config
|
|
|
|
# Backup the minion config
|
|
${If} ${FileExists} "$RootDir\conf\minion"
|
|
${LogMsg} "Renaming existing config file"
|
|
Rename "$RootDir\conf\minion" "$RootDir\conf\minion-$TimeStamp.bak"
|
|
${EndIf}
|
|
|
|
${If} ${FileExists} "$RootDir\conf\minion.d\*.*"
|
|
${LogMsg} "Renaming existing config directory"
|
|
Rename "$RootDir\conf\minion.d" "$RootDir\conf\minion.d-$TimeStamp.bak"
|
|
${EndIf}
|
|
|
|
${EndIf}
|
|
|
|
# By this point there should be no existing config. It was either backed up
|
|
# or wasn't there to begin with
|
|
${If} $ConfigType == "Custom Config" # If we're using Custom Config
|
|
${AndIfNot} $CustomConfig == "" # If a custom config is passed
|
|
|
|
# Check for a file name
|
|
# Named file should be in the same directory as the installer
|
|
${LogMsg} "Make sure config directory is exists"
|
|
${LogMsg} "Path: $RootDir\conf"
|
|
CreateDirectory "$RootDir\conf"
|
|
|
|
${If} ${FileExists} "$EXEDIR\$CustomConfig"
|
|
${LogMsg} "Copying custom config from path relative to installer"
|
|
${LogMsg} "Path: $EXEDIR\$CustomConfig"
|
|
CopyFiles /SILENT /FILESONLY "$EXEDIR\$CustomConfig" "$RootDir\conf\minion"
|
|
${ElseIf} ${FileExists} "$CustomConfig"
|
|
${LogMsg} "Copying custom config from full path"
|
|
${LogMsg} "Path: $CustomConfig"
|
|
CopyFiles /SILENT /FILESONLY "$CustomConfig" "$RootDir\conf\minion"
|
|
${Else}
|
|
${LogMsg} "Custom config not found, default values will be used"
|
|
${EndIf}
|
|
|
|
${EndIf}
|
|
|
|
FunctionEnd
|
|
|
|
|
|
Section -Post
|
|
|
|
${LogMsg} "Writing uninstaller"
|
|
WriteUninstaller "$INSTDIR\uninst.exe"
|
|
|
|
# The NSIS installer is a 32bit application and will use the WOW6432Node in
|
|
# the registry by default. We need to look in the 64 bit location on 64 bit
|
|
# systems
|
|
${If} ${RunningX64}
|
|
# https://nsis.sourceforge.io/Docs/Chapter4.html#setregview
|
|
${LogMsg} "Setting registry context to 64-bit registry"
|
|
SetRegView 64 # View 64 bit portion of the registry
|
|
${EndIf}
|
|
|
|
${LogMsg} "Updating installation information in the registry"
|
|
# Write Uninstall Registry Entries
|
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" \
|
|
"DisplayName" "$(^Name)"
|
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" \
|
|
"UninstallString" "$INSTDIR\uninst.exe"
|
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" \
|
|
"DisplayIcon" "$INSTDIR\salt.ico"
|
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" \
|
|
"DisplayVersion" "${PRODUCT_VERSION}"
|
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" \
|
|
"URLInfoAbout" "${PRODUCT_WEB_SITE}"
|
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" \
|
|
"Publisher" "${PRODUCT_PUBLISHER}"
|
|
WriteRegStr HKLM "SYSTEM\CurrentControlSet\services\salt-minion" \
|
|
"DependOnService" "nsi"
|
|
|
|
${LogMsg} "Getting estimated size"
|
|
# If ESTIMATED_SIZE is not set, calculated it
|
|
${If} ${ESTIMATED_SIZE} == 0
|
|
${GetSize} "$INSTDIR" "/S=OK" $R0 $R1 $R2
|
|
${Else}
|
|
StrCpy $R0 ${ESTIMATED_SIZE}
|
|
${Endif}
|
|
IntFmt $R0 "0x%08X" $R0
|
|
${LogMsg} "Setting estimated size: $R0"
|
|
WriteRegDWORD ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" \
|
|
"EstimatedSize" "$R0"
|
|
|
|
# Write Commandline Registry Entries
|
|
${LogMsg} "Registering salt commands for the cli"
|
|
WriteRegStr HKLM "${PRODUCT_CALL_REGKEY}" "" "$INSTDIR\salt-call.exe"
|
|
WriteRegStr HKLM "${PRODUCT_CALL_REGKEY}" "Path" "$INSTDIR\"
|
|
WriteRegStr HKLM "${PRODUCT_MINION_REGKEY}" "" "$INSTDIR\salt-minion.exe"
|
|
WriteRegStr HKLM "${PRODUCT_MINION_REGKEY}" "Path" "$INSTDIR\"
|
|
|
|
# Write Salt Configuration Registry Entries
|
|
# We want to write EXPAND_SZ string types to allow us to use environment
|
|
# variables. It's OK to use EXPAND_SZ even if you don't use an environment
|
|
# variable so we'll just do that whether it's new location or old.
|
|
|
|
# Check for Program Files
|
|
# We want to use the environment variables instead of the hardcoded path
|
|
# when setting values in the registry
|
|
${LogMsg} "Getting registry values for install_dir and root_dir"
|
|
${If} ${RunningX64}
|
|
${StrRep} "$RegInstDir" "$INSTDIR" "$ProgramFiles64" "%PROGRAMFILES%"
|
|
${Else}
|
|
${StrRep} "$RegInstDir" "$INSTDIR" "$ProgramFiles" "%PROGRAMFILES%"
|
|
${EndIf}
|
|
${LogMsg} "install_dir: $RegInstDir"
|
|
SetShellVarContext all
|
|
${StrRep} "$RegRootDir" "$RootDir" "$APPDATA" "%PROGRAMDATA%"
|
|
${LogMsg} "root_dir: $RegRootDir"
|
|
|
|
${LogMsg} "Writing install_dir and root_dir to the registry"
|
|
WriteRegExpandStr HKLM "SOFTWARE\Salt Project\Salt" "install_dir" "$RegInstDir"
|
|
WriteRegExpandStr HKLM "SOFTWARE\Salt Project\Salt" "root_dir" "$RegRootDir"
|
|
|
|
# Puts the nullsoft installer back to its default
|
|
${LogMsg} "Setting registry context back to 32-bit"
|
|
SetRegView 32 # Set it back to the 32 bit portion of the registry
|
|
|
|
# Register the Salt-Minion Service
|
|
${LogMsg} "Registering the salt-minion service"
|
|
nsExec::ExecToStack `"$INSTDIR\ssm.exe" install salt-minion "$INSTDIR\salt-minion.exe" -c """$RootDir\conf""" -l quiet`
|
|
pop $0 # ExitCode
|
|
pop $1 # StdOut
|
|
${IfNot} $0 == 0
|
|
StrCpy $msg "Failed to register the salt minion service.$\n\
|
|
ExitCode: $0$\n\
|
|
StdOut: $1"
|
|
${LogMsg} $msg
|
|
MessageBox MB_OK|MB_ICONEXCLAMATION $msg /SD IDOK IDOK
|
|
${LogMsg} "Aborting"
|
|
Abort
|
|
${Else}
|
|
${LogMsg} "Setting service description"
|
|
nsExec::ExecToStack "$INSTDIR\ssm.exe set salt-minion Description Salt Minion from saltstack.com"
|
|
pop $0 # ExitCode
|
|
pop $1 # StdOut
|
|
${If} $0 == 0
|
|
${LogMsg} "Success"
|
|
${Else}
|
|
${LogMsg} "Failed$\r$\nExitCode: $0$\r$\nStdOut: $1"
|
|
${EndIf}
|
|
${LogMsg} "Setting service autostart"
|
|
nsExec::ExecToStack "$INSTDIR\ssm.exe set salt-minion Start SERVICE_AUTO_START"
|
|
pop $0 # ExitCode
|
|
pop $1 # StdOut
|
|
${If} $0 == 0
|
|
${LogMsg} "Success"
|
|
${Else}
|
|
${LogMsg} "Failed$\r$\nExitCode: $0$\r$\nStdOut: $1"
|
|
${EndIf}
|
|
${LogMsg} "Setting service console stop method"
|
|
nsExec::ExecToStack "$INSTDIR\ssm.exe set salt-minion AppStopMethodConsole 24000"
|
|
pop $0 # ExitCode
|
|
pop $1 # StdOut
|
|
${If} $0 == 0
|
|
${LogMsg} "Success"
|
|
${Else}
|
|
${LogMsg} "Failed$\r$\nExitCode: $0$\r$\nStdOut: $1"
|
|
${EndIf}
|
|
${LogMsg} "Setting service windows stop method"
|
|
nsExec::ExecToStack "$INSTDIR\ssm.exe set salt-minion AppStopMethodWindow 2000"
|
|
pop $0 # ExitCode
|
|
pop $1 # StdOut
|
|
${If} $0 == 0
|
|
${LogMsg} "Success"
|
|
${Else}
|
|
${LogMsg} "Failed$\r$\nExitCode: $0$\r$\nStdOut: $1"
|
|
${EndIf}
|
|
${LogMsg} "Setting service app restart delay"
|
|
nsExec::ExecToStack "$INSTDIR\ssm.exe set salt-minion AppRestartDelay 60000"
|
|
pop $0 # ExitCode
|
|
pop $1 # StdOut
|
|
${If} $0 == 0
|
|
${LogMsg} "Success"
|
|
${Else}
|
|
${LogMsg} "Failed$\r$\nExitCode: $0$\r$\nStdOut: $1"
|
|
${EndIf}
|
|
${EndIf}
|
|
|
|
# There is a default minion config laid down in the $INSTDIR directory
|
|
${Switch} $ConfigType
|
|
${Case} "Existing Config"
|
|
${LogMsg} "Using existing config"
|
|
# If this is an Existing Config, we don't do anything
|
|
${Break}
|
|
${Case} "Custom Config"
|
|
${LogMsg} "Using custom config"
|
|
# If this is a Custom Config, update the custom config
|
|
Call updateMinionConfig
|
|
${Break}
|
|
${Case} "Default Config"
|
|
${LogMsg} "Using default config"
|
|
# If this is the Default Config, we move it and update it
|
|
StrCpy $switch_overwrite 1
|
|
!insertmacro MoveFolder "$INSTDIR\configs" "$RootDir\conf" "*.*"
|
|
Call updateMinionConfig
|
|
${Break}
|
|
${EndSwitch}
|
|
|
|
# Delete the configs directory that came with the installer
|
|
${LogMsg} "Removing configs directory"
|
|
RMDir /r "$INSTDIR\configs"
|
|
|
|
# Add $INSTDIR in the Path
|
|
${LogMsg} "Adding salt to the path"
|
|
EnVar::SetHKLM
|
|
EnVar::AddValue Path "$INSTDIR"
|
|
Pop $0
|
|
${If} $0 == 0
|
|
${LogMsg} "Success"
|
|
${Else}
|
|
# See this table for Error Codes:
|
|
# https://github.com/GsNSIS/EnVar#error-codes
|
|
${LogMsg} "Failed. Error Code: $0"
|
|
${EndIf}
|
|
|
|
SectionEnd
|
|
|
|
|
|
Function .onInstSuccess
|
|
|
|
# If StartMinionDelayed is 1, then set the service to start delayed
|
|
${If} $StartMinionDelayed == 1
|
|
${LogMsg} "Setting the salt-minion service to start delayed"
|
|
nsExec::ExecToStack "$INSTDIR\ssm.exe set salt-minion Start SERVICE_DELAYED_AUTO_START"
|
|
pop $0 # ExitCode
|
|
pop $1 # StdOut
|
|
${If} $0 == 0
|
|
${LogMsg} "Success"
|
|
${Else}
|
|
${LogMsg} "Failed$\r$\nExitCode: $0$\r$\nStdOut: $1"
|
|
${EndIf}
|
|
${EndIf}
|
|
|
|
# If start-minion is 1, then start the service
|
|
${If} $StartMinion == 1
|
|
${LogMsg} "Starting the salt-minion service"
|
|
nsExec::ExecToStack "$INSTDIR\ssm.exe start salt-minion"
|
|
pop $0 # ExitCode
|
|
pop $1 # StdOut
|
|
${If} $0 == 0
|
|
${LogMsg} "Success"
|
|
${Else}
|
|
${LogMsg} "Failed$\r$\nExitCode: $0$\r$\nStdOut: $1"
|
|
${EndIf}
|
|
${EndIf}
|
|
|
|
${LogMsg} "Salt installation complete"
|
|
|
|
# I don't know of another way to fix this. The installer hangs intermittently
|
|
# This will force kill the installer process. This must be the last thing that
|
|
# is run.
|
|
StrCpy $1 "wmic Path win32_process where $\"name like '$EXEFILE'$\" Call Terminate"
|
|
nsExec::Exec $1
|
|
|
|
FunctionEnd
|
|
|
|
|
|
Function un.onInit
|
|
|
|
Call un.parseUninstallerCommandLineSwitches
|
|
|
|
StrCpy $msg "Are you sure you want to completely remove $(^Name) and all \
|
|
of its components?"
|
|
${LogMsg} $msg
|
|
MessageBox MB_USERICON|MB_YESNO|MB_DEFBUTTON1 $msg /SD IDYES IDYES continue_remove
|
|
${LogMsg} "Aborting"
|
|
Abort
|
|
|
|
continue_remove:
|
|
|
|
FunctionEnd
|
|
|
|
|
|
Section Uninstall
|
|
|
|
Call un.uninstallSalt
|
|
|
|
# Remove $INSTDIR from the Path
|
|
${LogMsg} "Removing salt from the path"
|
|
EnVar::SetHKLM
|
|
EnVar::DeleteValue Path "$INSTDIR"
|
|
Pop $0
|
|
${If} $0 == 0
|
|
${LogMsg} "Success"
|
|
${Else}
|
|
# See this table for Error Codes:
|
|
# https://github.com/GsNSIS/EnVar#error-codes
|
|
${LogMsg} "Failed. Error Code: $0"
|
|
${EndIf}
|
|
|
|
SectionEnd
|
|
|
|
|
|
!macro uninstallSalt un
|
|
Function ${un}uninstallSalt
|
|
|
|
# WARNING: Any changes made here need to be reflected in the MSI uninstaller
|
|
# Make sure we're in the right directory
|
|
${LogMsg} "Detecting INSTDIR"
|
|
${If} $INSTDIR == "c:\salt\Scripts"
|
|
StrCpy $INSTDIR "C:\salt"
|
|
${EndIf}
|
|
# $ProgramFiles is different depending on the CPU Architecture
|
|
# https://nsis.sourceforge.io/Reference/$PROGRAMFILES
|
|
# x86 : C:\Program Files
|
|
# x64 : C:\Program Files (x86)
|
|
${If} $INSTDIR == "$ProgramFiles\Salt Project\Salt\Scripts"
|
|
StrCpy $INSTDIR "$ProgramFiles\Salt Project\Salt"
|
|
${EndIf}
|
|
# $ProgramFiles64 is the C:\Program Files directory
|
|
${If} $INSTDIR == "$ProgramFiles64\Salt Project\Salt\Scripts"
|
|
StrCpy $INSTDIR "$ProgramFiles64\Salt Project\Salt"
|
|
${EndIf}
|
|
${LogMsg} "INSTDIR: $INSTDIR"
|
|
|
|
# Only attempt to remove the services if ssm.exe is present"
|
|
${If} ${FileExists} "$INSTDIR\ssm.exe"
|
|
|
|
${LogMsg} "ssm.exe found"
|
|
|
|
# Stop and Remove salt-minion service
|
|
${LogMsg} "Stopping salt-minion service"
|
|
nsExec::ExecToStack "$INSTDIR\ssm.exe stop salt-minion"
|
|
pop $0 # ExitCode
|
|
pop $1 # StdOut
|
|
${If} $0 == 0
|
|
${LogMsg} "Success"
|
|
${Else}
|
|
${LogMsg} "Failed$\r$\nExitCode: $0$\r$\nStdOut: $1"
|
|
${EndIf}
|
|
|
|
${LogMsg} "Removing salt-minion service"
|
|
nsExec::ExecToStack "$INSTDIR\ssm.exe remove salt-minion confirm"
|
|
pop $0 # ExitCode
|
|
pop $1 # StdOut
|
|
${If} $0 == 0
|
|
${LogMsg} "Success"
|
|
${Else}
|
|
${LogMsg} "Failed$\r$\nExitCode: $0$\r$\nStdOut: $1"
|
|
Abort
|
|
${EndIf}
|
|
|
|
${Else}
|
|
|
|
${LogMsg} "ssm.exe not found"
|
|
|
|
${EndIf}
|
|
|
|
# Remove files
|
|
${LogMsg} "Deleting individual files"
|
|
Delete "$INSTDIR\multi-minion*"
|
|
Delete "$INSTDIR\salt*"
|
|
Delete "$INSTDIR\ssm.exe"
|
|
Delete "$INSTDIR\uninst.exe"
|
|
Delete "$INSTDIR\vcredist.exe"
|
|
${LogMsg} "Deleting directories"
|
|
RMDir /r "$INSTDIR\DLLs"
|
|
RMDir /r "$INSTDIR\Include"
|
|
RMDir /r "$INSTDIR\Lib"
|
|
RMDir /r "$INSTDIR\libs"
|
|
RMDir /r "$INSTDIR\Scripts"
|
|
|
|
# Remove everything in the 64 bit registry
|
|
|
|
# The NSIS installer is a 32bit application and will use the WOW6432Node in
|
|
# the registry by default. We need to look in the 64 bit location on 64 bit
|
|
# systems
|
|
${If} ${RunningX64}
|
|
|
|
${LogMsg} "Removing 64-bit registry items"
|
|
# https://nsis.sourceforge.io/Docs/Chapter4.html#setregview
|
|
SetRegView 64 # View the 64 bit portion of the registry
|
|
|
|
${EndIf}
|
|
|
|
${LogMsg} "Getting RootDir from 64-bit registry"
|
|
# Get Root Directory from the Registry (64 bit)
|
|
ReadRegStr $RootDir HKLM "SOFTWARE\Salt Project\Salt" "root_dir"
|
|
${LogMsg} "RootDir: $RootDir"
|
|
|
|
# Remove Registry entries
|
|
${LogMsg} "Deleting Add/Remove programs entries"
|
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
|
|
|
|
# Remove Command Line Registry entries
|
|
${LogMsg} "Deleting Command Line Registry Entries"
|
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_CALL_REGKEY}"
|
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_CP_REGKEY}"
|
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_KEY_REGKEY}"
|
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_MASTER_REGKEY}"
|
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_MINION_REGKEY}"
|
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_RUN_REGKEY}"
|
|
DeleteRegKey HKLM "SOFTWARE\Salt Project"
|
|
|
|
# SystemDrive is not a built in NSIS constant, so we need to get it from
|
|
# the environment variables
|
|
${LogMsg} "Getting System Drive"
|
|
ReadEnvStr $0 "SystemDrive" # Get the SystemDrive env var
|
|
StrCpy $SysDrive "$0\"
|
|
${LogMsg} "SystemDrive: $SysDrive"
|
|
|
|
# Automatically close when finished
|
|
SetAutoClose true
|
|
|
|
# Old Method Installation
|
|
${If} $INSTDIR == "C:\salt"
|
|
|
|
# Prompt to remove the Installation Directory. This is because that
|
|
# directory is also the root_dir which includes the config and pki
|
|
# directories
|
|
${IfNot} $DeleteInstallDir == 1
|
|
StrCpy $msg "Would you like to completely remove $INSTDIR and all \
|
|
of its contents?"
|
|
${LogMsg} $msg
|
|
MessageBox MB_YESNO|MB_DEFBUTTON2|MB_USERICON $msg /SD IDNO IDNO finished
|
|
${EndIf}
|
|
|
|
${LogMsg} "Removing INSTDIR"
|
|
SetOutPath "$SysDrive" # Can't remove CWD
|
|
RMDir /r "$INSTDIR"
|
|
|
|
${Else}
|
|
|
|
# Prompt for the removal of the Installation Directory which contains
|
|
# the extras directory and the Root Directory which contains the config
|
|
# and pki directories. These directories will not be removed during
|
|
# an upgrade.
|
|
${IfNot} $DeleteRootDir == 1
|
|
StrCpy $msg "Would you like to completely remove the entire Salt \
|
|
Installation? This includes the following:$\n\
|
|
- Extra Pip Packages ($INSTDIR\extras-3.##)$\n\
|
|
- Minion Config ($RootDir\conf)$\n\
|
|
- Minion PKIs ($RootDir\conf\pki)"
|
|
${LogMsg} $msg
|
|
MessageBox MB_YESNO|MB_DEFBUTTON2|MB_USERICON $msg /SD IDNO IDNO finished
|
|
${EndIf}
|
|
|
|
# New Method Installation
|
|
# This makes the $APPDATA variable point to the ProgramData folder instead
|
|
# of the current user's roaming AppData folder
|
|
${LogMsg} "Setting Shell Context to All Users"
|
|
SetShellVarContext all
|
|
|
|
# We can always remove the Installation Directory on New Method Installs
|
|
# because it only contains binary data
|
|
|
|
# Remove INSTDIR
|
|
# Make sure you're not removing important system directory such as
|
|
# Program Files, C:\Windows, or C:
|
|
${If} $INSTDIR != $ProgramFiles
|
|
${AndIf} $INSTDIR != $ProgramFiles64
|
|
${AndIf} $INSTDIR != $SysDrive
|
|
${AndIf} $INSTDIR != $WinDir
|
|
${LogMsg} "Removing INSTDIR"
|
|
SetOutPath "$SysDrive" # Can't remove CWD
|
|
RMDir /r $INSTDIR
|
|
${EndIf}
|
|
|
|
# Remove INSTDIR (The parent)
|
|
# For example, though salt is installed in ProgramFiles\Salt Project\Salt
|
|
# We want to remove ProgramFiles\Salt Project
|
|
# Only delete Salt Project directory if it's in Program Files
|
|
# Otherwise, we can't guess where the user may have installed salt
|
|
${LogMsg} "Getting InstDir Parent Directory"
|
|
${GetParent} $INSTDIR $R0 # Get parent directory (Salt Project)
|
|
${LogMsg} "Parent: $R0"
|
|
${If} $R0 == "$ProgramFiles\Salt Project" # Make sure it's ProgramFiles
|
|
${OrIf} $R0 == "$ProgramFiles64\Salt Project" # Make sure it's Program Files (x86)
|
|
${LogMsg} "Removing Salt Project directory from Program Files"
|
|
SetOutPath "$SysDrive" # Can't remove CWD
|
|
RMDir /r $R0
|
|
${EndIf}
|
|
|
|
# If RootDir is still empty, use C:\salt
|
|
${If} $RootDir == ""
|
|
StrCpy $RootDir "C:\salt"
|
|
${EndIf}
|
|
|
|
# Expand any environment variables
|
|
ExpandEnvStrings $RootDir $RootDir
|
|
|
|
${LogMsg} "Removing RootDir: $RootDir"
|
|
|
|
# Remove the Salt Project directory in ProgramData
|
|
# The Salt Project directory will only ever be in ProgramData
|
|
# It is not user selectable
|
|
${LogMsg} "Getting RootDir Parent Directory"
|
|
${GetParent} $RootDir $R0 # Get parent directory
|
|
${LogMsg} "Parent: $R0"
|
|
${If} $R0 == "$APPDATA\Salt Project" # Make sure it's not ProgramData
|
|
${LogMsg} "Removing Parent Directory from APPDATA"
|
|
SetOutPath "$SysDrive" # Can't remove CWD
|
|
RMDir /r $R0
|
|
${EndIf}
|
|
|
|
${EndIf}
|
|
|
|
finished:
|
|
${LogMsg} "Uninstall Complete"
|
|
|
|
FunctionEnd
|
|
!macroend
|
|
!insertmacro uninstallSalt ""
|
|
!insertmacro uninstallSalt "un."
|
|
|
|
|
|
Function un.onUninstSuccess
|
|
|
|
HideWindow
|
|
|
|
StrCpy $msg "$(^Name) was successfully removed from your computer."
|
|
${LogMsg} $msg
|
|
MessageBox MB_OK|MB_USERICON $msg /SD IDOK
|
|
|
|
# I don't know of another way to fix this. The installer hangs intermittently
|
|
# This will force kill the installer process. This must be the last thing that
|
|
# is run.
|
|
StrCpy $1 "wmic Path win32_process where $\"name like '$EXEFILE'$\" Call Terminate"
|
|
nsExec::Exec $1
|
|
|
|
FunctionEnd
|
|
|
|
|
|
###############################################################################
|
|
# Helper Functions
|
|
###############################################################################
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Trim Function
|
|
# - Trim whitespace from the beginning and end of a string
|
|
# - Trims spaces, \r, \n, \t
|
|
#
|
|
# Usage:
|
|
# Push " some string " ; String to Trim
|
|
# Call Trim
|
|
# Pop $0 ; Trimmed String: "some string"
|
|
#
|
|
# or
|
|
#
|
|
# ${Trim} $0 $1 ; Trimmed String, String to Trim
|
|
#------------------------------------------------------------------------------
|
|
!macro Func_Trim un
|
|
Function ${un}Trim
|
|
|
|
Exch $R1 # Original string
|
|
Push $R2
|
|
|
|
Loop:
|
|
StrCpy $R2 "$R1" 1
|
|
StrCmp "$R2" " " TrimLeft
|
|
StrCmp "$R2" "$\r" TrimLeft
|
|
StrCmp "$R2" "$\n" TrimLeft
|
|
StrCmp "$R2" "$\t" TrimLeft
|
|
GoTo Loop2
|
|
TrimLeft:
|
|
StrCpy $R1 "$R1" "" 1
|
|
Goto Loop
|
|
|
|
Loop2:
|
|
StrCpy $R2 "$R1" 1 -1
|
|
StrCmp "$R2" " " TrimRight
|
|
StrCmp "$R2" "$\r" TrimRight
|
|
StrCmp "$R2" "$\n" TrimRight
|
|
StrCmp "$R2" "$\t" TrimRight
|
|
GoTo Done
|
|
TrimRight:
|
|
StrCpy $R1 "$R1" -1
|
|
Goto Loop2
|
|
|
|
Done:
|
|
Pop $R2
|
|
Exch $R1
|
|
|
|
FunctionEnd
|
|
!macroend
|
|
!insertmacro Func_Trim ""
|
|
!insertmacro Func_Trim "un."
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Explode Function
|
|
# - Splits a string based off the passed separator
|
|
# - Each item in the string is pushed to the stack
|
|
# - The last item pushed to the stack is the length of the array
|
|
#
|
|
# Usage:
|
|
# Push "," ; Separator
|
|
# Push "string,to,separate" ; String to explode
|
|
# Call Explode
|
|
# Pop $0 ; Number of items in the array
|
|
#
|
|
# or
|
|
#
|
|
# ${Explode} $0 $1 $2 ; Length, Separator, String
|
|
#------------------------------------------------------------------------------
|
|
Function Explode
|
|
# Initialize variables
|
|
Var /GLOBAL explString
|
|
Var /GLOBAL explSeparator
|
|
Var /GLOBAL explStrLen
|
|
Var /GLOBAL explSepLen
|
|
Var /GLOBAL explOffset
|
|
Var /GLOBAL explTmp
|
|
Var /GLOBAL explTmp2
|
|
Var /GLOBAL explTmp3
|
|
Var /GLOBAL explArrCount
|
|
|
|
# Get input from user
|
|
Pop $explString
|
|
Pop $explSeparator
|
|
|
|
# Calculates initial values
|
|
StrLen $explStrLen $explString
|
|
StrLen $explSepLen $explSeparator
|
|
StrCpy $explArrCount 1
|
|
|
|
${If} $explStrLen <= 1 # If we got a single character
|
|
${OrIf} $explSepLen > $explStrLen # or separator is larger than the string,
|
|
Push $explString # then we return initial string with no change
|
|
Push 1 # and set array's length to 1
|
|
Return
|
|
${EndIf}
|
|
|
|
# Set offset to the last symbol of the string
|
|
StrCpy $explOffset $explStrLen
|
|
IntOp $explOffset $explOffset - 1
|
|
|
|
# Clear temp string to exclude the possibility of appearance of occasional data
|
|
StrCpy $explTmp ""
|
|
StrCpy $explTmp2 ""
|
|
StrCpy $explTmp3 ""
|
|
|
|
# Loop until the offset becomes negative
|
|
${Do}
|
|
# If offset becomes negative, it is time to leave the function
|
|
${IfThen} $explOffset == -1 ${|} ${ExitDo} ${|}
|
|
|
|
# Remove everything before and after the searched part ("TempStr")
|
|
StrCpy $explTmp $explString $explSepLen $explOffset
|
|
|
|
${If} $explTmp == $explSeparator
|
|
# Calculating offset to start copy from
|
|
IntOp $explTmp2 $explOffset + $explSepLen # Offset equals to the current offset plus length of separator
|
|
StrCpy $explTmp3 $explString "" $explTmp2
|
|
|
|
Push $explTmp3 # Throwing array item to the stack
|
|
IntOp $explArrCount $explArrCount + 1 # Increasing array's counter
|
|
|
|
StrCpy $explString $explString $explOffset 0 # Cutting all characters beginning with the separator entry
|
|
StrLen $explStrLen $explString
|
|
${EndIf}
|
|
|
|
${If} $explOffset = 0 # If the beginning of the line met and there is no separator,
|
|
# copying the rest of the string
|
|
${If} $explSeparator == "" # Fix for the empty separator
|
|
IntOp $explArrCount $explArrCount - 1
|
|
${Else}
|
|
Push $explString
|
|
${EndIf}
|
|
${EndIf}
|
|
|
|
IntOp $explOffset $explOffset - 1
|
|
${Loop}
|
|
|
|
Push $explArrCount
|
|
FunctionEnd
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
|
# UninstallMSI Function
|
|
# - Uninstalls MSI by product code
|
|
#
|
|
# Usage:
|
|
# Push product code
|
|
# Call UninstallMSI
|
|
#
|
|
# Source:
|
|
# https://nsis.sourceforge.io/Uninstalling_a_previous_MSI_(Windows_installer_package)
|
|
#------------------------------------------------------------------------------
|
|
Function UninstallMSI
|
|
; $R0 === product code
|
|
MessageBox MB_OKCANCEL|MB_ICONINFORMATION \
|
|
"${PRODUCT_NAME} is already installed via MSI.$\n$\n\
|
|
Click `OK` to remove the existing installation." \
|
|
/SD IDOK IDOK UninstallMSI
|
|
Abort
|
|
|
|
UninstallMSI:
|
|
ExecWait '"msiexec.exe" /x $R0 /qb /quiet /norestart'
|
|
|
|
FunctionEnd
|
|
|
|
|
|
###############################################################################
|
|
# Specialty Functions
|
|
###############################################################################
|
|
|
|
Function getExistingInstallation
|
|
# Try to detect an existing installation. There are three possible scenarios
|
|
# 1. Existing New Method Installation
|
|
# 2. Existing Old Method Installation
|
|
# 3. New Installation
|
|
# The results of this function will determine if the user is allowed to set
|
|
# the install location in the GUI. If there is an existing installation
|
|
# present, the location picker will be grayed out
|
|
# This function also sets the RootDir and INSTDIR variables used by the
|
|
# installer.
|
|
|
|
${LogMsg} "Detecting existing installation"
|
|
|
|
# Reset ExistingInstallation
|
|
StrCpy $ExistingInstallation 0
|
|
|
|
# Get ProgramFiles
|
|
# Use RunningX64 here to get the Architecture for the system running the
|
|
# installer.
|
|
# There are 3 scenarios here:
|
|
${LogMsg} "Setting Default InstDir"
|
|
${If} ${RunningX64}
|
|
StrCpy $INSTDIR "$ProgramFiles64\Salt Project\Salt"
|
|
${Else}
|
|
# 32 bit Salt on 32 bit system (C:\Program Files)
|
|
StrCpy $INSTDIR "$ProgramFiles\Salt Project\Salt"
|
|
${EndIf}
|
|
|
|
# This makes the $APPDATA variable point to the ProgramData folder instead
|
|
# of the current user's roaming AppData folder
|
|
SetShellVarContext all
|
|
|
|
# Set default location of for salt config
|
|
${LogMsg} "Setting Default RootDir"
|
|
StrCpy $RootDir "$APPDATA\Salt Project\Salt"
|
|
|
|
# The NSIS installer is a 32bit application and will use the WOW6432Node in
|
|
# the registry by default. We need to look in the 64 bit location on 64 bit
|
|
# systems
|
|
${If} ${RunningX64}
|
|
# https://nsis.sourceforge.io/Docs/Chapter4.html#setregview
|
|
SetRegView 64 # View the 64 bit portion of the registry
|
|
${EndIf}
|
|
|
|
# Check for existing new method installation from registry
|
|
${LogMsg} "Looking for New Method installation"
|
|
|
|
# Look for `install_dir` in HKLM\SOFTWARE\Salt Project\Salt
|
|
${LogMsg} "Getting INSTDIR from Registry"
|
|
ReadRegStr $R0 HKLM "SOFTWARE\Salt Project\Salt" "install_dir"
|
|
StrCmp $R0 "" checkOldInstallation
|
|
|
|
${LogMsg} "Detected existing installation"
|
|
StrCpy $ExistingInstallation 1
|
|
|
|
# Set INSTDIR to the location in the registry
|
|
StrCpy $INSTDIR $R0
|
|
# Expand any environment variables it contains
|
|
ExpandEnvStrings $INSTDIR $INSTDIR
|
|
|
|
${LogMsg} "INSTDIR: $INSTDIR"
|
|
|
|
# Set RootDir, if defined
|
|
${LogMsg} "Getting RootDir"
|
|
ReadRegStr $R0 HKLM "SOFTWARE\Salt Project\Salt" "root_dir"
|
|
StrCmp $R0 "" finished
|
|
StrCpy $RootDir $R0
|
|
# Expand any environment variables it contains
|
|
ExpandEnvStrings $RootDir $RootDir
|
|
${LogMsg} "RootDir: $RootDir"
|
|
Goto finished
|
|
|
|
# Check for existing old method installation
|
|
# Look for `python.exe` in C:\salt\bin
|
|
checkOldInstallation:
|
|
${LogMsg} "Looking for Old Method installation"
|
|
IfFileExists "C:\salt\bin\python.exe" 0 newInstallation
|
|
StrCpy $ExistingInstallation 1
|
|
StrCpy $INSTDIR "C:\salt"
|
|
StrCpy $RootDir "C:\salt"
|
|
${LogMsg} "Found Old Method installation"
|
|
Goto finished
|
|
|
|
# This is a new installation
|
|
# Check if custom location was passed via command line
|
|
newInstallation:
|
|
${LogMsg} "This is a New Installation"
|
|
${IfNot} $CustomLocation == ""
|
|
StrCpy $INSTDIR $CustomLocation
|
|
${EndIf}
|
|
|
|
finished:
|
|
${LogMsg} "Finished detecting installation type"
|
|
SetRegView 32 # View the 32 bit portion of the registry
|
|
|
|
FunctionEnd
|
|
|
|
|
|
Function getExistingMinionConfig
|
|
|
|
${LogMsg} "Getting existing Minion Config"
|
|
|
|
# Set Config Found Default Value
|
|
StrCpy $ExistingConfigFound 0
|
|
|
|
# Find config, should be in $RootDir\conf\minion
|
|
# Root dir is usually ProgramData\Salt Project\Salt\conf though it may be
|
|
# C:\salt\conf if Salt was installed the old way
|
|
|
|
${LogMsg} "Looking for minion config in $RootDir"
|
|
IfFileExists "$RootDir\conf\minion" check_owner
|
|
${LogMsg} "Looking for minion config in C:\salt"
|
|
IfFileExists "C:\salt\conf\minion" old_location confNotFound
|
|
|
|
old_location:
|
|
${LogMsg} "Found config in old location. Updating RootDir"
|
|
StrCpy $RootDir "C:\salt"
|
|
${LogMsg} "RootDir: $RootDir"
|
|
|
|
check_owner:
|
|
# We need to verify the owner of the config directory (C:\salt\conf) to
|
|
# ensure the config has not been modified by an unknown user. The
|
|
# permissions and ownership of the directories is determined by the
|
|
# installer used to install Salt. The NullSoft installer requests Admin
|
|
# privileges so all directories are created with the Administrators
|
|
# Group (S-1-5-32-544) as the owner. The MSI installer, however, runs in
|
|
# the context of the Windows Installer service (msiserver), therefore
|
|
# all directories are created with the Local System account (S-1-5-18)
|
|
# as the owner.
|
|
#
|
|
# When Salt is launched it sets the root_dir (C:\salt) permissions as
|
|
# follows:
|
|
# - Owner: Administrators
|
|
# - Allow Perms:
|
|
# - Owner: Full Control
|
|
# - System: Full Control
|
|
# - Administrators: Full Control
|
|
#
|
|
# The conf_dir (C:\salt\conf) inherits Allow/Deny permissions from the
|
|
# parent, but NOT Ownership. The owner will be the Administrators Group
|
|
# if it was installed via NullSoft or the Local System account if it was
|
|
# installed via the MSI. Therefore valid owners for the conf_dir are
|
|
# both the Administrators group and the Local System account.
|
|
#
|
|
# An unprivileged account cannot change the owner of a directory by
|
|
# default. So, if the owner of the conf_dir is either the Administrators
|
|
# group or the Local System account, then we will trust it. Otherwise,
|
|
# we will display an option to abort the installation or to backup the
|
|
# untrusted config directory and continue with the default config. If
|
|
# running the install with the silent option (/S) it will backup the
|
|
# untrusted config directory and continue with the default config.
|
|
|
|
${LogMsg} "Validating permissions to config"
|
|
AccessControl::GetFileOwner /SID "$RootDir\conf"
|
|
Pop $0
|
|
|
|
# Check for valid SIDs
|
|
StrCmp $0 "S-1-5-32-544" correct_owner # Administrators Group (NullSoft)
|
|
StrCmp $0 "S-1-5-18" correct_owner # Local System (MSI)
|
|
StrCpy $msg "Insecure config found at $RootDir\conf. If you continue, the \
|
|
config directory will be renamed to $RootDir\conf.insecure \
|
|
and the default config will be used. Continue?"
|
|
${LogMsg} $msg
|
|
MessageBox MB_YESNO $msg /SD IDYES IDYES insecure_config
|
|
${LogMsg} "Aborting"
|
|
Abort
|
|
|
|
insecure_config:
|
|
# Backing up insecure config
|
|
${LogMsg} "Backing up insecure config"
|
|
Rename "$RootDir\conf" "$RootDir\conf.insecure-$TimeStamp"
|
|
Goto confNotFound
|
|
|
|
correct_owner:
|
|
${LogMsg} "Found existing config with correct permissions"
|
|
StrCpy $ExistingConfigFound 1
|
|
${LogMsg} "Opening minion config read-only"
|
|
ClearErrors
|
|
FileOpen $0 "$RootDir\conf\minion" r
|
|
IfErrors 0 get_config_values
|
|
${LogMsg} "There was an error opening the minion config"
|
|
${LogMsg} "Config values will not be detected"
|
|
Goto set_default_values
|
|
|
|
get_config_values:
|
|
${LogMsg} "Getting config values from existing config"
|
|
|
|
confLoop:
|
|
ClearErrors # clear Errors
|
|
FileRead $0 $1 # read the next line
|
|
IfErrors EndOfFile # error is probably EOF
|
|
${StrLoc} $2 $1 "master:" ">" # find `master:` starting at the beginning
|
|
${If} $2 == 0 # if it found it in the first position, then it is defined
|
|
${StrStrAdv} $2 $1 "master: " ">" ">" "0" "0" "0" # read everything after `master: `
|
|
${Trim} $2 $2 # trim white space
|
|
${If} $2 == "" # if it's empty, it's probably a list of masters
|
|
masterLoop:
|
|
ClearErrors # clear Errors
|
|
FileRead $0 $1 # read the next line
|
|
IfErrors EndOfFile # error is probably EOF
|
|
${StrStrAdv} $2 $1 "- " ">" ">" "0" "0" "0" # read everything after `- `
|
|
${Trim} $2 $2 # trim white space
|
|
${IfNot} $2 == "" # if the line is not empty, we found something
|
|
${If} $MasterHost_Cfg == "" # if the config setting is empty
|
|
StrCpy $MasterHost_Cfg $2 # make the first item the new entry
|
|
${Else}
|
|
StrCpy $MasterHost_Cfg "$MasterHost_Cfg,$2" # Append the new master, comma separated
|
|
${EndIf}
|
|
Goto masterLoop # check the next one
|
|
${EndIf}
|
|
${Else}
|
|
StrCpy $MasterHost_Cfg $2 # a single master entry
|
|
${EndIf}
|
|
${EndIf}
|
|
|
|
${StrLoc} $2 $1 "id:" ">"
|
|
${If} $2 == 0
|
|
${StrStrAdv} $2 $1 "id: " ">" ">" "0" "0" "0"
|
|
${Trim} $2 $2
|
|
StrCpy $MinionName_Cfg $2
|
|
${EndIf}
|
|
|
|
Goto confLoop
|
|
|
|
EndOfFile:
|
|
FileClose $0
|
|
|
|
confNotFound:
|
|
${LogMsg} "Config not found"
|
|
|
|
set_default_values:
|
|
# Set Default Config Values if not found
|
|
${If} $MasterHost_Cfg == ""
|
|
${LogMsg} "Setting master host setting to default: salt"
|
|
StrCpy $MasterHost_Cfg "salt"
|
|
${EndIf}
|
|
${If} $MinionName_Cfg == ""
|
|
${LogMsg} "Setting minion id setting to default: hostname"
|
|
StrCpy $MinionName_Cfg "hostname"
|
|
${EndIf}
|
|
|
|
FunctionEnd
|
|
|
|
|
|
Var cfg_line
|
|
Var chk_line
|
|
Var lst_check
|
|
Var tgt_file
|
|
Var tmp_file
|
|
Function updateMinionConfig
|
|
|
|
StrCpy $ConfigWriteMaster 1 # write the master config value
|
|
StrCpy $ConfigWriteMinion 1 # write the minion config value
|
|
|
|
${If} $MasterHost == "" # if master is empty
|
|
${OrIf} $MasterHost == "salt" # or if master is 'salt'
|
|
StrCpy $ConfigWriteMaster 0 # no need to write master config
|
|
${EndIf} # close if statement
|
|
${If} $MinionName == "" # if minion is empty
|
|
${OrIf} $MinionName == "hostname" # and if minion is not 'hostname'
|
|
StrCpy $ConfigWriteMinion 0 # no need to write minion config
|
|
${EndIf} # close if statement
|
|
|
|
${If} $ConfigWriteMaster == 0
|
|
${AndIf} $ConfigWriteMinion == 0
|
|
${LogMsg} "No config values to update. Config will not be updated"
|
|
Goto update_minion_config_finished
|
|
${EndIf}
|
|
|
|
${LogMsg} "Updating Minion Config"
|
|
|
|
${LogMsg} "Opening target file: $RootDir\conf\minion"
|
|
ClearErrors
|
|
FileOpen $tgt_file "$RootDir\conf\minion" r # open target file for reading
|
|
${If} ${Errors}
|
|
${LogMsg} "Target file could not be opened read-only"
|
|
${LogMsg} "Minion config will not be updated"
|
|
Goto update_minion_config_finished
|
|
${EndIf}
|
|
|
|
GetTempFileName $R0 # get new temp file name
|
|
${LogMsg} "Opening temp file: $R0"
|
|
ClearErrors
|
|
FileOpen $tmp_file "$R0" w # open temp file for writing
|
|
${If} ${Errors}
|
|
${LogMsg} "Temp file could not be opened for writing"
|
|
${LogMsg} "Minion config will not be updated"
|
|
Goto update_minion_config_finished
|
|
${EndIf}
|
|
|
|
loop: # loop through each line
|
|
${LogMsg} "Reading line from target config file"
|
|
ClearErrors
|
|
FileRead $tgt_file $cfg_line # read line from target file
|
|
${If} ${Errors}
|
|
${LogMsg} "Error: Most likely reached End-Of-File"
|
|
Goto done
|
|
${EndIf}
|
|
|
|
loop_after_read:
|
|
StrCpy $lst_check 0 # list check not performed
|
|
|
|
${If} $ConfigWriteMaster == 1 # if we need to write master config
|
|
|
|
${StrLoc} $3 $cfg_line "master:" ">" # where is 'master:' in this line
|
|
${If} $3 == 0 # is it in the first...
|
|
${OrIf} $3 == 1 # or second position (account for comments)
|
|
|
|
${LogMsg} "Found master. Updating temp config"
|
|
|
|
${Explode} $9 "," $MasterHost # Split the hostname on commas, $9 is the number of items found
|
|
${If} $9 == 1 # 1 means only a single master was passed
|
|
StrCpy $cfg_line "master: $MasterHost$\r$\n" # write the master
|
|
${Else} # make a multi-master entry
|
|
StrCpy $cfg_line "master:" # make the first line "master:"
|
|
|
|
loop_explode: # start a loop to go through the list in the config
|
|
pop $8 # pop the next item off the stack
|
|
${Trim} $8 $8 # trim any whitespace
|
|
StrCpy $cfg_line "$cfg_line$\r$\n - $8" # add it to the master variable ($2)
|
|
IntOp $9 $9 - 1 # decrement the list count
|
|
${If} $9 >= 1 # if it's not 0
|
|
Goto loop_explode # do it again
|
|
${EndIf} # close if statement
|
|
StrCpy $cfg_line "$cfg_line$\r$\n" # Make sure there's a new line at the end
|
|
|
|
# Remove remaining items in list
|
|
${While} $lst_check == 0 # while list item found
|
|
FileRead $tgt_file $chk_line # read line from target file
|
|
IfErrors done # end if errors are encountered (end of line)
|
|
${StrLoc} $3 $chk_line " - " ">" # where is 'master:' in this line
|
|
${If} $3 == "" # is it in the first...
|
|
StrCpy $lst_check 1 # list check performed and finished
|
|
${EndIf}
|
|
${EndWhile}
|
|
|
|
${EndIf} # close if statement
|
|
|
|
StrCpy $ConfigWriteMaster 0 # master value written to config
|
|
|
|
${EndIf} # close if statement
|
|
${EndIf} # close if statement
|
|
|
|
${If} $ConfigWriteMinion == 1 # if we need to write minion config
|
|
${StrLoc} $3 $cfg_line "id:" ">" # where is 'id:' in this line
|
|
${If} $3 == 0 # is it in the first...
|
|
${OrIf} $3 == 1 # or the second position (account for comments)
|
|
${LogMsg} "Found minion ID. Updating temp config"
|
|
StrCpy $cfg_line "id: $MinionName$\r$\n" # write the minion config setting
|
|
StrCpy $ConfigWriteMinion 0 # minion value written to config
|
|
${EndIf} # close if statement
|
|
${EndIf} # close if statement
|
|
|
|
ClearErrors
|
|
${LogMsg} "Writing config line(s) to temp file"
|
|
# Enable this line for troubleshooting
|
|
# ${LogMsg} "cfg_line: $cfg_line"
|
|
FileWrite $tmp_file $cfg_line # write changed or unchanged line to temp file
|
|
${If} ${Errors}
|
|
${LogMsg} "There was an error writing new config line(s) to temp file"
|
|
Goto update_minion_config_finished
|
|
${EndIf}
|
|
|
|
${If} $lst_check == 1 # master not written to the config
|
|
StrCpy $cfg_line $chk_line
|
|
Goto loop_after_read # A loop was performed, skip the next read
|
|
${EndIf} # close if statement
|
|
|
|
Goto loop # check the next line in the config file
|
|
|
|
done:
|
|
ClearErrors
|
|
# Does master config still need to be written
|
|
${If} $ConfigWriteMaster == 1 # master not written to the config
|
|
|
|
${LogMsg} "Master not found in existing config. Appending to the bottom"
|
|
|
|
${Explode} $9 "," $MasterHost # split the hostname on commas, $9 is the number of items found
|
|
${If} $9 == 1 # 1 means only a single master was passed
|
|
StrCpy $cfg_line "master: $MasterHost" # write the master
|
|
${Else} # make a multi-master entry
|
|
StrCpy $cfg_line "master:" # make the first line "master:"
|
|
|
|
loop_explode_2: # start a loop to go through the list in the config
|
|
pop $8 # pop the next item off the stack
|
|
${Trim} $8 $8 # trim any whitespace
|
|
StrCpy $cfg_line "$cfg_line$\r$\n - $8" # add it to the master variable ($2)
|
|
IntOp $9 $9 - 1 # decrement the list count
|
|
${If} $9 >= 1 # if it's not 0
|
|
Goto loop_explode_2 # do it again
|
|
${EndIf} # close if statement
|
|
${EndIf} # close if statement
|
|
|
|
ClearErrors
|
|
${LogMsg} "Writing master config to temp file"
|
|
FileWrite $tmp_file $cfg_line # write changed or unchanged line to temp file
|
|
${If} ${Errors}
|
|
${LogMsg} "There was an error writing master config to the temp file"
|
|
${LogMsg} "cfg_line: $cfg_line"
|
|
Goto update_minion_config_finished
|
|
${EndIf}
|
|
|
|
${EndIf} # close if statement
|
|
|
|
${If} $ConfigWriteMinion == 1 # minion ID not written to the config
|
|
${LogMsg} "Minion ID not found in existing config. Appending to the bottom"
|
|
StrCpy $cfg_line "$\r$\nid: $MinionName" # write the minion config setting
|
|
|
|
ClearErrors
|
|
${LogMsg} "Writing minion id to temp config file"
|
|
FileWrite $tmp_file $cfg_line # write changed or unchanged line to temp file
|
|
${If} ${Errors}
|
|
${LogMsg} "There was an error writing minion id to temop config file"
|
|
${LogMsg} "cfg_line: $cfg_line"
|
|
Goto update_minion_config_finished
|
|
${EndIf}
|
|
${EndIf} # close if statement
|
|
|
|
${LogMsg} "Closing config files"
|
|
FileClose $tgt_file # close target file
|
|
FileClose $tmp_file # close temp file
|
|
${LogMsg} "Deleting target config"
|
|
Delete "$RootDir\conf\minion" # delete target file
|
|
${LogMsg} "Copying new target config"
|
|
CopyFiles /SILENT $R0 "$RootDir\conf\minion" # copy temp file to target file
|
|
${LogMsg} "Deleting old temp file"
|
|
Delete $R0 # delete temp file
|
|
|
|
update_minion_config_finished:
|
|
${LogMsg} "Update minion config finished"
|
|
|
|
FunctionEnd
|
|
|
|
|
|
Function un.parseUninstallerCommandLineSwitches
|
|
|
|
${LogMsg} "Parsing command line parameters for the Uninstaller"
|
|
|
|
# Load the parameters
|
|
${GetParameters} $cmdLineParams
|
|
|
|
# Uninstaller: Remove Installation Directory
|
|
${LogMsg} "Checking /delete-install-dir"
|
|
ClearErrors
|
|
${GetOptions} $cmdLineParams "/delete-install-dir" $R1
|
|
${If} ${Errors}
|
|
${LogMsg} "/delete-install-dir not found"
|
|
${Else}
|
|
${LogMsg} "Found /delete-install-dir"
|
|
StrCpy $DeleteInstallDir 1
|
|
${EndIf}
|
|
|
|
# Uninstaller: Remove Root Directory
|
|
${LogMsg} "Checking /delete-root-dir"
|
|
ClearErrors
|
|
${GetOptions} $cmdLineParams "/delete-root-dir" $R1
|
|
${If} ${Errors}
|
|
${LogMsg} "/delete-root-dir not found"
|
|
${Else}
|
|
${LogMsg} "Found /delete-root-dir"
|
|
StrCpy $DeleteRootDir 1
|
|
${EndIf}
|
|
|
|
FunctionEnd
|
|
|
|
|
|
Function parseInstallerCommandLineSwitches
|
|
|
|
${LogMsg} "Parsing command line parameters for the Installer"
|
|
|
|
# Load the parameters
|
|
${GetParameters} $cmdLineParams
|
|
${LogMsg} "Passed: $cmdLineParams"
|
|
|
|
# Check for start-minion switches
|
|
${LogMsg} "Checking for /start-minion"
|
|
${GetOptions} $cmdLineParams "/start-minion=" $R1
|
|
${IfNot} $R1 == ""
|
|
${LogMsg} "Found /start-minion=$R1"
|
|
# If start-minion was passed something, then set it
|
|
StrCpy $StartMinion $R1
|
|
${Else}
|
|
# Otherwise default to 1
|
|
${LogMsg} "/start-minion not found. Using default"
|
|
StrCpy $StartMinion 1
|
|
${EndIf}
|
|
|
|
# Service: Minion Startup Type Delayed
|
|
${LogMsg} "Checking for /start-minion-delayed"
|
|
ClearErrors
|
|
${GetOptions} $cmdLineParams "/start-minion-delayed" $R1
|
|
${If} ${Errors}
|
|
${LogMsg} "/start-minion-delayed not found"
|
|
${Else}
|
|
${LogMsg} "Found /start-minion-delayed"
|
|
StrCpy $StartMinionDelayed 1
|
|
${EndIf}
|
|
|
|
# Set default value for Use Existing Config
|
|
StrCpy $ConfigType "Existing Config"
|
|
|
|
# Minion Config: Master IP/Name
|
|
# If setting master, we don't want to use existing config
|
|
${LogMsg} "Checking for /master"
|
|
${GetOptions} $cmdLineParams "/master=" $R1
|
|
${If} ${Errors}
|
|
${LogMsg} "/master= not found. Using default"
|
|
StrCpy $MasterHost "salt"
|
|
${ElseIfNot} $R1 == ""
|
|
${LogMsg} "Found /master=$R1"
|
|
StrCpy $MasterHost $R1
|
|
StrCpy $ConfigType "Default Config"
|
|
${Else}
|
|
${LogMsg} "/master found, but value not passed. Using default value"
|
|
StrCpy $MasterHost "salt"
|
|
${EndIf}
|
|
|
|
# Minion Config: Minion ID
|
|
# If setting minion id, we don't want to use existing config
|
|
${LogMsg} "Checking for /minion-name"
|
|
${GetOptions} $cmdLineParams "/minion-name=" $R1
|
|
${If} ${Errors}
|
|
${LogMsg} "/minion-name= not found. Using default"
|
|
StrCpy $MinionName "hostname"
|
|
${ElseIfNot} $R1 == ""
|
|
${LogMsg} "Found /minion-name=$R1"
|
|
StrCpy $MinionName $R1
|
|
StrCpy $ConfigType "Default Config"
|
|
${Else}
|
|
${LogMsg} "/minion-name= found, but value not passed. Using default"
|
|
StrCpy $MinionName "hostname"
|
|
${EndIf}
|
|
|
|
# Use Default Config
|
|
${LogMsg} "Checking for /default-config"
|
|
ClearErrors
|
|
${GetOptions} $cmdLineParams "/default-config" $R1
|
|
${If} ${Errors}
|
|
${LogMsg} "/default-config not found"
|
|
${Else}
|
|
${LogMsg} "Found /default-config"
|
|
StrCpy $ConfigType "Default Config"
|
|
${EndIf}
|
|
|
|
# Use Custom Config
|
|
# Set default value for Use Custom Config
|
|
${LogMsg} "Checking for /custom-config"
|
|
# Existing config will get a `.bak` extension
|
|
${GetOptions} $cmdLineParams "/custom-config=" $R1
|
|
${If} ${Errors}
|
|
${LogMsg} "/custom-config= not found"
|
|
StrCpy $CustomConfig ""
|
|
${ElseIfNot} $R1 == ""
|
|
${LogMsg} "Found /custom-config=$R1"
|
|
StrCpy $CustomConfig $R1
|
|
StrCpy $ConfigType "Custom Config"
|
|
${Else}
|
|
${LogMsg} "/custom-config= found, but value not passed"
|
|
StrCpy $CustomConfig ""
|
|
${EndIf}
|
|
|
|
# Set Install Location
|
|
${LogMsg} "Checking for /install-dir"
|
|
ClearErrors
|
|
${GetOptions} $cmdLineParams "/install-dir=" $R1
|
|
${If} ${Errors}
|
|
${LogMsg} "/install-dir= not found"
|
|
StrCpy $CustomLocation ""
|
|
${ElseIfNot} $R1 == ""
|
|
# A Custom Location was passed, set it
|
|
${LogMsg} "Found /install-dir=$R1"
|
|
StrCpy $CustomLocation $R1
|
|
${Else}
|
|
${LogMsg} "/install-dir= found, but value not passed"
|
|
StrCpy $CustomConfig ""
|
|
${EndIf}
|
|
|
|
# Set Move Config Option
|
|
${LogMsg} "Checking for /move-config"
|
|
ClearErrors
|
|
${GetOptions} $cmdLineParams "/move-config" $R1
|
|
${If} ${Errors}
|
|
${LogMsg} "/move-config not found"
|
|
StrCpy $MoveExistingConfig 0
|
|
${Else}
|
|
${LogMsg} "Found /move-config"
|
|
StrCpy $MoveExistingConfig 1
|
|
${EndIf}
|
|
|
|
FunctionEnd
|