Command Line Package Management on Windows

It was always my opinion that the “installer wizard” is a suboptimal method of delivering and deploying applications on client machines. Compared to the default (preferred) ways of installing applications on other platforms, the process of downloading and clicking through multi-step wizards seems rather outdated and convoluted.

The worst thing about wizards is that they are completely unnecessary. There is absolutely no reason to ask user whether they want to install their app to the default location if the answer is going to be yes 99% of the time. There is no reason to present the user with multiple confirmation dialogs which will abort the installation if the answer is anything other than affirmative. Installation really ought to be an atomic process – you initiate it, and it either succeeds or fails.

Linux have had centralized package repositories with unattended, one-click download, install and forget mechanisms of this type for decades now. Initially they have been mostly command line tools, but they have started getting more user friendly in recent years with graphical embellishments like the Ubuntu Software Center. Apple has its App Store which is quickly becoming the preferred method of application delivery on that platform (to the chagrin of many open source developers because of it’s locked down, walled garden nature). Windows has always lagged in this department.

Fortunately for all of us, the behemoth that was Microsoft has lost a lot of ground in recent years to their more agile competition. The beast was roused out of it’s complacent state of hibernation and finally allowed it’s engineers to start innovating (and by that I mean catching up to the rest of the software industry). And so we now have the (mostly empty) Windows Store which is Microsoft attempt to provide one-click, unattended installation. But of course in a typical Microsoft short-sightedness the store is mostly dedicated to supporting Windows 8 Metro apps, it puts stupidly restrictive requirements on the developers and it is full of rubbish. The hope however is that one day it will become a viable method that will supplant installer dialogs, especially for high profile proprietary applications.

Until that happens though, the pipe dream and the holy grail of platform-agnostic nerds is the so called “apt for windows”. A tool that would bring the apt-get functionality to the House of Microsoft. In 2007 I posted a brief overview of the few valiant attempts to make that happen. Most of them were moderately unsuccessful. The one that mirrored the desired functionality most closely was a weird command line abomination written in Pascal, and semi-abandoned years before I even found it.

What all of these apps had in common was that their philosophy. Instead of developing a framework that would deliver actual software packages and manage their installation itself they would simply set up a service that would download an installer from a cached link and run it in silent mode. That is of course a great way to quickly build up a library of popular open source packages. Hell, that’s even a good way to distribute proprietary packages via your network without breaking re-distribution laws (probably). But it is not what apt is. When you apt-get something, it can figure out dependencies and conflicts. These tools cannot do that, because they are only in the business of re-distributing ready-made installer packages which usually ship with bundled dependencies.. Or not at which point the installs fail miserably. This is obviously an inferior approach.

The only tool of this type I have actually use Ninite. But Ninite is not as much a package manager, as a rapid package deployment tool. It lets you queue bunch of untended installs then go for lunch, and their application lists are always up to date.

I sort of given up on ever finding an actual community driven package manager for Windows that doesn’t completely suck. Then the other day I saw something weird. I was looking at the Yeoman suite which is neat, but it has a laundry list of dependencies a mile long (among other things node.js, ruby, gem, git, compass, python and etc..). I was checking to make sure my Windows box has all the things needed to run it and I suddenly saw this in their installation instructions:

Yeoman Install Instructions

Yeoman Install Instructions

What? What the actual fuck? Is this real life? What kind of wizardry is this? How does this even…

Chocolatey Goodness

Yeoman team seems to have realized that while installing their tool on say Ubuntu (apt-get install yeoman) or OSX (brew install yeoman) is straightforward, it is needlessly convoluted process for Windows users. So they found a solution and adopted Chocolatey as one of their official distribution channels.

What is Chocolatey? It is the fabled apt for windows. A real one. A genuine attempt to create a honest to goodness, no-faking package manager. It is not just one guy hacking up a tool in Pascal and connecting it to a repository of links. No it is a framework that is actually leveraging existing modern technologies (namely Windows Powershell and the Visual Studio extension management toolkit called NuGet) and has a growing and rather active community.

Most importantly it is not a link repository. Depending how you build the packages they will typically install to Chocolatey managed program folder, and get their executable injected into the system path for easy access. Packages for many popular existing projects are still set up as simple silent installer links, but that’s mostly because these are re-distributions created by third parties and not the original project teams which are likely still unaware of this neat utility.

The proper packages, maintained by actual project owners are set up the right way and will actually pull down all the dependencies. So for example, if you tell Chocolatey to install Yeoman as in the example above it will actually pull down MySysGit, Ruby, Ruby Gems, Python, Node.js and all the other components it depends on. This is more or less exactly what I wanted to find in 2007 when I wrote my piece about Windows package management.

Using Chocolatey

How do you get Chocolatey? Like this:

Installing Chocolatey

Installing Chocolatey

Yep, you just paste a single line into the terminal and you are all set. Just from that alone you can get the feeling that these guys get it. They are aware of the desperate need Windows community has for no-bullshit, unattended way to install apps. It literally takes five seconds, and you are ready to roll.

