Skip to content

Commit

Permalink
[FEATURE] Rewrite Windows installer from scratch
Browse files Browse the repository at this point in the history
This patch introduces the following new features:
- include plugin EnVar for better path handling
- create unicode installer by default
- use SOLID lzma compression
- introduce installation types `Full`, `Simple` and `Minimal`
- use of DDEV branding images
- show license pages of selected components only
- use start menu selection page
- provide option to run `mkcert -install` for attended install
- allow downgrade of DDEV
- copy license files for all installed components
- power off DDEV before update
- clean up multiple path entries in the registry
- copy icons for nice start menu links
- write various link helpers for start menu short cuts to Links directory
- create various start menu short cuts
- introduce section groups for a better overview
- create mkcert install and uninstall links and start menu short cuts
- remember last install directory for updates
- clean up mistakenly created keys in the registry
- add links and icon to the uninstaller entry
- log external calls to the install files window
- improve 64 bit OS support and abort on 32 bit
- provide option to download and install Docker Desktop
- provide option to open the Docker Toolbox download page
- provide option to run `mkcert -uninstall` in uninstaller
- cleanly remove installed files
- license pages will be shown on first install only

And some other goodies simplifying development on the installer:
- allow manual compilation e.g. from an IDE
- short description of how to do common changes to the installer
- inline documentation
- test project to test libraries
- docker support can be disabled by option `/DDOCKER_EXCLUDE`

The new graphics can be found in winpkg/graphics and their sources (psd) in winpkg/graphics/sources.

Additional plugins are stored in winpkg/plugins.
  • Loading branch information
gilbertsoft committed Oct 31, 2019
1 parent cd302a0 commit 46493ce
Show file tree
Hide file tree
Showing 20 changed files with 1,340 additions and 480 deletions.
1,476 changes: 996 additions & 480 deletions winpkg/ddev.nsi

Large diffs are not rendered by default.

84 changes: 84 additions & 0 deletions winpkg/ddev_lib_test.nsi
@@ -0,0 +1,84 @@
Name "DDEV Lib Test"
OutFile "..\.gotmp\bin\windows_amd64\ddev_lib_test.exe"
ShowInstDetails show
RequestExecutionLevel user

#!define DDEV_NO_PLUGINS
#!define DOCKER_NO_PLUGINS

!addincludedir include
!include ddev.nsh
!include docker.nsh

Page components "" ""
Page instfiles

Section "Run tests"

ClearErrors

SetRegView 64
ReadRegStr $0 HKLM `SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\ddev.exe` `Path`
SetRegView Default

${If} ${DdevIsInstalled} "$0"
DetailPrint "DDEV is installed"
${Else}
DetailPrint "$0\ddev.exe not found"
${EndIf}

${If} ${DdevIsExecutable} "$0"
Pop $R0 ; Output
DetailPrint "DDEV is executable:"
DetailPrint " $R0"
${Else}
DetailPrint "DDEV is not executable"
${EndIf}

${If} ${DdevPowerOff} "$0"
Pop $R0 ; Output
DetailPrint "DDEV projects are powered off now:"
DetailPrint " $R0"
${Else}
Pop $R0 ; Output
DetailPrint "DDEV power off failed:"
DetailPrint " $R0"
${EndIf}

${DdevDoPowerOff} "$0"
Pop $R0 ; Return
Pop $R1 ; Output
DetailPrint "DDEV power off result: $R0"
DetailPrint "DDEV power off output:"
DetailPrint " $R1"


${If} ${DockerDesktopIsInstallable}
DetailPrint "Docker Desktop is installable"
${Else}
DetailPrint "Docker Desktop is not installable"
${EndIf}

${If} ${DockerDesktopIsInstalled}
DetailPrint "Docker Desktop is installed"
${Else}
DetailPrint "Docker Desktop is not installed"
${EndIf}

${If} ${DockerDesktopIsExecutable}
Pop $R0 ; Output
DetailPrint "docker.exe is executable:"
DetailPrint " $R0"
${Else}
DetailPrint "docker.exe is not executable"
${EndIf}

${If} ${DockerComposeIsExecutable}
Pop $R0 ; Output
DetailPrint "docker-compose.exe is executable"
DetailPrint " $R0"
${Else}
DetailPrint "docker-compose.exe is not executable"
${EndIf}

