windows-installer/setup.nsi (262 lines of code) (raw):

;-------------------------------- ; Stackdriver Logging Agent Installer. ; ; Installs and starts the Stackdriver logging agent. ;-------------------------------- ;-------------------------------- ; GLOBAL VARIABLES ;-------------------------------- ; Company or Publisher name. !define COMPANY "Google" ; The parent product. !define PRODUCT "Stackdriver" ; Software name used for display to users. !define DISPLAY_NAME "${COMPANY} ${PRODUCT} Logging Agent ${VERSION}" ; Software name with no white space. !define COMPRESSED_NAME "${COMPANY}${PRODUCT}LoggingAgent" ; Registry entry key to store arbitrary information. !define REG_KEY "Software\${COMPANY}\${PRODUCT}\LoggingAgent" ; Uninstaller registry key, used to register the agent. !define STACKDRIVER_UNINST_REG_KEY "${UNINST_REG_KEY}\${COMPRESSED_NAME}" ; Absolute location of the uninstaller. !define UNINSTALLER_LOCATION "$INSTDIR\uninstall.exe" ; Directory to install all files into. This makes uninstall easier and safer. !define MAIN_INSTDIR "$INSTDIR\Main" ; Directory where the fluentd config will be placed. !define FLUENTD_CONFIG_DIRECTORY "$INSTDIR" ; Directory under which the buffer files will be stored. !define BUFFER_FILE_DIRECTORY "$INSTDIR\buffers" ; Directory under which the pos files will be stored. !define POS_FILE_DIRECTORY "$INSTDIR\pos" ; Directory for the user to add custom configs. !define CUSTOM_CONFIG_DIR "config.d" ; The name of fluentd config template file, this is bundled into the script. !define FLUENTD_CONFIG_TEMPLATE "fluent-template.conf" ; Absolute location of the fluentd config file. !define FLUENTD_CONFIG_LOCATION "${FLUENTD_CONFIG_DIRECTORY}\fluent.conf" ; Directory where the fluentd log file will be written. !define FLUENTD_LOG_DIRECTORY "$INSTDIR" ; Absolute location of the fluentd log file. !define FLUENTD_LOG_LOCATION "${FLUENTD_LOG_DIRECTORY}\fluentd.log" ; Name of the main zip file, this is bundled into the script. !define ZIP_FILE "${COMPRESSED_NAME}.zip" ;-------------------------------- ; GENERAL CONFIGURATION ;-------------------------------- ; Needed to properly display all languages, may not work on older windows OSs. Unicode true ; Name used for display throughout the installer. Name "${DISPLAY_NAME}" ; Output location/name of the installer executable. OutFile "${COMPRESSED_NAME}-${VERSION}_unsigned.exe" ; Default install location. InstallDir "$PROGRAMFILES\Stackdriver\LoggingAgent" ; Require admin level logs access, this is required as we need to read event logs. RequestExecutionLevel admin ;-------------------------------- ; INCLUDES ;-------------------------------- ; General includes. !include "Locate.nsh" ; Needed for GetSize !include "StrFunc.nsh" ; Needed for StrTrimNewLines and StrRep !include "WordFunc.nsh" ; Needed for WordFind ; Stackdriver includes. !include "stackdriver_language_util.nsh" !include "stackdriver_ui.nsh" !include "stackdriver_util.nsh" ;-------------------------------- ; FUNCTIONS ;-------------------------------- ; Define StrTrimNewLines and StrRep functions to use below. ${StrTrimNewLines} ${StrRep} ;-------------------------------- ; GENERAL UI SET UP ;-------------------------------- ; Configures auto save for the users selected language. See stackdriver_language_util.nsh. !insertmacro STACKDRIVER_SAVE_USER_LANGUAGE "${REG_KEY}" ; Configures the UI and pages for the installer. See stackdriver_ui.nsh. !insertmacro STACKDRIVER_UI "false" ; Adds all supported languages. See stackdriver_language_util.nsh. !insertmacro STACKDRIVER_INCLUDE_ALL_LANGUAGES ;-------------------------------- ; INSTALLER FUNCTIONS ;-------------------------------- ; Function called as soon as the installer is initialized, before the GUI. Function .onInit ; Display the language selection dialog. !insertmacro MUI_LANGDLL_DISPLAY ; Check for a previously installed version. If one exists ; prompt the user to remove it before continuing. ReadRegStr $0 HKLM "${STACKDRIVER_UNINST_REG_KEY}" "UninstallString" ${If} $0 != "" ${RemoveOldVersion} "${DISPLAY_NAME}" $0 ${EndIf} ; Temporary directory used during install and automatically cleaned up after. InitPluginsDir FunctionEnd ;-------------------------------- ; INSTALLER SECTIONS ;-------------------------------- Section "Install" ; Print messages to the details list view not the text (status) bar, ; this provides a cleaner install when files are being unzipped. SetDetailsPrint listonly ; Set output path for files to the install directory. SetOutPath $INSTDIR ; Add extra space to the size to account for the compressed file. ; Size is in KB. 100,000KB = 100MB AddSize 100000 ; Include the icon file in the installer directory, this is used in ; the add/remove programs menu. File "${UI_ICON}" ; Include the custom fluentd config to capture windows event logs. File "${FLUENTD_CONFIG_TEMPLATE}" ; Include the main zip file. File "${ZIP_FILE}" ; Create an uninstaller and show status. ${Print} "Generating an uninstaller..." WriteUninstaller "${UNINSTALLER_LOCATION}" ; Create a directory for the extracted files. CreateDirectory ${MAIN_INSTDIR} ; Extract the needed files and show status. ${Print} "Extracting files to $MAIN_INSTDIR..." nsisunz::Unzip "$OUTDIR\${ZIP_FILE}" "${MAIN_INSTDIR}" Pop $0 ; Ensure the file unzipped if not notify the user and abort. ${If} $0 != "success" ${IfNot} ${Silent} MessageBox MB_OK "Failed to unzip: $0" ${Else} ${Print} "Failed to unzip: $0" ${EndIf} Abort ${EndIf} ; Delete the zip file after extraction. Delete "$OUTDIR\${ZIP_FILE}" ; Create a directory to store buffer files. CreateDirectory ${BUFFER_FILE_DIRECTORY} ; Create a directory to store position files. CreateDirectory ${POS_FILE_DIRECTORY} ; Create a directory for custom configs. CreateDirectory "${FLUENTD_CONFIG_DIRECTORY}\${CUSTOM_CONFIG_DIR}" ; Copy and update the fluentd config and show status, we cannot use most of ; the needed plugins that would do this in a better way as they do not work ; well with unicode on and fail (mostly silently). ; NOTE: This is very dependent on the config. It should have multiple place ; holders that will be replaced. ${Print} "Updating configuration files..." ; ----- Begin update fluent config ----- ; Be sure to clear any errors before file operations. ClearErrors ; Open the tempate config to read and create a new config file to write to. FileOpen $0 "$OUTDIR\${FLUENTD_CONFIG_TEMPLATE}" "r" FileOpen $1 "${FLUENTD_CONFIG_LOCATION}" "w" ; Write each file from the template config to the new config, ; updating each line as needed. loop: ; Read the next line, if we hit an error we are at the end of the file. FileRead $0 $2 IfErrors done ; Trim out newlines as WordFind cannot handle them. ${StrTrimNewLines} $3 "$2" ; Look for 'BUFFER_PATH_PLACE_HOLDER', if found replace it with the ; proper path. ${WordFind} "$3" "BUFFER_PATH_PLACE_HOLDER" "#" $4 ${If} $4 == "1" ; Replace the whole line instead of using "StrRep" to avoid unicode issues. StrCpy $2 " buffer_path '${BUFFER_FILE_DIRECTORY}'$\r$\n" ${EndIf} ; Look for 'WIN_EVT_POS_FILE_PLACE_HOLDER', if found replace it with the ; proper pos_file. ${WordFind} "$3" "WIN_EVT_POS_FILE_PLACE_HOLDER" "#" $4 ${If} $4 == "1" ; Replace the whole line instead of using "StrRep" to avoid unicode issues. StrCpy $2 " path '${POS_FILE_DIRECTORY}\winevtlog.pos'$\r$\n" ${EndIf} ; Look for 'CUSTOM_CONFIG_PLACE_HOLDER', if found replace it with the ; proper path. ${WordFind} "$3" "CUSTOM_CONFIG_PLACE_HOLDER" "#" $4 ${If} $4 == "1" ; Fluentd doesn't properly glob windows paths. This is a temporary ; fix until https://github.com/fluent/fluentd/issues/1138 is solved. ${StrRep} "$5" "${CUSTOM_CONFIG_DIR}\**\*.conf" "\" "/" ; Replace the whole line instead of using "StrRep" to avoid unicode issues. StrCpy $2 "@include '$5'$\r$\n" ${EndIf} ; Write the line to the config file. FileWrite $1 $2 Goto loop ; We finished be sure to close the file handles. done: FileClose $0 FileClose $1 ; Delete the template config. Delete "$OUTDIR\${FLUENTD_CONFIG_TEMPLATE}" ; ----- End update fluent config ----- ; Get the size of the install directory. This is used to give a proper estimate ; in the add/remove programs menu. ; "/S=Kb" Gets the size in KB ; $0 = size, $1 = number of files, $2 = number of directories. ${locate::GetSize} "$INSTDIR" "/S=Kb" $0 $1 $2 ; Register the software so it will appear in the add/remove programs menu. ${Print} "Registering ${DISPLAY_NAME}..." ${RegisterUninstallSoftware} \ "${DISPLAY_NAME}" "${COMPRESSED_NAME}" "${UNINSTALLER_LOCATION}" "${UI_ICON}" "${COMPANY}" "$0" "${VERSION}" ; Update the paths in ruby files. ${ExecuteCommand} "${MAIN_INSTDIR}\bin\ruby.exe" "'${MAIN_INSTDIR}\bin\gem' \ pristine --all --only-executables" ; Start the fluentd service and show status. ; '--reg-winsvc i' -> Install as a windows service ; '--reg-winsvc-auto-start' -> Set service to start automatically (at boot) ; '--reg-winsvc-delay-start' -> Delay auto-start until shortly after boot ; '--reg-winsvc-fluentdopt' -> Pass along the config file ; '--winsvc-name' -> The service name the agent will run as ; '--winsvc-display-name' -> The display name of service ; '--winsvc-desc' -> A description of the service ${Print} "Starting the ${DISPLAY_NAME}..." ${ExecuteCommand} "${MAIN_INSTDIR}\bin\fluentd.bat" \ "--reg-winsvc i --reg-winsvc-auto-start --reg-winsvc-delay-start \ --reg-winsvc-fluentdopt $\"-c $\'${FLUENTD_CONFIG_LOCATION}$\' -o $\'${FLUENTD_LOG_LOCATION}$\'$\" \ --winsvc-name $\"${PRODUCT}Logging$\" \ --winsvc-display-name $\"${PRODUCT} Logging$\" \ --winsvc-desc $\"A service that collects and reports logs to ${PRODUCT}$\"" ; All done! ${Print} "Installation Complete" SectionEnd ;-------------------------------- ; UNINSTALLER FUNCTIONS ;-------------------------------- ; Function called as soon as the uninstaller is initialized, before the GUI. Function un.onInit ; Display the language selection dialog. !insertmacro MUI_UNGETLANGUAGE FunctionEnd ;-------------------------------- ; UNINSTALLER SECTIONS ;-------------------------------- Section "Uninstall" ; Print messages to the details list view not the text (status) bar, ; this provides a cleaner install when files are being removed. SetDetailsPrint listonly ; Stop the fluentd service and show status. ; '--reg-winsvc u' -> Uninstall ${UnPrint} "Stopping the ${DISPLAY_NAME}..." ${UnExecuteCommand} "${MAIN_INSTDIR}\bin\fluentd.bat" "--reg-winsvc u --winsvc-name $\"${PRODUCT}Logging$\"" ; Remove the software from the registry. ${UnPrint} "Unregistering the ${DISPLAY_NAME}..." ${RemoveRegisterUninstallSoftware} "${COMPRESSED_NAME}" ; Clean up any other registry entires used. DeleteRegKey HKLM "${REG_KEY}" ${UnPrint} "Cleaning up files in $INSTDIR..." ; Delete all files in the main install directory. RMDir /r /REBOOTOK "${MAIN_INSTDIR}" ; Clean up all files not in the main directory. Delete /REBOOTOK "${UNINSTALLER_LOCATION}" Delete /REBOOTOK "${FLUENTD_CONFIG_LOCATION}" Delete /REBOOTOK "$INSTDIR\${UI_ICON}" ; Remove the install directory if it is empty. RMDir /REBOOTOK "$INSTDIR" ; All done! ${UnPrint} "Uninstallation Complete" SectionEnd