123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623 |
- !define PRODUCT_NAME "Salt Minion"
- !define PRODUCT_NAME_OTHER "Salt"
- !define PRODUCT_PUBLISHER "SaltStack, Inc"
- !define PRODUCT_WEB_SITE "http://saltstack.org"
- !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_KEY_OTHER "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME_OTHER}"
- !define PRODUCT_UNINST_ROOT_KEY "HKLM"
- !define OUTFILE "Salt-Minion-${PRODUCT_VERSION}-Py${PYTHON_VERSION}-${CPUARCH}-Setup.exe"
- # Import Libraries
- !include "MUI2.nsh"
- !include "nsDialogs.nsh"
- !include "LogicLib.nsh"
- !include "FileFunc.nsh"
- !include "StrFunc.nsh"
- !include "x64.nsh"
- !include "WinMessages.nsh"
- !include "WinVer.nsh"
- ${StrLoc}
- ${StrStrAdv}
- !ifdef SaltVersion
- !define PRODUCT_VERSION "${SaltVersion}"
- !else
- !define PRODUCT_VERSION "Undefined Version"
- !endif
- !ifdef PythonVersion
- !define PYTHON_VERSION "${PythonVersion}"
- !else
- !define PYTHON_VERSION "2"
- !endif
- !if "$%PROCESSOR_ARCHITECTURE%" == "AMD64"
- !define CPUARCH "AMD64"
- !else if "$%PROCESSOR_ARCHITEW6432%" == "AMD64"
- !define CPUARCH "AMD64"
- !else
- !define CPUARCH "x86"
- !endif
- # Part of the Trim function for Strings
- !define Trim "!insertmacro Trim"
- !macro Trim ResultVar String
- Push "${String}"
- Call Trim
- 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
- ###############################################################################
- # 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"
- # This entire if block can be removed for the Sodium release... including the !define MUI_WELCOMEPAGE_TEXT
- # NSIS will just use the default like it does for Python 3, which should be the same test
- !if "${PYTHON_VERSION}" == "2"
- !define MUI_WELCOMEPAGE_TEXT "\
- WARNING: Python 2 Support will be discontinued in Sodium. Salt will only ship Python 3 \
- installers starting with the Sodium release.$\r$\n\
- $\r$\n\
- Setup will guide you through the installation of ${PRODUCT_NAME} ${PRODUCT_VERSION}.$\r$\n\
- $\r$\n\
- It is recommended that you close all other applications before starting Setup. This will make it possible to \
- update relevant system files without having to reboot your computer.$\r$\n\
- $\r$\n\
- Click Next to continue."
- !endif
- # Welcome page
- !insertmacro MUI_PAGE_WELCOME
- # License page
- !insertmacro MUI_PAGE_LICENSE "LICENSE.txt"
- # 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 CheckBox_Minion_Start
- Var CheckBox_Minion_Start_Delayed
- Var ConfigMasterHost
- Var MasterHost
- Var MasterHost_State
- Var ConfigMinionName
- Var MinionName
- Var MinionName_State
- Var ExistingConfigFound
- Var ConfigType
- Var ConfigType_State
- Var CustomConfig
- Var CustomConfig_btn
- Var CustomConfig_State
- Var WarningCustomConfig
- Var WarningExistingConfig
- Var WarningDefaultConfig
- Var StartMinion
- Var StartMinionDelayed
- Var DeleteInstallDir
- Var ConfigWriteMinion
- Var ConfigWriteMaster
- ###############################################################################
- # 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% 12u "Master IP or Hostname:"
- Pop $Label
- ${NSD_CreateText} 0 13u 100% 12u $MasterHost_State
- Pop $MasterHost
- # Minion ID Dialog Control
- ${NSD_CreateLabel} 0 30u 100% 12u "Minion Name:"
- Pop $Label
- ${NSD_CreateText} 0 43u 100% 12u $MinionName_State
- Pop $MinionName
- # Config Drop List
- ${NSD_CreateDropList} 0 65u 25% 36u ""
- Pop $ConfigType
- ${NSD_CB_AddString} $ConfigType "Default Config"
- ${NSD_CB_AddString} $ConfigType "Custom Config"
- ${NSD_OnChange} $ConfigType pageMinionConfig_OnChange
- # Add Existing Config Warning Label
- ${NSD_CreateLabel} 0 80u 100% 60u "The values above are taken from an \
- existing configuration found in `c:\salt\conf\minion`. Configuration \
- settings defined in the `minion.d` directories, if they exist, are not \
- shown here.$\r$\n\
- $\r$\n\
- Clicking `Install` will leave the existing config unchanged."
- Pop $WarningExistingConfig
- CreateFont $0 "Arial" 10 500 /ITALIC
- SendMessage $WarningExistingConfig ${WM_SETFONT} $0 1
- SetCtlColors $WarningExistingConfig 0xBB0000 transparent
- # Add Default Config Warning Label
- ${NSD_CreateLabel} 0 80u 100% 60u "Clicking `Install` will backup the \
- the existing minion config file and minion.d directories. The values \
- above will be used in the new default config.$\r$\n\
- $\r$\n\
- NOTE: If Master IP is set to `salt` and Minion Name is set to \
- `hostname` no changes will be made."
- Pop $WarningDefaultConfig
- CreateFont $0 "Arial" 10 500 /ITALIC
- SendMessage $WarningDefaultConfig ${WM_SETFONT} $0 1
- SetCtlColors $WarningDefaultConfig 0xBB0000 transparent
- # Add Custom Config File Selector and Warning Label
- ${NSD_CreateText} 26% 65u 64% 12u $CustomConfig_State
- Pop $CustomConfig
- ${NSD_CreateButton} 91% 65u 9% 12u "..."
- Pop $CustomConfig_btn
- ${NSD_OnClick} $CustomConfig_btn pageCustomConfigBtn_OnClick
- ${If} $ExistingConfigFound == 0
- ${NSD_CreateLabel} 0 80u 100% 60u "Values entered above will be used \
- in the custom config.$\r$\n\
- $\r$\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 80u 100% 60u "Clicking `Install` will backup the \
- the existing minion config file and minion.d directories. The \
- values above will be used in the custom config.$\r$\n\
- $\r$\n\
- NOTE: If Master IP is set to `salt` and Minion Name is set to \
- `hostname` no changes will be made."
- ${Endif}
- Pop $WarningCustomConfig
- CreateFont $0 "Arial" 10 500 /ITALIC
- SendMessage $WarningCustomConfig ${WM_SETFONT} $0 1
- SetCtlColors $WarningCustomConfig 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 "Existing Config"
- ${Else}
- ShowWindow $WarningDefaultConfig ${SW_HIDE}
- ${Endif}
- ${NSD_CB_SelectString} $ConfigType $ConfigType_State
- ${NSD_SetText} $CustomConfig $CustomConfig_State
- 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 $ConfigType_State
- # Update Dialog
- ${Switch} $ConfigType_State
- ${Case} "Existing Config"
- # Enable Master/Minion and set values
- EnableWindow $MasterHost 0
- EnableWindow $MinionName 0
- ${NSD_SetText} $MasterHost $ConfigMasterHost
- ${NSD_SetText} $MinionName $ConfigMinionName
- # Hide Custom File Picker
- ShowWindow $CustomConfig ${SW_HIDE}
- ShowWindow $CustomConfig_btn ${SW_HIDE}
- # Hide Warnings
- ShowWindow $WarningDefaultConfig ${SW_HIDE}
- ShowWindow $WarningCustomConfig ${SW_HIDE}
- # Show Existing Warning
- ShowWindow $WarningExistingConfig ${SW_SHOW}
- ${Break}
- ${Case} "Custom Config"
- # Enable Master/Minion and set values
- EnableWindow $MasterHost 1
- EnableWindow $MinionName 1
- ${NSD_SetText} $MasterHost $MasterHost_State
- ${NSD_SetText} $MinionName $MinionName_State
- # Show Custom File Picker
- ShowWindow $CustomConfig ${SW_SHOW}
- ShowWindow $CustomConfig_btn ${SW_SHOW}
- # Hide Warnings
- ShowWindow $WarningDefaultConfig ${SW_HIDE}
- ShowWindow $WarningExistingConfig ${SW_HIDE}
- # Show Custom Warning
- ShowWindow $WarningCustomConfig ${SW_SHOW}
- ${Break}
- ${Case} "Default Config"
- # Enable Master/Minion and set values
- EnableWindow $MasterHost 1
- EnableWindow $MinionName 1
- ${NSD_SetText} $MasterHost $MasterHost_State
- ${NSD_SetText} $MinionName $MinionName_State
- # Hide Custom File Picker
- ShowWindow $CustomConfig ${SW_HIDE}
- ShowWindow $CustomConfig_btn ${SW_HIDE}
- # Hide Warnings
- ShowWindow $WarningExistingConfig ${SW_HIDE}
- ShowWindow $WarningCustomConfig ${SW_HIDE}
- # Show Default Warning, if there is an existing config
- ${If} $ExistingConfigFound == 1
- ShowWindow $WarningDefaultConfig ${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 $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 $2
- ${EndIf}
- # Free resources
- System::Free $1
- System::Free $0
- FunctionEnd
- Function pageMinionConfig_Leave
- # Save the State
- ${NSD_GetText} $MasterHost $MasterHost_State
- ${NSD_GetText} $MinionName $MinionName_State
- ${NSD_GetText} $ConfigType $ConfigType_State
- ${NSD_GetText} $CustomConfig $CustomConfig_State
- # Abort if config file not found
- ${If} $ConfigType_State == "Custom Config"
- IfFileExists "$CustomConfig_State" continue 0
- MessageBox MB_OK "File not found: $CustomConfig_State" /SD IDOK
- Abort
- ${EndIf}
- continue:
- Call BackupExistingConfig
- 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 $CheckBox_Minion_Start
- SetCtlColors $CheckBox_Minion_Start "" "ffffff"
- # This command required to bring the checkbox to the front
- System::Call "User32::SetWindowPos(i, i, i, i, i, i, i) b ($CheckBox_Minion_Start, ${HWND_TOP}, 0, 0, 0, 0, ${SWP_NOSIZE}|${SWP_NOMOVE})"
- # Create Start Minion Delayed ComboBox
- ${NSD_CreateCheckbox} 130u 102u 100% 12u "&Delayed Start"
- Pop $CheckBox_Minion_Start_Delayed
- SetCtlColors $CheckBox_Minion_Start_Delayed "" "ffffff"
- # This command required to bring the checkbox to the front
- System::Call "User32::SetWindowPos(i, i, i, i, i, i, i) b ($CheckBox_Minion_Start_Delayed, ${HWND_TOP}, 0, 0, 0, 0, ${SWP_NOSIZE}|${SWP_NOMOVE})"
- # Load current settings for Minion
- ${If} $StartMinion == 1
- ${NSD_Check} $CheckBox_Minion_Start
- ${EndIf}
- # Load current settings for Minion Delayed
- ${If} $StartMinionDelayed == 1
- ${NSD_Check} $CheckBox_Minion_Start_Delayed
- ${EndIf}
- FunctionEnd
- Function pageFinish_Leave
- # Assign the current checkbox states
- ${NSD_GetState} $CheckBox_Minion_Start $StartMinion
- ${NSD_GetState} $CheckBox_Minion_Start_Delayed $StartMinionDelayed
- FunctionEnd
- ###############################################################################
- # Installation Settings
- ###############################################################################
- !if ${PYTHON_VERSION} == 3
- Name "${PRODUCT_NAME} ${PRODUCT_VERSION} (Python ${PYTHON_VERSION})"
- !else
- Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
- !endif
- OutFile "${OutFile}"
- InstallDir "c:\salt"
- InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
- ShowInstDetails show
- ShowUnInstDetails show
- Section -copy_prereqs
- # Copy prereqs to the Plugins Directory
- # These files will be vcredist 2008 and KB2999226 for Win8.1 and below
- # These files are downloaded by build_pkg.bat
- # This directory gets removed upon completion
- SetOutPath "$PLUGINSDIR\"
- File /r "..\prereqs\"
- SectionEnd
- # Check and install the Windows 10 Universal C Runtime (KB2999226)
- # ucrt is needed on Windows 8.1 and lower
- # They are installed as a Microsoft Update package (.msu)
- # ucrt for Windows 8.1 RT is only available via Windows Update
- Section -install_ucrt
- Var /GLOBAL MsuPrefix
- Var /GLOBAL MsuFileName
- # UCRT only needs to be installed for Python 3
- StrCmp ${PYTHON_VERSION} 2 lbl_done
- # Get the Major.Minor version Number
- # Windows 10 introduced CurrentMajorVersionNumber
- ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" \
- CurrentMajorVersionNumber
- # Windows 10/2016 will return a value here, skip to the end if returned
- StrCmp $R0 '' lbl_needs_ucrt 0
- # Found Windows 10
- detailPrint "KB2999226 does not apply to this machine"
- goto lbl_done
- lbl_needs_ucrt:
- # UCRT only needed on Windows Server 2012R2/Windows 8.1 and below
- # The first ReadRegStr command above should have skipped to lbl_done if on
- # Windows 10 box
- # Is the update already installed
- ClearErrors
- # Use WMI to check if it's installed
- detailPrint "Checking for existing KB2999226 installation"
- nsExec::ExecToStack 'cmd /q /c wmic qfe get hotfixid | findstr "^KB2999226"'
- # Clean up the stack
- Pop $R0 # Gets the ErrorCode
- Pop $R1 # Gets the stdout, which should be KB2999226 if it's installed
- # If it returned KB2999226 it's already installed
- StrCmp $R1 'KB2999226' lbl_done
- detailPrint "KB2999226 not found"
- # All lower versions of Windows
- ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" \
- CurrentVersion
- # Get the name of the .msu file based on the value of $R0
- ${Switch} "$R0"
- ${Case} "6.3"
- StrCpy $MsuPrefix "Windows8.1"
- ${break}
- ${Case} "6.2"
- StrCpy $MsuPrefix "Windows8-RT"
- ${break}
- ${Case} "6.1"
- StrCpy $MsuPrefix "Windows6.1"
- ${break}
- ${Case} "6.0"
- StrCpy $MsuPrefix "Windows6.0"
- ${break}
- ${EndSwitch}
- # Use RunningX64 here to get the Architecture for the system running the installer
- # CPUARCH is defined when the installer is built and is based on the machine that
- # built the installer, not the target system as we need here.
- ${If} ${RunningX64}
- StrCpy $MsuFileName "$MsuPrefix-KB2999226-x64.msu"
- ${Else}
- StrCpy $MsuFileName "$MsuPrefix-KB2999226-x86.msu"
- ${EndIf}
- ClearErrors
- detailPrint "Installing KB2999226 using file $MsuFileName"
- nsExec::ExecToStack 'cmd /c wusa "$PLUGINSDIR\$MsuFileName" /quiet /norestart'
- # Clean up the stack
- Pop $R0 # Get Error
- Pop $R1 # Get stdout
- ${IfNot} $R0 == 0
- detailPrint "error: $R0"
- detailPrint "output: $R2"
- Sleep 3000
- ${Else}
- detailPrint "KB2999226 installed successfully"
- ${EndIf}
- lbl_done:
- SectionEnd
- # Check and install Visual C++ redist packages
- # See http://blogs.msdn.com/b/astebner/archive/2009/01/29/9384143.aspx for more info
- # Hidden section (-) to install VCRedist
- Section -install_vcredist
- Var /GLOBAL VcRedistName
- Var /GLOBAL VcRedistGuid
- Var /GLOBAL NeedVcRedist
- Var /GLOBAL CheckVcRedist
- StrCpy $CheckVcRedist "False"
- # Visual C++ 2008 SP1 MFC Security Update redist packages
- !define PY2_VC_REDIST_NAME "VC_Redist_2008_SP1_MFC"
- !define PY2_VC_REDIST_X64_GUID "{5FCE6D76-F5DC-37AB-B2B8-22AB8CEDB1D4}"
- !define PY2_VC_REDIST_X86_GUID "{9BE518E6-ECC6-35A9-88E4-87755C07200F}"
- # VCRedist only needs to be installed for Python 2
- ${If} ${PYTHON_VERSION} == 2
- StrCpy $VcRedistName ${PY2_VC_REDIST_NAME}
- ${If} ${CPUARCH} == "AMD64"
- StrCpy $VcRedistGuid ${PY2_VC_REDIST_X64_GUID}
- ${Else}
- StrCpy $VcRedistGuid ${PY2_VC_REDIST_X86_GUID}
- ${EndIf}
- # VCRedist 2008 only needed on Windows Server 2008R2/Windows 7 and below
- ${If} ${AtMostWin2008R2}
- StrCpy $CheckVcRedist "True"
- ${EndIf}
- ${EndIf}
- ${If} $CheckVcRedist == "True"
- Push $VcRedistGuid
- Call MsiQueryProductState
- ${If} $NeedVcRedist == "True"
- MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 \
- "$VcRedistName is currently not installed. Would you like to install?" \
- /SD IDYES IDNO endVcRedist
- # 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
- ExecWait '"$PLUGINSDIR\vcredist.exe" /q' $0
- IfErrors 0 CheckVcRedistErrorCode
- MessageBox MB_OK \
- "$VcRedistName failed to install. Try installing the package manually." \
- /SD IDOK
- Goto endVcRedist
- CheckVcRedistErrorCode:
- # Check for Reboot Error Code (3010)
- ${If} $0 == 3010
- MessageBox MB_OK \
- "$VcRedistName installed but requires a restart to complete." \
- /SD IDOK
- # Check for any other errors
- ${ElseIfNot} $0 == 0
- MessageBox MB_OK \
- "$VcRedistName failed with ErrorCode: $0. Try installing the package manually." \
- /SD IDOK
- ${EndIf}
- endVcRedist:
- ${EndIf}
- ${EndIf}
- SectionEnd
- Section "MainSection" SEC01
- SetOutPath "$INSTDIR\"
- SetOverwrite off
- CreateDirectory $INSTDIR\conf\pki\minion
- CreateDirectory $INSTDIR\conf\minion.d
- File /r "..\buildenv\"
- nsExec::Exec 'icacls c:\salt /inheritance:r /grant:r "*S-1-5-32-544":(OI)(CI)F /grant:r "*S-1-5-18":(OI)(CI)F'
- SectionEnd
- Function .onInit
- Call parseCommandLineSwitches
- # If custom config passed, verify its existence before continuing so we
- # don't uninstall an existing installation and then fail
- ${If} $ConfigType_State == "Custom Config"
- IfFileExists "$CustomConfig_State" customConfigExists 0
- Abort
- ${EndIf}
- customConfigExists:
- # Check for existing installation
- ReadRegStr $R0 HKLM \
- "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
- "UninstallString"
- StrCmp $R0 "" checkOther
- # Found existing installation, prompt to uninstall
- MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \
- "${PRODUCT_NAME} is already installed.$\n$\n\
- Click `OK` to remove the existing installation." \
- /SD IDOK IDOK uninst
- Abort
- checkOther:
- # Check for existing installation of full salt
- ReadRegStr $R0 HKLM \
- "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME_OTHER}" \
- "UninstallString"
- StrCmp $R0 "" skipUninstall
- # Found existing installation, prompt to uninstall
- MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \
- "${PRODUCT_NAME_OTHER} is already installed.$\n$\n\
- Click `OK` to remove the existing installation." \
- /SD IDOK IDOK uninst
- Abort
- uninst:
- # Get current Silent status
- StrCpy $R0 0
- ${If} ${Silent}
- StrCpy $R0 1
- ${EndIf}
- # Turn on Silent mode
- SetSilent silent
- # Don't remove all directories
- StrCpy $DeleteInstallDir 0
- # Uninstall silently
- Call uninstallSalt
- # Set it back to Normal mode, if that's what it was before
- ${If} $R0 == 0
- SetSilent normal
- ${EndIf}
- skipUninstall:
- Call getExistingMinionConfig
- ${If} $ExistingConfigFound == 0
- ${AndIf} $ConfigType_State == "Existing Config"
- StrCpy $ConfigType_State "Default Config"
- ${EndIf}
- IfSilent 0 +2
- Call BackupExistingConfig
- FunctionEnd
- # Time Stamp Definition
- !define /date TIME_STAMP "%Y-%m-%d-%H-%M-%S"
- Function BackupExistingConfig
- ${If} $ExistingConfigFound == 1 # If existing config found
- ${AndIfNot} $ConfigType_State == "Existing Config" # If not using Existing Config
- # Backup the minion config
- Rename "$INSTDIR\conf\minion" "$INSTDIR\conf\minion-${TIME_STAMP}.bak"
- IfFileExists "$INSTDIR\conf\minion.d" 0 +2
- Rename "$INSTDIR\conf\minion.d" "$INSTDIR\conf\minion.d-${TIME_STAMP}.bak"
- ${EndIf}
- # By this point there should be no existing config
- # It was either backed up or wasn't there to begin with
- ${If} $ConfigType_State == "Custom Config" # If we're using Custom Config
- ${AndIfNot} $CustomConfig_State == "" # If a custom config is passed
- # Check for a file name
- # Named file should be in the same directory as the installer
- CreateDirectory "$INSTDIR\conf"
- IfFileExists "$EXEDIR\$CustomConfig_State" 0 checkFullPath
- CopyFiles /SILENT /FILESONLY "$EXEDIR\$CustomConfig_State" "$INSTDIR\conf\minion"
- goto finished
- # Maybe it was a full path to a file
- checkFullPath:
- IfFileExists "$CustomConfig_State" 0 finished
- CopyFiles /SILENT /FILESONLY "$CustomConfig_State" "$INSTDIR\conf\minion"
- finished:
- ${EndIf}
- FunctionEnd
- Section -Post
- WriteUninstaller "$INSTDIR\uninst.exe"
- # 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"
- # Set the estimated size
- ${GetSize} "$INSTDIR\bin" "/S=OK" $0 $1 $2
- IntFmt $0 "0x%08X" $0
- WriteRegDWORD ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" \
- "EstimatedSize" "$0"
- # Commandline Registry Entries
- WriteRegStr HKLM "${PRODUCT_CALL_REGKEY}" "" "$INSTDIR\salt-call.bat"
- WriteRegStr HKLM "${PRODUCT_CALL_REGKEY}" "Path" "$INSTDIR\bin\"
- WriteRegStr HKLM "${PRODUCT_MINION_REGKEY}" "" "$INSTDIR\salt-minion.bat"
- WriteRegStr HKLM "${PRODUCT_MINION_REGKEY}" "Path" "$INSTDIR\bin\"
- # Register the Salt-Minion Service
- nsExec::Exec "$INSTDIR\bin\ssm.exe install salt-minion $INSTDIR\bin\python.exe -E -s $INSTDIR\bin\Scripts\salt-minion -c $INSTDIR\conf -l quiet"
- nsExec::Exec "$INSTDIR\bin\ssm.exe set salt-minion Description Salt Minion from saltstack.com"
- nsExec::Exec "$INSTDIR\bin\ssm.exe set salt-minion Start SERVICE_AUTO_START"
- nsExec::Exec "$INSTDIR\bin\ssm.exe set salt-minion AppStopMethodConsole 24000"
- nsExec::Exec "$INSTDIR\bin\ssm.exe set salt-minion AppStopMethodWindow 2000"
- ${IfNot} $ConfigType_State == "Existing Config" # If not using Existing Config
- Call updateMinionConfig
- ${EndIf}
- Push "C:\salt"
- Call AddToPath
- SectionEnd
- Function .onInstSuccess
- # If StartMinionDelayed is 1, then set the service to start delayed
- ${If} $StartMinionDelayed == 1
- nsExec::Exec "$INSTDIR\bin\ssm.exe set salt-minion Start SERVICE_DELAYED_AUTO_START"
- ${EndIf}
- # If start-minion is 1, then start the service
- ${If} $StartMinion == 1
- nsExec::Exec 'net start salt-minion'
- ${EndIf}
- FunctionEnd
- Function un.onInit
- # Load the parameters
- ${GetParameters} $R0
- # Uninstaller: Remove Installation Directory
- ClearErrors
- ${GetOptions} $R0 "/delete-install-dir" $R1
- IfErrors delete_install_dir_not_found
- StrCpy $DeleteInstallDir 1
- delete_install_dir_not_found:
- MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 \
- "Are you sure you want to completely remove $(^Name) and all of its components?" \
- /SD IDYES IDYES +2
- Abort
- FunctionEnd
- Section Uninstall
- Call un.uninstallSalt
- # Remove C:\salt from the Path
- Push "C:\salt"
- Call un.RemoveFromPath
- SectionEnd
- !macro uninstallSalt un
- Function ${un}uninstallSalt
- # Make sure we're in the right directory
- ${If} $INSTDIR == "c:\salt\bin\Scripts"
- StrCpy $INSTDIR "C:\salt"
- ${EndIf}
- # Stop and Remove salt-minion service
- nsExec::Exec 'net stop salt-minion'
- nsExec::Exec 'sc delete salt-minion'
- # Stop and remove the salt-master service
- nsExec::Exec 'net stop salt-master'
- nsExec::Exec 'sc delete salt-master'
- # Remove files
- Delete "$INSTDIR\uninst.exe"
- Delete "$INSTDIR\ssm.exe"
- Delete "$INSTDIR\salt*"
- Delete "$INSTDIR\vcredist.exe"
- RMDir /r "$INSTDIR\bin"
- # Remove Registry entries
- DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
- DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY_OTHER}"
- 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}"
- # Automatically close when finished
- SetAutoClose true
- # Prompt to remove the Installation directory
- ${IfNot} $DeleteInstallDir == 1
- MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 \
- "Would you like to completely remove $INSTDIR and all of its contents?" \
- /SD IDNO IDNO finished
- ${EndIf}
- # Make sure you're not removing Program Files
- ${If} $INSTDIR != 'Program Files'
- ${AndIf} $INSTDIR != 'Program Files (x86)'
- RMDir /r "$INSTDIR"
- ${EndIf}
- finished:
- FunctionEnd
- !macroend
- !insertmacro uninstallSalt ""
- !insertmacro uninstallSalt "un."
- Function un.onUninstSuccess
- HideWindow
- MessageBox MB_ICONINFORMATION|MB_OK \
- "$(^Name) was successfully removed from your computer." \
- /SD IDOK
- FunctionEnd
- ###############################################################################
- # Helper Functions
- ###############################################################################
- Function MsiQueryProductState
- # Used for detecting VCRedist Installation
- !define INSTALLSTATE_DEFAULT "5"
- Pop $R0
- StrCpy $NeedVcRedist "False"
- System::Call "msi::MsiQueryProductStateA(t '$R0') i.r0"
- StrCmp $0 ${INSTALLSTATE_DEFAULT} +2 0
- StrCpy $NeedVcRedist "True"
- FunctionEnd
- #------------------------------------------------------------------------------
- # 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
- #------------------------------------------------------------------------------
- Function 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
- #------------------------------------------------------------------------------
- # 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
- #------------------------------------------------------------------------------
- # StrStr Function
- # - find substring in a string
- #
- # Usage:
- # Push "this is some string"
- # Push "some"
- # Call StrStr
- # Pop $0 # "some string"
- #------------------------------------------------------------------------------
- !macro StrStr un
- Function ${un}StrStr
- Exch $R1 # $R1=substring, stack=[old$R1,string,...]
- Exch # stack=[string,old$R1,...]
- Exch $R2 # $R2=string, stack=[old$R2,old$R1,...]
- Push $R3 # $R3=strlen(substring)
- Push $R4 # $R4=count
- Push $R5 # $R5=tmp
- StrLen $R3 $R1 # Get the length of the Search String
- StrCpy $R4 0 # Set the counter to 0
- loop:
- StrCpy $R5 $R2 $R3 $R4 # Create a moving window of the string that is
- # the size of the length of the search string
- StrCmp $R5 $R1 done # Is the contents of the window the same as
- # search string, then done
- StrCmp $R5 "" done # Is the window empty, then done
- IntOp $R4 $R4 + 1 # Shift the windows one character
- Goto loop # Repeat
- done:
- StrCpy $R1 $R2 "" $R4
- Pop $R5
- Pop $R4
- Pop $R3
- Pop $R2
- Exch $R1 # $R1=old$R1, stack=[result,...]
- FunctionEnd
- !macroend
- !insertmacro StrStr ""
- !insertmacro StrStr "un."
- #------------------------------------------------------------------------------
- # AddToPath Function
- # - Adds item to Path for All Users
- # - Overcomes NSIS ReadRegStr limitation of 1024 characters by using Native
- # Windows Commands
- #
- # Usage:
- # Push "C:\path\to\add"
- # Call AddToPath
- #------------------------------------------------------------------------------
- !define Environ 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
- Function AddToPath
- Exch $0 # Path to add
- Push $1 # Current Path
- Push $2 # Results of StrStr / Length of Path + Path to Add
- Push $3 # Handle to Reg / Length of Path
- Push $4 # Result of Registry Call
- # Open a handle to the key in the registry, handle in $3, Error in $4
- System::Call "advapi32::RegOpenKey(i 0x80000002, t'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', *i.r3) i.r4"
- # Make sure registry handle opened successfully (returned 0)
- IntCmp $4 0 0 done done
- # Load the contents of path into $1, Error Code into $4, Path length into $2
- System::Call "advapi32::RegQueryValueEx(i $3, t'PATH', i 0, i 0, t.r1, *i ${NSIS_MAX_STRLEN} r2) i.r4"
- # Close the handle to the registry ($3)
- System::Call "advapi32::RegCloseKey(i $3)"
- # Check for Error Code 234, Path too long for the variable
- IntCmp $4 234 0 +4 +4 # $4 == ERROR_MORE_DATA
- DetailPrint "AddToPath Failed: original length $2 > ${NSIS_MAX_STRLEN}"
- MessageBox MB_OK \
- "You may add C:\salt to the %PATH% for convenience when issuing local salt commands from the command line." \
- /SD IDOK
- Goto done
- # If no error, continue
- IntCmp $4 0 +5 # $4 != NO_ERROR
- # Error 2 means the Key was not found
- IntCmp $4 2 +3 # $4 != ERROR_FILE_NOT_FOUND
- DetailPrint "AddToPath: unexpected error code $4"
- Goto done
- StrCpy $1 ""
- # Check if already in PATH
- Push "$1;" # The string to search
- Push "$0;" # The string to find
- Call StrStr
- Pop $2 # The result of the search
- StrCmp $2 "" 0 done # String not found, try again with ';' at the end
- # Otherwise, it's already in the path
- Push "$1;" # The string to search
- Push "$0\;" # The string to find
- Call StrStr
- Pop $2 # The result
- StrCmp $2 "" 0 done # String not found, continue (add)
- # Otherwise, it's already in the path
- # Prevent NSIS string overflow
- StrLen $2 $0 # Length of path to add ($2)
- StrLen $3 $1 # Length of current path ($3)
- IntOp $2 $2 + $3 # Length of current path + path to add ($2)
- IntOp $2 $2 + 2 # Account for the additional ';'
- # $2 = strlen(dir) + strlen(PATH) + sizeof(";")
- # Make sure the new length isn't over the NSIS_MAX_STRLEN
- IntCmp $2 ${NSIS_MAX_STRLEN} +4 +4 0
- DetailPrint "AddToPath Failed: new length $2 > ${NSIS_MAX_STRLEN}"
- MessageBox MB_OK \
- "You may add C:\salt to the %PATH% for convenience when issuing local salt commands from the command line." \
- /SD IDOK
- Goto done
- # Append dir to PATH
- DetailPrint "Add to PATH: $0"
- StrCpy $2 $1 1 -1 # Copy the last character of the existing path
- StrCmp $2 ";" 0 +2 # Check for trailing ';'
- StrCpy $1 $1 -1 # remove trailing ';'
- StrCmp $1 "" +2 # Make sure Path is not empty
- StrCpy $0 "$1;$0" # Append new path at the end ($0)
- # We can use the NSIS command here. Only 'ReadRegStr' is affected
- WriteRegExpandStr ${Environ} "PATH" $0
- # Broadcast registry change to open programs
- SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
- done:
- Pop $4
- Pop $3
- Pop $2
- Pop $1
- Pop $0
- FunctionEnd
- #------------------------------------------------------------------------------
- # RemoveFromPath Function
- # - Removes item from Path for All Users
- # - Overcomes NSIS ReadRegStr limitation of 1024 characters by using Native
- # Windows Commands
- #
- # Usage:
- # Push "C:\path\to\add"
- # Call un.RemoveFromPath
- #------------------------------------------------------------------------------
- Function un.RemoveFromPath
- Exch $0
- Push $1
- Push $2
- Push $3
- Push $4
- Push $5
- Push $6
- # Open a handle to the key in the registry, handle in $3, Error in $4
- System::Call "advapi32::RegOpenKey(i 0x80000002, t'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', *i.r3) i.r4"
- # Make sure registry handle opened successfully (returned 0)
- IntCmp $4 0 0 done done
- # Load the contents of path into $1, Error Code into $4, Path length into $2
- System::Call "advapi32::RegQueryValueEx(i $3, t'PATH', i 0, i 0, t.r1, *i ${NSIS_MAX_STRLEN} r2) i.r4"
- # Close the handle to the registry ($3)
- System::Call "advapi32::RegCloseKey(i $3)"
- # Check for Error Code 234, Path too long for the variable
- IntCmp $4 234 0 +4 +4 # $4 == ERROR_MORE_DATA
- DetailPrint "AddToPath: original length $2 > ${NSIS_MAX_STRLEN}"
- Goto done
- # If no error, continue
- IntCmp $4 0 +5 # $4 != NO_ERROR
- # Error 2 means the Key was not found
- IntCmp $4 2 +3 # $4 != ERROR_FILE_NOT_FOUND
- DetailPrint "AddToPath: unexpected error code $4"
- Goto done
- StrCpy $1 ""
- # Ensure there's a trailing ';'
- StrCpy $5 $1 1 -1 # Copy the last character of the path
- StrCmp $5 ";" +2 # Check for trailing ';', if found continue
- StrCpy $1 "$1;" # ensure trailing ';'
- # Check for our directory inside the path
- Push $1 # String to Search
- Push "$0;" # Dir to Find
- Call un.StrStr
- Pop $2 # The results of the search
- StrCmp $2 "" done # If results are empty, we're done, otherwise continue
- # Remove our Directory from the Path
- DetailPrint "Remove from PATH: $0"
- StrLen $3 "$0;" # Get the length of our dir ($3)
- StrLen $4 $2 # Get the length of the return from StrStr ($4)
- StrCpy $5 $1 -$4 # $5 is now the part before the path to remove
- StrCpy $6 $2 "" $3 # $6 is now the part after the path to remove
- StrCpy $3 "$5$6" # Combine $5 and $6
- # Check for Trailing ';'
- StrCpy $5 $3 1 -1 # Load the last character of the string
- StrCmp $5 ";" 0 +2 # Check for ';'
- StrCpy $3 $3 -1 # remove trailing ';'
- # Write the new path to the registry
- WriteRegExpandStr ${Environ} "PATH" $3
- # Broadcast the change to all open applications
- SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
- done:
- Pop $6
- Pop $5
- Pop $4
- Pop $3
- Pop $2
- Pop $1
- Pop $0
- FunctionEnd
- ###############################################################################
- # Specialty Functions
- ###############################################################################
- Function getExistingMinionConfig
- # Set Config Found Default Value
- StrCpy $ExistingConfigFound 0
- confFind:
- IfFileExists "$INSTDIR\conf\minion" confFound confNotFound
- confNotFound:
- ${If} $INSTDIR == "c:\salt\bin\Scripts"
- StrCpy $INSTDIR "C:\salt"
- goto confFind
- ${Else}
- goto confReallyNotFound
- ${EndIf}
- confFound:
- StrCpy $ExistingConfigFound 1
- FileOpen $0 "$INSTDIR\conf\minion" r
- 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} $ConfigMasterHost == "" # if the config setting is empty
- StrCpy $ConfigMasterHost $2 # make the first item the new entry
- ${Else}
- StrCpy $ConfigMasterHost "$ConfigMasterHost,$2" # Append the new master, comma separated
- ${EndIf}
- Goto masterLoop # check the next one
- ${EndIf}
- ${Else}
- StrCpy $ConfigMasterHost $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 $ConfigMinionName $2
- ${EndIf}
- Goto confLoop
- EndOfFile:
- FileClose $0
- confReallyNotFound:
- # Set Default Config Values if not found
- ${If} $ConfigMasterHost == ""
- StrCpy $ConfigMasterHost "salt"
- ${EndIf}
- ${If} $ConfigMinionName == ""
- StrCpy $ConfigMinionName "hostname"
- ${EndIf}
- FunctionEnd
- Var cfg_line
- Var chk_line
- Var lst_check
- Function updateMinionConfig
- ClearErrors
- FileOpen $0 "$INSTDIR\conf\minion" "r" # open target file for reading
- GetTempFileName $R0 # get new temp file name
- FileOpen $1 $R0 "w" # open temp file for writing
- StrCpy $ConfigWriteMaster 1 # write the master config value
- StrCpy $ConfigWriteMinion 1 # write the minion config value
- loop: # loop through each line
- FileRead $0 $cfg_line # read line from target file
- IfErrors done # end if errors are encountered (end of line)
- loop_after_read:
- StrCpy $lst_check 0 # list check not performed
- ${If} $MasterHost_State == "" # if master is empty
- ${OrIf} $MasterHost_State == "salt" # or if master is 'salt'
- StrCpy $ConfigWriteMaster 0 # no need to write master config
- ${EndIf} # close if statement
- ${If} $MinionName_State == "" # if minion is empty
- ${OrIf} $MinionName_State == "hostname" # and if minion is not 'hostname'
- StrCpy $ConfigWriteMinion 0 # no need to write minion config
- ${EndIf} # close if statement
- ${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)
- ${Explode} $9 "," $MasterHost_state # 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_State$\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 $0 $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)
- StrCpy $cfg_line "id: $MinionName_State$\r$\n" # write the minion config setting
- StrCpy $ConfigWriteMinion 0 # minion value written to config
- ${EndIf} # close if statement
- ${EndIf} # close if statement
- FileWrite $1 $cfg_line # write changed or unchanged line to temp file
- ${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
- ${Explode} $9 "," $MasterHost_state # 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_State" # 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
- FileWrite $1 $cfg_line # write changed or unchanged line to temp file
- ${EndIf} # close if statement
- ${If} $ConfigWriteMinion == 1 # minion ID not written to the config
- StrCpy $cfg_line "$\r$\nid: $MinionName_State" # write the minion config setting
- FileWrite $1 $cfg_line # write changed or unchanged line to temp file
- ${EndIf} # close if statement
- FileClose $0 # close target file
- FileClose $1 # close temp file
- Delete "$INSTDIR\conf\minion" # delete target file
- CopyFiles /SILENT $R0 "$INSTDIR\conf\minion" # copy temp file to target file
- Delete $R0 # delete temp file
- FunctionEnd
- Function parseCommandLineSwitches
- # Load the parameters
- ${GetParameters} $R0
- # Display Help
- ClearErrors
- ${GetOptions} $R0 "/?" $R1
- IfErrors display_help_not_found
- System::Call 'kernel32::GetStdHandle(i -11)i.r0'
- System::Call 'kernel32::AttachConsole(i -1)i.r1'
- ${If} $0 = 0
- ${OrIf} $1 = 0
- System::Call 'kernel32::AllocConsole()'
- System::Call 'kernel32::GetStdHandle(i -11)i.r0'
- ${EndIf}
- FileWrite $0 "$\n"
- FileWrite $0 "$\n"
- FileWrite $0 "Help for Salt Minion installation$\n"
- FileWrite $0 "===============================================================================$\n"
- FileWrite $0 "$\n"
- FileWrite $0 "/minion-name=$\t$\tA string value to set the minion name. Default value is$\n"
- FileWrite $0 "$\t$\t$\t'hostname'. Setting the minion name causes the installer$\n"
- FileWrite $0 "$\t$\t$\tto use the default config or a custom config if defined$\n"
- FileWrite $0 "$\n"
- FileWrite $0 "/master=$\t$\tA string value to set the IP address or hostname of the$\n"
- FileWrite $0 "$\t$\t$\tmaster. Default value is 'salt'. You may pass a single$\n"
- FileWrite $0 "$\t$\t$\tmaster or a comma-separated list of masters. Setting$\n"
- FileWrite $0 "$\t$\t$\tthe master will cause the installer to use the default$\n"
- FileWrite $0 "$\t$\t$\tconfig or a custom config if defined$\n"
- FileWrite $0 "$\n"
- FileWrite $0 "/start-minion=$\t$\t1 will start the minion service, 0 will not.$\n"
- FileWrite $0 "$\t$\t$\tDefault is 1$\n"
- FileWrite $0 "$\n"
- FileWrite $0 "/start-minion-delayed$\tSet the minion start type to 'Automatic (Delayed Start)'$\n"
- FileWrite $0 "$\n"
- FileWrite $0 "/default-config$\t$\tOverwrite the existing config if present with the$\n"
- FileWrite $0 "$\t$\t$\tdefault config for salt. Default is to use the existing$\n"
- FileWrite $0 "$\t$\t$\tconfig if present. If /master and/or /minion-name is$\n"
- FileWrite $0 "$\t$\t$\tpassed, those values will be used to update the new$\n"
- FileWrite $0 "$\t$\t$\tdefault config$\n"
- FileWrite $0 "$\n"
- FileWrite $0 "$\t$\t$\tAny existing config will be backed up by appending$\n"
- FileWrite $0 "$\t$\t$\ta timestamp and a .bak extension. That includes\n"
- FileWrite $0 "$\t$\t$\tthe minion file and the minion.d directory$\n"
- FileWrite $0 "$\n"
- FileWrite $0 "/custom-config=$\t$\tA string value specifying the name of a custom config$\n"
- FileWrite $0 "$\t$\t$\tfile in the same path as the installer or the full path$\n"
- FileWrite $0 "$\t$\t$\tto a custom config file. If /master and/or /minion-name$\n"
- FileWrite $0 "$\t$\t$\tis passed, those values will be used to update the new$\n"
- FileWrite $0 "$\t$\t$\tcustom config$\n"
- FileWrite $0 "$\n"
- FileWrite $0 "$\t$\t$\tAny existing config will be backed up by appending$\n"
- FileWrite $0 "$\t$\t$\ta timestamp and a .bak extension. That includes\n"
- FileWrite $0 "$\t$\t$\tthe minion file and the minion.d directory$\n"
- FileWrite $0 "$\n"
- FileWrite $0 "/S$\t$\t$\tInstall Salt silently$\n"
- FileWrite $0 "$\n"
- FileWrite $0 "/?$\t$\t$\tDisplay this help screen$\n"
- FileWrite $0 "$\n"
- FileWrite $0 "-------------------------------------------------------------------------------$\n"
- FileWrite $0 "$\n"
- FileWrite $0 "Examples:$\n"
- FileWrite $0 "$\n"
- FileWrite $0 "${OutFile} /S$\n"
- FileWrite $0 "$\n"
- FileWrite $0 "${OutFile} /S /minion-name=myminion /master=master.mydomain.com /start-minion-delayed$\n"
- FileWrite $0 "$\n"
- FileWrite $0 "===============================================================================$\n"
- FileWrite $0 "$\n"
- System::Free $0
- System::Free $1
- System::Call 'kernel32::FreeConsole()'
- # Give the user back the prompt
- !define VK_RETURN 0x0D ; Enter Key
- !define KEYEVENTF_EXTENDEDKEY 0x0001
- !define KEYEVENTF_KEYUP 0x0002
- System::Call "user32::keybd_event(i${VK_RETURN}, i0x45, i${KEYEVENTF_EXTENDEDKEY}|0, i0)"
- System::Call "user32::keybd_event(i${VK_RETURN}, i0x45, i${KEYEVENTF_EXTENDEDKEY}|${KEYEVENTF_KEYUP}, i0)"
- Abort
- display_help_not_found:
- # Set default value for Use Existing Config
- StrCpy $ConfigType_State "Existing Config"
- # Check for start-minion switches
- # /start-service is to be deprecated, so we must check for both
- ${GetOptions} $R0 "/start-service=" $R1
- ${GetOptions} $R0 "/start-minion=" $R2
- # Service: Start Salt Minion
- ${IfNot} $R2 == ""
- # If start-minion was passed something, then set it
- StrCpy $StartMinion $R2
- ${ElseIfNot} $R1 == ""
- # If start-service was passed something, then set StartMinion to that
- StrCpy $StartMinion $R1
- ${Else}
- # Otherwise default to 1
- StrCpy $StartMinion 1
- ${EndIf}
- # Service: Minion Startup Type Delayed
- ClearErrors
- ${GetOptions} $R0 "/start-minion-delayed" $R1
- IfErrors start_minion_delayed_not_found
- StrCpy $StartMinionDelayed 1
- start_minion_delayed_not_found:
- # Minion Config: Master IP/Name
- # If setting master, we don't want to use existing config
- ${GetOptions} $R0 "/master=" $R1
- ${IfNot} $R1 == ""
- StrCpy $MasterHost_State $R1
- StrCpy $ConfigType_State "Default Config"
- ${ElseIf} $MasterHost_State == ""
- StrCpy $MasterHost_State "salt"
- ${EndIf}
- # Minion Config: Minion ID
- # If setting minion id, we don't want to use existing config
- ${GetOptions} $R0 "/minion-name=" $R1
- ${IfNot} $R1 == ""
- StrCpy $MinionName_State $R1
- StrCpy $ConfigType_State "Default Config"
- ${ElseIf} $MinionName_State == ""
- StrCpy $MinionName_State "hostname"
- ${EndIf}
- # Use Default Config
- ${GetOptions} $R0 "/default-config" $R1
- IfErrors default_config_not_found
- StrCpy $ConfigType_State "Default Config"
- default_config_not_found:
- # Use Custom Config
- # Set default value for Use Custom Config
- StrCpy $CustomConfig_State ""
- # Existing config will get a `.bak` extension
- ${GetOptions} $R0 "/custom-config=" $R1
- ${IfNot} $R1 == ""
- # Custom Config was passed something, set it
- StrCpy $CustomConfig_State $R1
- StrCpy $ConfigType_State "Custom Config"
- ${EndIf}
- FunctionEnd
|