SectionEnd
Binary file added winpkg/graphics/ca-install.ico
Binary file not shown.
Binary file added winpkg/graphics/ca-uninstall.ico
Binary file not shown.
Binary file added winpkg/graphics/ddev-header.bmp
Binary file not shown.
Binary file added winpkg/graphics/ddev-install.ico
Binary file not shown.
Binary file added winpkg/graphics/ddev-uninstall.ico
Binary file not shown.
Binary file added winpkg/graphics/ddev-wizard.bmp
Binary file not shown.
Binary file added winpkg/graphics/sources/ddev-header.psd
Binary file not shown.
Binary file added winpkg/graphics/sources/ddev-install.psd
Binary file not shown.
Binary file added winpkg/graphics/sources/ddev-uninstall.psd
Binary file not shown.
Binary file added winpkg/graphics/sources/ddev-wizard.psd
Binary file not shown.
112 changes: 112 additions & 0 deletions winpkg/include/ddev.nsh
@@ -0,0 +1,112 @@
/**
* ddev.nsh - LogicLib extensions for handling DDEV checks and actions
*
* The following "expressions" are available:
*
* DdevIsInstalled checks if ddev.exe is available in the provided directory
*
* ${If} ${DdevIsInstalled} "$PROGRAMFILES64\DDEV"
* DetailPrint "DDEV exists"
* ${Else}
* DetailPrint "$PROGRAMFILES64\DDEV\ddev.exe not found"
* ${EndIf}
*
*
* DdevIsExecutable checks if ddev.exe can be executed in the provided directory
*
* ${If} ${DdevIsExecutable} "$PROGRAMFILES64\DDEV"
* DetailPrint "DDEV is executable"
* ${Else}
* Pop $R0 ; Output
* DetailPrint "DDEV is not executable: $R0"
* ${EndIf}
*
*
* DdevPowerOff executes ddev.exe poweroff in the provided directory
*
* ${If} ${DdevPowerOff} "$PROGRAMFILES64\DDEV"
* DetailPrint "DDEV projects are powered off now"
* ${Else}
* Pop $R0 ; Output
* DetailPrint "DDEV power off failed: $R0"
* ${EndIf}
*
*
* The following "statements" are available:
*
* DdevDoPowerOff executes ddev.exe poweroff in the provided directory
*
* ${DdevDoPowerOff} "$PROGRAMFILES64\DDEV"
* Pop $R0 ; Output
* DetailPrint "DDEV power off output: $R0"
*
*
* DDEV_NO_PLUGINS disables the usage of external plugins and relays on built
* in functions only but on the other hand disable some functionality like
* accessing the output of the command execution.
*
* !define DDEV_NO_PLUGINS
* !include ddev.nsh
*
*/

!verbose push
!verbose 3
!ifndef DDEV_VERBOSITY
!define DDEV_VERBOSITY 3
!endif
!define _DDEV_VERBOSITY ${DDEV_VERBOSITY}
!undef DDEV_VERBOSITY
!verbose ${_DDEV_VERBOSITY}

!ifndef DDEV_NSH
!define DDEV_NSH

!ifndef DDEV_NO_PLUGINS
ReserveFile /plugin nsExec.dll
!endif

!include LogicLib.nsh

!macro _DdevIsInstalled _a _b _t _f
!insertmacro _FileExists `${_a}` `${_b}\ddev.exe` `${_t}` `${_f}`
!macroend
!define DdevIsInstalled `"" DdevIsInstalled`

!macro _DdevIsExecutable _a _b _t _f
!insertmacro _LOGICLIB_TEMP
!ifdef DDEV_NO_PLUGINS
ExecWait `"${_b}\ddev.exe" version` $_LOGICLIB_TEMP
!else
nsExec::ExecToStack `"${_b}\ddev.exe" version`
Pop $_LOGICLIB_TEMP ; Return, the Output remains on the stack
!endif
!insertmacro _== $_LOGICLIB_TEMP `0` `${_t}` `${_f}`
!macroend
!define DdevIsExecutable `"" DdevIsExecutable`

