31 July 2015

I have created my fair share of installers in my career. Most of them created with WiX toolset, I have tried InstallShield … then moved back to WiX toolset. With WiX it was love & hate relationship, I have been jumping around the office every time I get something done, and I pulled my hair out when trying to figure why it’s not behaving the way I expect and don’t get me even started with creating a custom dialog. Creating setups is not my primary job, so the learning curve for WiX was always here. Now I haven’t touched setup project for almost a year. And I tell you, life was good! Then one day I got email with Jira ticket overview, request for new setup for v2.0 of our product. Immediately I have started thinking how I could just redo the deployment process, so no changes would be required with WiX. Then I started checking around the web if there’s ANY new products around that could help me with creating a setup. I found Advanced Installer, initially I was skeptical, how come I haven’t heard of this product before, probably because this product has some limitations … I found they offer a 30-day trial so I have decided I’ll give it a shot, I might lose some time but gain would be incredible.

First I did my research about the company and the product:

  • They ship new version almost every month - good
  • They fix bugs regularly - good
  • Documentation is written in a clear manner with nice FAQ section answering most common problems - good
  • Their developers are involved forums and they have quick and in-depth response. (example) – extra good
  • They even got a nice set of short tutorial videos on YouTube , covering most of basic and also some advanced topics, link - bonus

That’s all I could I ask from a SW vendor. My goal was to cover all the features I needed for my setup:

  • Output must be a MSI file (without bootstraper)
  • Setup must be able to upgrade when the fourth (revision) version is changed
  • Produce logs in a case of an error
  • Customization from a build script (version increase, setting the UpgradeCode, harvesting the files for features)
  • Custom dialogs
  • IIS and [MS]SQL integration
  • Upgrade should remember entered values
  • Custom actions

Spoiler alert, I did it all, and in just a few days!

So I started, having some background with MSI I didn’t have problems with terminology, properties, features, conditions where all familiar to me.

My first task was to select a web site from IIS that would require a custom dialog and some custom actions. Problem with IIS is that it needs elevated rights to query it. Previously I solved this with running a bootstrapper before MSI (yes, losing all the MSI functionality in the way). I was very surprised that guys at Advanced Installed thought of that and they have created their own custom actions for IIS queries. Setting up such query requires few clicks.

Next task was to create a custom dialog. It was drag and drop experience, just like in Windows.Forms.

I got IIS page made in few minutes, then I hooked up ListBox to right property and it was ready for a test run. I have expected the bootstraper will be created, however there was just MSI in the output. I ran the MSI, after few click on Next the UAC dialog was presented and then

I was happy, those guys really thought of everything – evaluating from the custom action to the entire installer package. The same smooth process is with the SQL using their SQL Browse.

Next step was a customization from a build script. We ship our product to multiple clients and we change the name of the product so it contains client’s name and stage name (RC, Prod,…). Also we ship some websites so we need to sync the content for any new or deleted files.

On their docs I read about their command line integration and it’s pretty straightforward. I have created a template of command file, named CommandTemplate.aic

;aic
SetVersion {version}
SetProperty UpgradeCode=""
SetProperty CLIENT_NAME="{clientName}"
SetProperty RELEASE="{release}"
Rebuild

And a powershell wrapper for building Advanced Installer project, build.ps1

function CreateCommandFile($version, $implementationName, $release, $guid)
{
    $template = Get-Content .\CommandTemplate.aic

    $command = $template -replace "{version}", $version
    $command = $command -replace "{implementationName}", $implementationName
    $command = $command -replace "{guid}", $guid
    $command = $command -replace "{release}", "-$release"
    $command | Set-Content Command.aic
}

function CreatePathVariables()
{
    $currentDirectory = pwd | select -ExpandProperty path

    $xml = [xml](Get-Content .\PathVariables.xml)
    $node = $xml.PathVariables.Var | where { $_.Name -eq "SETUP_ROOT"}
    $node.Path = "$currentDirectory"
    
    $node = $xml.PathVariables.Var | where { $_.Name -eq "ARTIFACTS_ROOT"}
    $node.Path = [string](join-path $currentDirectory "Artifacts")

    $xml.Save("PathVariablesEdited.xml")
    
}
$exe = "C:\Program Files (x86)\Caphyon\Advanced Installer 12.2.1\bin\x86\AdvancedInstaller.com"
$aip = "Solution.aip"

# Creating command file
CreateCommandFile "2.4.2.11" "Customer" "RC" "347508b6-aa6a-49b3-8491-3ea050ca1af4"

# Creating variables
CreatePathVariables
& $exe /loadpathvars .\PathVariablesEdited.xml

# Harvest Backend
& $exe /edit $aip /ResetSync APPDIR\Backend
& $exe /edit $aip /NewSync APPDIR\WebApi .\Artifacts\Backend
# Harvest Client
& $exe /edit $aip /ResetSync APPDIR\Client
& $exe /edit $aip /NewSync APPDIR\WebPortal .\Artifacts\Client

# Building
& $exe /execute $aip .\Command.aic


# Clean
Remove-Item .\Command.aic -Force
Remove-Item .\PathVariablesEdited.xml -Force 

This script loads current PathVariables, these variables are locations for all the folders that are required for successful installer build. So I can just drop artifacts of my solution into the Backend and Client directories of the Artifacts directory.

Also in this build script I do a folder synchronization for two features. In WiX community this is called harvest. Synchronization takes everything in the directory and include it in setup.

One thing I never got working in WiX is the Repair mode. So next thing I wanted to try how difficult would that be in Advanced Installer, also I wanted to remember property values for future upgrade scenarios. In Dialogs view there is a clean folder structure that describes the setup flow.

Persistence properties are automatically saved in registry and are pre-filled when doing upgrades or maintenances. You can set property to persistent in the Edit Property dialog

Just a single click, in WiX I had to save and read those values from a custom action.

One requirement is mandatory for my boss, he wants a log file for every single installation. In WiX, of course, you do that within a bootstrapper. Advanced Installer has an option in the Install Parameters window, to set the Enable verbose logging in the Installation Options. This does exactly what most of the people need, if error occurs, produce a log, if everything goes smoothly, no log is required. When setup finishes, Show log checkbox on the Finish dialog opens the log.

Custom actions are supported, there are plenty of them built-in, which is pretty nice, demo how to use custom actions (e.g. PowerShell script run) can be found in their YouTube account.

So I got everything covered, except upgrade when 4th part (revision) of the version number changes. MSI doesn’t recognize fourth number, and some heavy hacks were required in WiX to support this. Their amazing documentation came to rescue and again, the solution was just few clicks away. More info can be found http://www.advancedinstaller.com/user-guide/faq-upgrade.html#question65

I have to say I didn’t expect such sophisticated tool, Ii’m pleased that guys at Caphyon are doing such great job, my company is buying this product and we’re rewriting all installers from WiX to Advanced Installer.

I’m pretty glad that we’re are finally exiting the era of XML programming.



blog comments powered by Disqus