Supposed there is a portable Windows application without an installer and uninstaller, how to create them back? In today's post, we will explore one way to build a Setup.exe
using AutoHotkey (AHK), with additional compression of 7-Zip applied to the Setup.exe
and remaining files of the portable application for maximum compression, and then wrap it with an outer unattended installer, turning a portable application into an installable one while being suitable also for silent deployment.
The application example, i.e. the application for which a setup is created is AeroZoom. While some terminologies are specific to AeroZoom, the general concepts should apply to other software.
// ⭐1️⃣ to be built: outer unattended installer written in AHK
AeroZoom_Unattended_Installer.exe
│
│ // 2️⃣ to be built: 7-Zip self-extracting archive
│
└───AeroZoom_7-Zip_SFX.exe
│
├───AeroZoom // portable app example
│
│ AeroZoom.exe
│ ...
│
│ // ⭐3️⃣ to be built: inner setup written in AHK
│
│ Setup.exe
│
└───Data
-
AeroZoom_Unattended_Installer.exe
will be the outer unattended installer we will write in AutoHotkey (AHK) language, which contains 7-Zip SFXAeroZoom_7-Zip_SFX.exe
and is responsible for extraction as well as calling an innerSetup.exe
to install AeroZoom for all users silently -
The second-level
AeroZoom_7-Zip_SFX.exe
will be our 7-Zip self-extracting archive (SFX). It contains the portable application files of AeroZoom and the innerSetup.exe
- Use of a 7-Zip SFX automatically provides silent extraction parameters for the outer
AeroZoom_Unattended_Installer.exe
to leverage - The SFX will be zipped with the ultra compression option to effectively reduce the size of AeroZoom from 32MB to 2MB in the case of AeroZoom which contains multiple similar executables
- Use of a 7-Zip SFX automatically provides silent extraction parameters for the outer
-
The third-level
Setup.exe
, the inner setup, is the second AutoHotkey program we will write which provides installations parameters for the outerAeroZoom_Unattended_Installer.exe
which can be leveraged e.g. bychoco install
command of Chocolatey, uninstallation parameters forchoco uninstall
, as well as logic to determine several things such as whether AeroZoom has already been installed, which will be detailed in the last section
After walking through how to create AeroZoom_7-Zip_SFX.exe
and AeroZoom_Unattended_Installer.exe
(goal #1), we will take a detour to go through how to push this unattended installer to the community repository of Chocolatey (goal #2), the package manager for Windows, before going back to detailing how to create the inner Setup.exe
(goal #3).
This how-to will be centered around our code repository on GitHub:
- 1. Step-by-Step: Building Outer Unattended Installer Using AutoHotkey (Goal #1)
- 2. Pushing Unattended Installer to Chocolatey (Goal #2)
- 3. Step-by-Step: Building Inner Setup Using AutoHotkey (Goal #3)
Let's go and create all those exe files above!
Scripted in AHK, AeroZoom enhances upon Windows Magnifier and optionally Sysinternals ZoomIt to enable screen magnification by mouse-wheeling, as well as turning any mouse into a Home-Theater PC/presentation mouse, where zooming and positioning becomes a breeze without a keyboard.
Originally, AeroZoom was built as a portable application. Its Setup.exe
was introduced in a later version, v2.0
, and the unattended setup AeroZoom_Unattended_Installer.exe
, the first outcome of this article, was introduced in v4.0
.
This first section walks through how to create the outer unattended installer, AeroZoom_Unattended_Installer.exe
, written in AutoHotkey:
-
In Command Prompt, download or git clone our code repository to a desired directory e.g.
c:\az-autohotkey-silent-setup
cd /d c: git clone https://github.com/wandersick/az-autohotkey-silent-setup.git
So that the following folder structure is acquired
C:\az-autohotkey-silent-setup │ ... │ │ // AHK code of the outer unattended installer to be customized │ │ AeroZoom_Unattended_Installer.ahk │ │ // optional: for use with Compile_AHK II (alternative compiler) │ └───AeroZoom_Unattended_Installer.ahk.ini
-
Download AeroZoom and extract it to a desired directory, e.g.
C:\AeroZoom
C:\AeroZoom │ AeroZoom.exe │ Readme.txt │ Setup.exe │ └───Data
-
Build an inner
Setup.exe
using AutoHotkey following these instructions in the third and final section to learn the process, or leave it as is for now and learn how to build it later (recommended for now)- Ensure
Setup.exe
is next to AeroZoom
C:\AeroZoom │ AeroZoom.exe │ Readme.txt │ │ // if you manually build this Setup.exe, replace existing one │ // otherwise, no action is required │ │ Setup.exe │ └───Data
- Ensure
-
Package (compress) the above
C:\AeroZoom
application directory in a 7-Zip SFX (self-extracting archive)-
Optionally, this step can be skipped by leveraging the AeroZoom download, which already comes with an SFX
AeroZoom_v4.0.0.7_beta_2.exe
after extraction -
Put the SFX file there and rename it as
AeroZoom_7-Zip_SFX.exe
C:\az-autohotkey-silent-setup │ AeroZoom_Unattended_Installer.ahk │ AeroZoom_Unattended_Installer.ahk.ini │ README.md │ ... │ │ // place SFX (containing C:\AeroZoom) built using 7-Zip here │ └───AeroZoom_7-Zip_SFX.exe
-
-
Place an icon named
AeroZoom_Setup.ico
there (optional)C:\az-autohotkey-silent-setup │ AeroZoom_7-Zip_SFX.exe │ AeroZoom_Unattended_Installer.ahk │ AeroZoom_Unattended_Installer.ahk.ini │ README.md │ ... │ │ // optionally, place an icon here │ └───AeroZoom_Setup.ico
-
Edit AeroZoom_Unattended_Installer.ahk and change below
C:\az-autohotkey-silent-setup\AeroZoom_7-Zip_SFX.exe
to a desired location (no change if directory is the same as the example)As shown below, the AutoHotkey source code of
AeroZoom_Unattended_Installer.exe
is relatively simple. It only contains three lines (excluding comments):; Package an application (e.g. AeroZoom) in 7-Zip SFX ; (FYI: the AeroZoom download already comes with an SFX) ; Place it in the location specified below ; e.g. C:\az-autohotkey-silent-setup\AeroZoom_7-Zip_SFX.exe FileInstall, C:\az-autohotkey-silent-setup\AeroZoom_7-Zip_SFX.exe, %A_ScriptDir%\AeroZoom_7-Zip_SFX.exe, 1 ; Silently extract AeroZoom from SFX into the current folder RunWait, %A_ScriptDir%\AeroZoom_7-Zip_SFX.exe -o"%A_ScriptDir%" -y ; Run silent setup command: Setup.exe /programfiles /unattendaz=1 ; For AeroZoom, thse parameters will perform installation: ; - silently (/unattendedaz=1) ; - to All Users (/programfiles) ; Or uninstall in case AeroZoom is found in the target folder ; (built into the logic of Setup.exe of AeroZoom) RunWait, %A_ScriptDir%\AeroZoom\Setup.exe /programfiles /unattendaz=1
-
Download and install AutoHotKey (specify 32-bit in the setup wizard to maximize compatibility of the compiled executables)
-
To compile the AutoHotkey script as an executable, download and install Compile_AHK II.
- While under repository directory (e.g.
C:\az-autohotkey-silent-setup
), right-clickAeroZoom_Unattended_Installer.ahk
and select Compile with Options which would parse parameters from AeroZoom_Unattended_Installer.ahk.ini - The ini file has an option named
Execution_Level=4
which meansrequireAdministrator
(run as administrator). This is required for the installer to carry out installation successfully. - While Compile_AHK II comes with compression feature, this article uses 7-Zip as 7-Zip reduces the file size much better (from 32MB to 2MB) in our case.
Alternatively, the default compiler which comes with AutoHotkey can be used instead of Compile_AHK II if preferred.
- While under repository directory (e.g.
C:\az-autohotkey-silent-setup
), compileAeroZoom_Unattended_Installer.ahk
using the bundled AHk2Exe utility, usually located underC:\Program Files\AutoHotkey\Compiler
as so: "C:\Program Files\AutoHotkey\Compiler\Ahk2Exe.exe" /in "AeroZoom_Unattended_Installer.ahk" /icon "AeroZoom_Setup.ico"
- Icon parameter is optional:
/icon "AeroZoom_Setup.ico"
- Icon parameter is optional:
- For me, I prefer Compile_AHK II than the official compiler in our case where the installer requires “Run as Administrator” rights. Compile_AHK II has built in support of
Execution_Levels
while the official compiler has other means to achieve it.
To each their own, choose a method with which you are comfortable. If you know of a better way, feel free to let me know!
- While under repository directory (e.g.
-
Done. Now executing
AeroZoom_Unattended_Installer.exe
would silently trigger an extraction of 7-Zip SFXAeroZoom_7-Zip_SFX.exe
and calls the inner AeroZoomSetup.exe
to install AeroZoom for all users with its unattended installation parameter/programfiles /unattendAZ=1
(which will be further explained in the third and final section)
Goal #1: The end result, AeroZoom_Unattended_Installer.exe
, is available for download here (as AeroZoom_v4.0.0.7_beta_2_silent_installer.exe
).
Like certain AutoHotkey applications, some anti-virus vendors may falsely identify the unattended installer created as undesirable. It is understandable considering the nature of this application is to perform installation and uninstallation in a silent way, which involves seemingly risky tasks such as modifying uninstallation keys in the registry.
On the other hand, I found that compiling using Compile_AHK II and/or an icon helps lower the detection rates a little bit (from 12 down to <10 out of 65 anti-virus applications on VirusTotal).
Still, this false-positive detection issue may not be completely eliminated and can be safely ignored. It is recommended to report your file to your anti-virus vendor as clean if possible.
Thanks to this Chocolatey how-to article by Coffmans and guidance from Chocolatey, I was able to figure out how to push the outer unattended installer to the Chocolatey community repository here.
The Chocolatey package specification files customized for AeroZoom have been included in the git repository downloaded in step #1 of the above section which was initially created with choco new <package name>
command after Chocolatey has been downloaded and installed on a supported Windows machine.
Let's walk through the folder structure:
C:\az-autohotkey-silent-setup\Chocolatey\AeroZoom
│ ReadMe.md
│ _TODO.txt
│ ...
│
│ // 1️⃣ package metadata
│
│ aerozoom.nuspec
│
└───tools
// 2️⃣ tasks run before [un]install scripts
chocolateybeforemodify.ps1
// 3️⃣ edited Chocolatey install script
// (for use with 'choco install')
chocolateyinstall.ps1
// 4️⃣ edited Chocolatey uninstall script
// (for use with: 'choco uninstall')
chocolateyuninstall.ps1
-
aerozoom.nuspec contains the below self-describing package metadata (click the hyperlink to see the AeroZoom example with comments)
- id
- version
- packageSourceUrl
- owners
- title
- authors
- projectUrl
- iconUrl
- licenseUrl
- requireLicenseAcceptance
- projectSourceUrl
- docsUrl
- mailingListUrl
- bugTrackerUrl
- tags
- summary
- description
- releaseNotes
-
chocolateybeforemodify.ps1 performs pre-checks prior to installation and uninstallation. For example, to prevent running processes from conflicting with setup, we can use PowerShell cmdlet
Stop-Process
to forcefully terminate processes
-
It is important to add
-ErrorAction SilentlyContinue
so that users do not see error texts when the command runs without any process to stopStop-Process -ProcessName aerozoom* -Force -ErrorAction SilentlyContinue
-
chocolateyinstall.ps1 performs silent installation by downloading and using an unattended installer, which is the outcome from the first section of this article. It should be hosted on a publicly accessible web server in order for this Chocolatey installation script to leverage
$url = 'https://github.com/wandersick/aerozoom/releases/download/4.0.2/AeroZoom_v4.0.0.7_beta_2_silent_installer.exe'
-
chocolateyuninstall.ps1 performs silent uninstallation by using a parameter specific to the application installer, which is
/programfiles /unattendAZ=1
in the case of AeroZoom. (The parameters will be further explained in the third and final section)silentArgs = "/programfiles /unattendAZ=1"
One AeroZoom-specific side-note:
-
Due to the way
Setup.exe
of AeroZoom works, forchocolateyuninstall.ps1
, I have addedSubstring
(from PowerShell) to remove/programfiles /unattendAZ=2
fromUninstallString
(in Windows registry), replacing it with/programfiles /unattendAZ=1
from$silentArgs
(inchocolateyuninstall.ps1
). Otherwise, uninstallation would not be performed in an unattended way$packageArgs['file'] = "$($_.UninstallString)".Substring(0, $_.UninstallString.IndexOf(' /'))
Once the PowerShell scripts have been edited, below are the commands for packaging, testing (installing and uninstalling), as well as pushing to the Chocolatey community repository
# create NuGet package (aerozoom.4.0.0.7.nupkg)
# ensure current directory is correct
cd az-autohotkey-silent-setup\Chocolatey\AeroZoom
choco pack
# install aerozoom.4.0.0.7.nupkg by running:
# - chocolateybeforemodify.ps1
# - chocolateyinstall.ps1
choco install aerozoom.4.0.0.7.nupkg
# uninstall aerozoom by running:
# - chocolateybeforemodify.ps1
# - chocolateyuninstall.ps1
choco uninstall aerozoom
# push to community repo (--api-key required)
choco push aerozoom.4.0.0.7.nupkg
Goal #2: Having gone through the moderation review process, AeroZoom is available on Chocolatey community repository now.
This final section walks through how to create the inner Setup.exe
acquired after 7-Zip extraction.
The steps for building the Setup.exe
would be:
-
First, let's delete
Setup.exe
in the AeroZoom folderIf not already done so, the files below can be downloaded here and extracted to a desired directory, e.g.
C:\AeroZoom
C:\AeroZoom │ AeroZoom.exe │ Readme.txt │ ... │ │ // Setup.exe will be built using below method here │ └───Data
-
Acquire the source code of
Setup.exe
, i.e. Setup.ahkIf not already done so, open Command Prompt, download or
git clone
our code repository to a desired directory e.g.c:\az-autohotkey-silent-setup
cd /d c: git clone https://github.com/wandersick/az-autohotkey-silent-setup.git
So that the following folder structure is acquired
C:\az-autohotkey-silent-setup │ Setup.ahk.ini │ ... │ │ // source code of Setup.exe of AeroZoom │ └───Setup.ahk
-
If not already done so, download and install AutoHotKey (specify 32-bit in the setup wizard to maximize compatibility of the compiled executables)
-
To compile the AutoHotkey script into an executable, download and install Compile_AHK II.
- While under repository directory (e.g.
C:\az-autohotkey-silent-setup
), right-clickSetup.ahk
and select Compile with Options, which would parse parameters from Setup.ahk.ini - The ini file contains
Execution_Level=3
which meanshighestAvailable
(run with highest privileges available) instead ofrequireAdministrator
(run as administrator) as theSetup.ahk
supports dynamically installing into current user profile (when no administrator rights are available) or installing into system directory e.g.C:\Program Files (x86)
(when administrator rights are available andSetup.exe /programfiles
is specified)
- While under repository directory (e.g.
-
Done
Goal #3: The end result, Setup.exe
, can be used to install and uninstall AeroZoom, provided that it is located in the below directory, and that suitable unattended installation parameters are passed (see Setup.exe /?
), or the installation is performed in an normal attended way (i.e. double-clicking the Setup.exe
and follow the on-screen installation instructions).
C:\AeroZoom
│ AeroZoom.exe
│ Readme.txt
│ ...
│
│ // Place the newly created Setup.exe in this folder
│ // It can install and uninstall AeroZoom here
│ Setup.exe
│
└───Data
If you would like, you may also continue from step 3 of the first section to leverage this newly created Setup.exe
to create the outer unattended installer again, which enables a totally silent installation experience of AeroZoom without the need to supply any parameters.
Instead of using a popular approach such as Windows Installer, AeroZoom implements Setup.exe
from the ground up, which has its own parameters:
/programfiles
for installing intoC:\Program Files (x86)
(orC:\Program Files
for 32-bit OS) instead of current user profile, i.e.%localappdata%
, usuallyC:\Users\{username}\AppData\Local
/unattendAZ=1
for an unattended installation
If it detects AeroZoom is already installed, the setup will perform an uninstallation instead
- If
/unattendAZ=2
or any other values, an uninstallation dialog box will also be prompted
targetDir=%localappdata%
If %1% {
; For each parameter
Loop, %0%
{
; Retrieve A_Index variable contents
param := %A_Index%
If (param="/unattendAZ=1")
unattendAZ=1
Else if (param="/unattendAZ=2")
unattendAZ=2
Else if (param="/programfiles")
{
targetDir=%programfiles%
setupAllUsers=1
}
Else
{
Msgbox, 262192, AeroZoom Setup, Supported parameters:`n`n - Unattended setup : /unattendAZ=1`n - Install for all users : /programfiles`n`nFor example: Setup.exe /programfiles /unattendaz=1`n`nNote:`n - If setup finds a copy in the target location, uninstallation will be carried out instead.`n - If you install into Program Files folder, be sure you're running it with administrator rights.
ExitApp, 5
}
}
}
During installation or uninstallation, Setup.exe
would first check a few prerequisites, such as whether files it depends on exist or not, as well as terminating any executables that could be running.
Once it is OK to proceed with installation, Setup.exe
would create shortcuts:
IfExist, %targetDir%\wandersick\AeroZoom\AeroZoom.exe
{
; Create shortcut to Start Menu (All Users)
If setupAllUsers
{
FileCreateShortcut, %targetDir%\wandersick\AeroZoom\AeroZoom.exe, %A_ProgramsCommon%\AeroZoom.lnk, %targetDir%\wandersick\AeroZoom\,, AeroZoom`, the smooth wheel-zooming and snipping mouse-enhancing panel,,
FileCreateShortcut, %targetDir%\wandersick\AeroZoom\AeroZoom.exe, %A_DesktopCommon%\AeroZoom.lnk, %targetDir%\wandersick\AeroZoom\,, AeroZoom`, the smooth wheel-zooming and snipping mouse-enhancing panel,,
}
; Create shortcut to Start Menu (Current User)
Else
{
FileCreateShortcut, %targetDir%\wandersick\AeroZoom\AeroZoom.exe, %A_Programs%\AeroZoom.lnk, %targetDir%\wandersick\AeroZoom\,, AeroZoom`, the smooth wheel-zooming and snipping mouse-enhancing panel,,
FileCreateShortcut, %targetDir%\wandersick\AeroZoom\AeroZoom.exe, %A_Desktop%\AeroZoom.lnk, %targetDir%\wandersick\AeroZoom\,, AeroZoom`, the smooth wheel-zooming and snipping mouse-enhancing panel,,
}
}
Next, Setup.exe
would write uninstallation information such as UninstallString
to the Windows Registry:
If setupAllUsers
{
; If AeroZoom was installed for all users
RegWrite, REG_SZ, HKEY_CURRENT_USER, %regKey%, UninstallString, %targetDir%\wandersick\AeroZoom\Setup.exe /unattendAZ=2 /programfiles
}
Else
{
; If AeroZoom was installed for current user
RegWrite, REG_SZ, HKEY_CURRENT_USER, %regKey%, UninstallString, %targetDir%\wandersick\AeroZoom\Setup.exe /unattendAZ=2
}
Other information it writes there are:
- Publisher
- DisplayVersion
- InstallLocation
- URLInfoAbout
- HelpLink
- InstallDate
- DisplayName
- DisplayIcon
- EstimatedSize
Regarding uninstallation, it is simply the above process in reverse, i.e. deleting shortcuts and removing the registry entries.
One thing worth mentioning is previous version of AeroZoom installer (v4.0
and before) would leave Setup.exe
under the installation directory. Since v5.0
, this has been solved by calling a minimized cmd.exe /c
to ping localhost
followed by the self-destruction, in order for Setup.exe
to delete itself.
; Remove directory content including Setup.exe that is running
; after 3 seconds using ping in a minimized Command Prompt
Run, cmd /c start /min ping 127.0.0.1 -n 3 >nul & rd /s /q "%targetDir%\wandersick\AeroZoom"
That's it.
For simplicity, only the essential parts of Setup.exe
are described above. Things that are specific to AeroZoom (e.g. removing scheduled tasks that AeroZoom may have created if specified by user) are not mentioned. For the rest, please refer to the comments in the source code file Setup.ahk
and the comments inside.
It would be my pleasure if you find this article informative. Welcome to comment if you have any question or suggestion. Have a nice day!