!macro _DdevPowerOff _a _b _t _f
!insertmacro _LOGICLIB_TEMP
!insertmacro _DdevDoPowerOff `${_b}`
Pop $_LOGICLIB_TEMP ; Return, the Output remains on the stack
!insertmacro _== $_LOGICLIB_TEMP `0` `${_t}` `${_f}`
!macroend
!define DdevPowerOff `"" DdevPowerOff`

!macro _DdevDoPowerOff _path
!insertmacro _LOGICLIB_TEMP
!ifdef DDEV_NO_PLUGINS
ExecWait `"${_path}\ddev.exe" poweroff` $_LOGICLIB_TEMP
Push $_LOGICLIB_TEMP
!else
nsExec::ExecToStack `"${_path}\ddev.exe" poweroff`
!endif
!macroend
!define DdevDoPowerOff `!insertmacro _DdevDoPowerOff`

!endif ; DDEV_NSH

!verbose 3
!define DDEV_VERBOSITY ${_DDEV_VERBOSITY}
!undef _DDEV_VERBOSITY
!verbose pop
148 changes: 148 additions & 0 deletions winpkg/include/docker.nsh
@@ -0,0 +1,148 @@
/**
* docker.nsh - LogicLib extensions for handling docker checks
*
* The following "expressions" are available:
*
* DockerDesktopIsInstallable checks if docker is installable
*
* ${If} ${DockerDesktopIsInstallable}
* DetailPrint "DDEV exists"
* ${Else}
* DetailPrint "$PROGRAMFILES64\DDEV\ddev.exe not found"
* ${EndIf}
*
*
* DockerDesktopIsInstalled checks if docker is installed
*
* ${If} ${DockerDesktopIsInstalled} "$PROGRAMFILES64\DDEV"
* DetailPrint "DDEV exists"
* ${Else}
* DetailPrint "$PROGRAMFILES64\DDEV\ddev.exe not found"
* ${EndIf}
*
*
* DockerDesktopIsExecutable checks if docker can be executed
*
* ${If} ${DockerDesktopIsExecutable}
* DetailPrint "DDEV is accessible"
* ${Else}
* Pop $R0 ; Output
* DetailPrint "DDEV is not accessible: $R0"
* ${EndIf}
*
*
* DockerComposeIsExecutable checks if docker-compose can be executed
*
* ${If} ${DockerComposeIsExecutable}
* DetailPrint "DDEV is accessible"
* ${Else}
* Pop $R0 ; Output
* DetailPrint "DDEV is not accessible: $R0"
* ${EndIf}
*
*
* DOCKER_NO_PLUGINS disables the usage of external plugins and relays on built
* in functions only but on the other hand disable some functionality like
* accessing the output of the command execution.
*
* !define DOCKER_NO_PLUGINS
* !include docker.nsh
*
*/

!verbose push
!verbose 3
!ifndef DOCKER_VERBOSITY
!define DOCKER_VERBOSITY 3
!endif
!define _DOCKER_VERBOSITY ${DOCKER_VERBOSITY}
!undef DOCKER_VERBOSITY
!verbose ${_DOCKER_VERBOSITY}

!ifndef DOCKER_NSH
!define DOCKER_NSH

; Optional plugins
!ifndef DOCKER_NO_PLUGINS
ReserveFile /plugin nsExec.dll
!endif

; Includes
!include LogicLib.nsh
!include WinVer.nsh

; Global constants
!define DOCKER_DESKTOP_NAME `Docker Desktop`
!define DOCKER_DESKTOP_URL `https://download.docker.com/win/stable/Docker%20Desktop%20Installer.exe`
!define DOCKER_DESKTOP_SETUP `Docker Desktop Installer.exe`

!define DOCKER_TOOLBOX_NAME `Docker Toolbox`
!define DOCKER_TOOLBOX_URL `https://github.com/docker/toolbox/releases/latest`