From that point on, things are easy. For example, let’s say you want to install Luke’s Setup Assistant. Normally I would tell you to go to the download page, grab the zip file, unzip it and then put the executable anywhere and run it. However, now that I went ahead and made it into a Chocolatey package you can simply grab it by typing in the following on the command line:

cinst Setup-Assistant

From that point on you can simply call it up from the command line by typing: Setup-Assistant. How awesome is that?

Creating Packages

Chocolatey works great, but their documentation leaves a lot to be desired. And not because it is incomplete – it is because it is overly complex. You can probably read their Creating Packages page and their Quick Start Guide a dozen times and still have no idea where to begin. It is a convoluted mess. Thankfully, yours truly is here to straighten it all out.

Here is how you create a package for a project that is just a simple executable without an installer:

First you need to create a nuspec file. It is a simple XML file that will be named package-name.nuspec (where package-name is obviously the intended name of your package) and follows this here format:

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
  <metadata>
    <id>__PACKAGE_NAME__</id>
    <title>__FULL_NAME_OF_YOUR_APP___</title>
    <version>__VERSION_NUMBER__</version>
    <authors>__YOUR_FULL_NAME__</authors>
    <owners>__YOUR_CHOCOLATEY_USERNAME__</owners>
    <summary>__ONE_SENTENCE_SUMMARY_</summary>
    <description>__LONG_DESCRIPTION__</description>
    <projectUrl>__URL__</projectUrl>
    <tags>__TAG__ admin</tags>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
  </metadata>
  <files>
    <file src="tools\**" target="tools" />
  </files>
</package>

The id field is what you want people to type in to instal your package, and the owners field has to be your registered username on the Chocolatey package portal. The rest is up to you. I believe this is the bare bones minimal version of the file – there is more metadata you can add to it, but I stripped it out for simplicity sake.

The files section tells Chocolatey where it will find your application files, and where to put them. If you keep it as is, it will make things easy. Let’s say your app is called Foo. Here is all you need to do:

  1. Save your Foo.numspec to some folder (say %USERPROFILE%\Documents\Foo.
  2. Navigate to that folder and create sub-directory called tools
  3. Put all the files you want to deploy with your app inside tools
  4. Run cpack from the same directory where you put your numspec file.

Boom, done! That is all you need to do for very simple tools. Once you figure this out, you can move on and make more complex packages but this is the simplest method and this should be up there on page one of their docs, instead of the most complex and convoluted use case as they have it now.

Cpack will generate a numpak file which will include all your executables in a compressed format. You can now go and upload it to the Chocolatey portal and make it available to the masses. Though I recommend testing it first because the fact that the numpak file was created is not always an indication that the installation will actually work. To do a test installation you simply specify a source attribute when you run cinst:

cinst Foo -source %cd%

What happens when you install a package this way? Well, by default the executable will be placed in their own project folder under C:\Chocolatey\lib\ and a batch-file redirect will be placed in C:\Chocolatey\bin which is now in your Windows Path. The cuninst command will delete the files from both locations cleanly wiping the application of your system.

If you are re-packaging and re-distributing an existing application with its own installer, or if you need to do something complex like create shortcuts, set system variables and etc, you can put a Powershell file named chocolateyInstall.ps1 in your tools directory. It will be automatically executed during install.

There are bunch of examples of how to create install files on the Wiki but they are about as obtuse as the rest of documentation. One crucial fact the Wiki is not very clear on is that the package maintainer who chooses to use a chocolateyInstall.ps1 is also expected to provide a chocolateyUninstall.ps1 that will reverse all the changes made to the system. As you can probably guess, not many people do that. It’s probably because the docs do not yell at people for not doing it, and do not put warnings in big red letters all over the place.

So a sloppy package made by a lazy developer may actually leave your system in a less than pristine state which is the one big issue I have with the framework. Granted this is mostly a matter of package maintainer user-education and clear concise documentation which right now is a bit lacking. Still, the project is still fairly new, still growing and still gaining momentum.

Conclusion

To be honest, I really like Chocolatey it so far. It is not without flaws, but it seems to have the right attitude and ideas. It is based on modern but at the same time mature tools, and technologies. The documentation is quite lacking, but it can be fixed. The software works well for the most part, and while I’m a bit concerned about the potential un-installation problems, they are a non-issue for simple packages (like my Setup-Assitant) or re-packaged installers. These two types of packages seem to currently be the most common package types available for download, which makes using the tool relatively safe.

I actually want it to succeed, and I am willing to support it, which is why I already made one of my apps available on the network. Hopefully as we move forward we can usher this little community project to become the de facto open source package and dependency manager for the windows platform. I’m looking forward to the day the little black box with the words cinst will be a common sight on download pages for open-source and freeware apps.

This entry was posted in sysadmin notes. Bookmark the permalink.



Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>