Buy vs. Build & YAGNI
I was recently at the Israeli ALT.Net tools night, and I had a very interesting discussion on installers. Installers are usually a very painful part of the release procedure. The installer format for Windows is MSI, which is… strange. It takes time to understand how MSI work, and even after you got that, it is still painful to work with. Wix is a great improvement when it comes to building MSI installations, but that doesn’t make it good. Other installer builders, such as InstallSheild and NSIS are just as awkward.
The discussion that I had related to the complexity of building an installer on those technologies.
My argument was that it simply made no sense to try to overcome the hurdles of the installer technologies, instead, we can write our own installer more easily than fussing about the existing ones. The installer already assumes the presence of the .NET framework, so that make things even easier.
This is an application of a principle that I strongly believes in: Single purpose, specially built tools & components can be advantageous over more generic ones, for your specific scenarios.
Case in point, the installer. Installers are complicated beasts because they must support a lot of complex scenarios (upgrading from 5.3.2 to 6.2.1, for example), be transactional, support installation, etc. But for the installer in question, upgrade is always an uninstall of the previous version & install of the new one, and the only tasks it requires is copying files and modifying registry entries.
Given that set of requirements, we can design the following installer framework:
public interface IInstallerTask { void Install(); void Uninstall(); } public class FileCopyTask : IInstallerTask { public string Source { get;set; } public string Destination { get;set; } public void Install() { File.Copy(Source, Destination,overwrite:true); } public void Uninstall() { File.Delete(Destination); } }
And building a particular installer would be:
ExecuteInstaller( Directory.GetFiles(extractedTempLocation) .Select( file => new FileCopyTask { Source = file, Destination = Path.Combine(destinationPath, file) } ), new RegistryKeyTask { Key = "HKLM/Windows/CurrentVersion...", Value = 9 } );
This gives the ExecuteInstaller method a list of tasks to be executed, which can then be used to installer or uninstall everything.
Yes, it is extremely simple, and yes, it wouldn’t fit many scenarios. But, it is quick to do, match the current and projected requirements, doesn’t introduce any new technology to the mix and it works.
Contrast that with having someone on the team that is the Installer expert (bad) or having to educate the entire team about installer (expensive).
Comments
I did something like this about 8 years ago and it turned out to be a big mistake. Starts out fine and then BAM! you are writing an installer (and not your product). I would never do this again.
I do the simple stuff easily with WiX and it _works_. WiX is not hard or expensive to learn so I would favour that over doing my own thing. In my experience MSI etc only gets hard when your install requirements get more complex (automated rollout, selectable components etc) and at that point, your approach would probably become quite costly in dev and support time anyway.
What about ClickOnce?
I agree with Ayende - cross that Bridge to MSI Hell when you come to it.
My last project had work had serious MSI issues. We used VS Setup projects, because they were the simplest thing that could possibly work. At random points during the project, the setup project somehow stopped working for no reason and we had to recreate it from scratch. Which of course caused bugs due to files we missed when we recreated it!
But what do you do, Ayende, when you need to install .Net if it's not installed? Basically the only reason we needed msi was for the bootstrapper, as odd as it may sound.
Why not just leveraging your build language of choice? NAnt, MSBuild, Rake, Sake, ... . All the tasks are already in place, even when you need more advanced stuff like installing stuff.
All these comments indicating that building proper windows installers is a no-brainer... Sounds like Steve Jobs telling me I'm holding it wrong.
And now every system administrator on the planet hates your guts because your custom application installer doesn't handle remote, headless or automated installation, and it's compatible with the installer management suites built for MSI or other.
Before building one more crappy custom application installer go read Bynkii's rants on the subject (mostly related to Adobe's various installers for OSX), then meet him in person and tell him you've written your own custom application installer and watch as he starts flogging you with your own intestines.
Seriously, I consider this post one of the new truly dumb ones I've seen on your blog.
Unless your tool is in-house only (which allows your in-house admins to hang you in person), do not ever build your own installer or installer framework. Providing none (and just shipping a zip file with the binaries inside) is better than building your own installer.
I have to agree. Writing your own installer is a bad idea. If your install procedure is only about copying files and setting a few registry settings, then doing it with .msi isn't that hard at the end. And you get some serious advantages for free.
You can be reasonable sure that your installer will work across most versions and languages of windows (including future versions!)
The installer will take care of registering your application with windows, so users can launch your application from the start menu and uninstall it from the control panel, etc.
You don't have to build the UI
You can install the Framework as part of the install
You can do automated installs (see masklinn's comment)
If you really think the existing tools are to complicated to use and prefer your code based approach, then write it as a fluent interface arround .msi, so that you can combine the advantages of both approaches and still get an .msi file at the end.
I'm just using wix to write an installer for an ultra simple app (nothing but file copying). It's just reminding me how hideous, how disgusting the whole windows installer business is.
Which is better: provide a broken installer (due to making a mistake somewhere in the arcane clusterf**k that is the Windows Installer system). or provide a correctly working non-standard installer... I know which I'd prefer to use.
I'd say if you're writing an application that is deployed internally, fine, knock yourself out.
I still can't easily distribute Firefox via AD to all of the computers in our small office, though, without resorting to a community-packaged MSI installer, because Firefox itself uses its own installer.
Personally, I've found the sweet spot to be using WiX and trimming out the more complicated features of the Windows Installer. For example, when I deploy an update to the Web site I work on, I do everything as a 'major upgrade'. I just double-click the MSI file and wham--the old version is completely uninstalled and the new version is replaced on top of it. If someone needs to uninstall it, it appears in Add/Remove Programs without me having to do anything special.
The other trick I've learned is to maintain the WiX project as I'm building out the rest of the project--it's one of the first things that I set up. Otherwise, it's easy to get to the end of the project and say "OK so how do we deploy this thing" and realize you have days of installer configuration ahead of you -or- realize that you have created an uninstallable monster.
One of the advantages of using WiX is that I get to use a suite of installation components--custom actions that configure IIS, install certificates, restart services, etc.--that have been written by people who know what they are doing in this regard (which is not me) and are being tested and used by lots of people.
It's a sad state of affairs that there doesn't seem to really be anyone on the Windows Installer team (if there still is one) at Microsoft who is concerned with the realistic issues facing setup developers today--e.g., I need to set up a Web site and install a database, not copy some files and tweak some registry settings. It's almost as if they see themselves solely as framework providers and want to rely on vendors to make it usable. And they complain about too many people writing custom actions!
Because the installation mechanism is so strange and--beyond transaction file copies and registry transforms--useless, we end up with insane setup applications like the SQL Server Express installation wizard that acts as frontend, chaining tens of baby MSI files one after the other according to some conditional logic.
Windows Installer in 2000 was innovative; in 2010, it's pretty bad. But it's the standard and it's what we have. While I wish Microsoft would invest more time into it from a "in the trenches" usage perspective, the next best thing that we can do is concentrate our efforts onto a common toolset and library that we can all use and test, and that means using WiX when possible.
(Don't get me started on ClickOnce! =)
My two cents. I do appreciate not being afraid to do it yourself or use an alternative--just look at nhibernate vs EF or log4net vs EntLib--but I also truly believe the installation and deployment is something that is "not invented here."
Well, Microsoft only provides an framework for installations. No two installations are the same, so it's very difficult to build something that works for everybody.
And MSI is primarily used to install desktop applications for end-users. Our backoffice applications uses the Windows identity to determine the (corporate) domain of the user and use DNS SRV records to determine where the database is located. The FQDN also contains a TXT record with the name of the database used.
Here's a sniplet from a BIND zone (if formatting is preserved):
[app]._admin._tcp. IN SRV 0 5 1433 192.168.223.31
[app]._admin._tcp. IN SRV 0 9 1433 192.168.222.10
[app]._admin._tcp. IN TXT "[dbname]"
Authentication to the database (and web/wcf services) is done with integrated authentication.
Database and website deployments are, by default, complex tasks. It always never comes down to only copy the website files. If you automate deployment, you should also automate configuration.
Because I have a strong (unix/linux/bsd) system administrating background, I still have the philosophy that if a person needs an installer, the user really needs to reconsider if he's the right person to do the installation. Here's why: If you don't know the weaknesses of an application, how on earth are you gonna protect the application against 'bad people'?
I'd have to agree that writing an installer is a bad idea. MSI installations provide the user with a fairly common and consistent experience to install and uninstall your application.
Personally I opt for WiX for any end-user MSI-based installation package, and XCopy deployment for server and web-sites. I think the only time I would consider writing something like an installer would be to incorporate something like a self-updating application. But even then I'd look at possible libraries to help provide that functionality before I try and write one. ClickOnce is far too imature, and gives users no control over the installation.
Installshield used to have a product that was absolutely fabulous for simple installations back in COM/DLL Hell days called InstallShield Express. It basically broke the installation down into a checklist where you could fill in a few details, point it at a project and have a standard working installer in a couple of minutes.
My team has ditched installers 100% in favor of powershell scripts.
I've used AdvancedInstaller before which generates a MSI file; relatively painless.
I do not see a problem with xcopy type installers and powershell/cscript/.reg scripts. Writing your own complex installer is a bad idea though.
Ayende, if you don't care about being MSI compliance, look at InnoSetup. It's been around for many years. It's Open Source and extremely powerful, flexible and easy to work with.
May I suggest taking a look at projects like Wix# or Fluent-Wix? Inspired by Fluent NH, a code-only approach to building Wix based setup files. AFAIK those are MSI compliant, and the code-only approach makes it compiler checked, which is nice.
@Everyone,
It is a problem when I give a concrete example of an abstract concept.
Everyone focuses on that example, and ignore the concept I am trying to discuss.
The point of this post isn't about installers, it is about the decision to invest time to create your own specific single use impl. or to try to learn something that already does this, but which may be expensive to learn.
@Ayende,
I think that often happens but in this case your post did not read as an example relating to an abstract problem e.g.
"My argument was that it simply made no sense to try to overcome the hurdles of the installer technologies, instead, we can write our own installer more easily than fussing about the existing ones."
This reads like a pretty concrete opinion on installers.
Either way, we got some interesting comments on installers :)
@Ayende,
The caution with that direction is that when you're a hammer, everything tends to look like a nail. When you're a really good hammer, even more stuff looks like a nail.
There's bound to be limits to what individuals can invest in any given technology, whether installers, ORM, IOC, etc. In a shop where we were making shrink-wrap software we had a developer dedicated to "negotiating" with the installer and babysitting the build & deployment process. I love picking up new technology but I often don't have time to fully learn how to use them how the authors/community intend to use them, but I'd rather use them to part of their full potential than try and re-invent a basic one myself. Case in point IOC containers: I totally grok Autofac, but I don't fully gel with all of the auto-resolution etc. that Nick & Rinat has invested in it but I do see a lot of value in it as a dependency factory and let it resolve my contstructor-based dependencies on retrieved objects. I sure as hell am not going to write my own because I don't understand or want to use something to its full potential.
Not to say your example isn't a case where build isn't better than buy. If you essentially want XCopy with registry keys then a few lines of C# will suffice, but it's treading into dangerous territory. By deviating from MSI users don't have a consistent way to uninstall your application properly, sure they can delete the directory, but you're leaving registry keys around. More serious cases arise such as when I've worked on .Net projects where developers either didn't know about or understand the standard cryptography libraries, and decided to write their own password scrambler. sigh.
Installers suck - but if you want to be accepted at ANY size company you will have to use a standard one. One that uses MSI, can do in place upgrades, uninstall, etc. It had better be able to get Windows Logo certification or users will crucify you.
I think this is one of those areas people think is easy, or they don't care about. But users do care. Open source - eh, people will just build the source. Commercial - people expect certain things, like a real installer.
Look at Tarma Installer - it works, can get logo compliance and it very cheap.
Comment preview