; Macros
!macro _DockerDesktopIsInstallable _a _b _t _f
!insertmacro _LOGICLIB_TEMP
!insertmacro _WinVer_BuildNumCheck U< 15063 DockerDesktopIsInstallableDone 0
ReadRegStr $_LOGICLIB_TEMP HKLM `SOFTWARE\Microsoft\Windows NT\CurrentVersion` `EditionID`
StrCmp $_LOGICLIB_TEMP `Home` DockerDesktopIsInstallableDone
StrCmp $_LOGICLIB_TEMP `HomeEval` DockerDesktopIsInstallableDone
StrCmp $_LOGICLIB_TEMP `Core` DockerDesktopIsInstallableDone
StrCmp $_LOGICLIB_TEMP `CoreN` DockerDesktopIsInstallableDone
StrCmp $_LOGICLIB_TEMP `CoreSingleLanguage` DockerDesktopIsInstallableDone
StrCmp $_LOGICLIB_TEMP `CoreCountrySpecific` DockerDesktopIsInstallableDone
StrCpy $_LOGICLIB_TEMP `Installable`
DockerDesktopIsInstallableDone:
!insertmacro _== $_LOGICLIB_TEMP `Installable` `${_t}` `${_f}`
!macroend
!define DockerDesktopIsInstallable `"" DockerDesktopIsInstallable ""`

!macro _DockerDesktopIsInstalled _a _b _t _f
!insertmacro _LOGICLIB_TEMP
StrCpy $_LOGICLIB_TEMP ``
!define DOCKER_REG_UNINST_KEY `SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall`
SetRegView 64
ReadRegStr $_LOGICLIB_TEMP HKLM `${DOCKER_REG_UNINST_KEY}\Docker Desktop` `UninstallString`
StrCmp $_LOGICLIB_TEMP `` 0 DockerDesktopIsInstalled
ReadRegStr $_LOGICLIB_TEMP HKLM `${DOCKER_REG_UNINST_KEY}\Docker for Windows` `UninstallString`
StrCmp $_LOGICLIB_TEMP `` 0 DockerDesktopIsInstalled
ReadRegStr $_LOGICLIB_TEMP HKLM `${DOCKER_REG_UNINST_KEY}\{C7F6BAA1-B432-4386-A4F0-395B8098C8D9}` `UninstallString`
StrCmp $_LOGICLIB_TEMP `` 0 DockerDesktopIsInstalled
Goto DockerDesktopIsInstalledDone
DockerDesktopIsInstalled:
StrCpy $_LOGICLIB_TEMP `Installed`
DockerDesktopIsInstalledDone:
SetRegView lastused
!insertmacro _== $_LOGICLIB_TEMP `Installed` `${_t}` `${_f}`
!macroend
!define DockerDesktopIsInstalled `"" DockerDesktopIsInstalled ""`

!macro _DockerDesktopIsExecutable _a _b _t _f
!insertmacro _LOGICLIB_TEMP
!ifdef DOCKER_NO_PLUGINS
ExecWait `"docker.exe" -v` $_LOGICLIB_TEMP
!else
nsExec::ExecToStack `"docker.exe" -v`
Pop $_LOGICLIB_TEMP ; Return, the Output remains on the stack
!endif
!insertmacro _== $_LOGICLIB_TEMP `0` `${_t}` `${_f}`
!macroend
!define DockerDesktopIsExecutable `"" DockerDesktopIsExecutable ""`

!macro _DockerComposeIsExecutable _a _b _t _f
!insertmacro _LOGICLIB_TEMP
!ifdef DOCKER_NO_PLUGINS
ExecWait `"docker-compose.exe" -v` $_LOGICLIB_TEMP
!else
nsExec::ExecToStack `"docker-compose.exe" -v`
Pop $_LOGICLIB_TEMP ; Return, the Output remains on the stack
!endif
!insertmacro _== $_LOGICLIB_TEMP `0` `${_t}` `${_f}`
!macroend
!define DockerComposeIsExecutable `"" DockerComposeIsExecutable ""`

!endif ; DOCKER_NSH

!verbose 3
!define DOCKER_VERBOSITY ${_DOCKER_VERBOSITY}
!undef _DOCKER_VERBOSITY
!verbose pop
Binary file added winpkg/plugins/amd64-unicode/EnVar.dll
Binary file not shown.
Binary file added winpkg/plugins/amd64-unicode/INetC.dll
Binary file not shown.
Binary file added winpkg/plugins/x86-ansi/EnVar.dll
Binary file not shown.
Binary file added winpkg/plugins/x86-ansi/INetC.dll
Binary file not shown.
Binary file added winpkg/plugins/x86-unicode/EnVar.dll
Binary file not shown.
Binary file added winpkg/plugins/x86-unicode/INetC.dll
Binary file not shown.

0 comments on commit 46493ce

Please sign in to comment.