A tale of 2 installers
For version 1.3 of SumatraPDF I’ve created a new installer.
The old installer:
This post explains why I spent the time rewriting perfectly functional installer.
How people write installers
Apparently people think that writing an installer is so difficult that it has to be simplified with a tool.
I’m here to advocate another way: write your own installers, people.
It’s not that hard.
As everyone else, I did my installers with a tool. NSIS was my weapon of choice: it’s free, (relatively) easy to learn, (relatively well) documented and since other people used it, there are examples to learn from.
NSIS is great if you don’t try to do anything that it doesn’t support out of the box. Once you stray outside the box, it’s hours spent trying to find an existing NSIS code to do what you want and if you’re unsuccessful, learning how to write code in NSIS’ awful macro language or write extension dlls.
Two issues I ran into were:
- since you can’t overwrite an executable file of a running program, it’s a good idea to kill running instance of the program in the installer, to avoid a failure in the middle of installation. There’s no built-in functionality to kill processes in NSIS. After spending way too much time trying to find an existing solution, I ended up writing an extension dll with necessary support command.
- for my .NET app I had to install .NET 4.0 runtime if it wasn’t already installed. Doing that in C code is simple: check registry keys to determine if .NET runtime is installed and execute the installer if it isn’t. This is a common problem and I found several solutions on the net but each one was slightly different, since I’m not proficient in NSIS macro language they were not easy to tweak for my purpose and they were all outdated (e.g. showing how to install .NET 2.0 while I needed .NET 4.0).
I realized that an installer doesn’t do anything complicated: it shows a window, writes a few registry keys a copies a few files. I figured that writing installer in C++ from scratch wouldn’t take more time that I’ve spent in total learning about NSIS.
I was right: it took me 9 days to write shippable version of Sumatra’s custom installer. Most of it was support code so writing future installers for my other software will be even faster since I’ll reuse most of the code.
Why write custom installer?
I already had a functioning installer so why fix something that isn’t broken? For me, the reasons where:
- provide a better user experience
- no frustration due to NSIS limitations
Installer is the first thing a potential user of your application sees. What will be his first experience with your app?
Will it be terrible, like those installers that take half an hour to unpack a few files?
Will it be boring, just like most other installers?
Or will it be remarkable, unique, extra pleasant? An experience worth talking about to others?
Writer Joe Konrath stress the importance of a good book cover. An installer is the equivalent of a great book cover.
Writing a custom installer doesn’t guarantee it’ll be exceptional, but using NSIS guarantees that it’ll be boring, just like every other installer created with NSIS.
In SumatraPDF’s case, I’ve made an usability improvement: installation is a one-click affair (old installer required a few clicks).
On the whimsicality front, I’ve added a small startup animation, which shows the program letters one by one. It’s only a small thing, I haven’t spent much time on it, but the possibilities for interesting animations are endless: scrolling text, 3d objects rotating, fireworks, star fields etc. Old school demos and processing are a rich source of inspiration for possible effects.
If you want to learn how a custom installer is done, the source is out there…