Automating software installs
This is my favourite software development topic: automating installs.I'm a lazy programmer, in the sense that Larry Wall talks about when he says laziness is one the three great virtues of a programmer: that means I hate doing things manually over and over again. I'd rather spend an hour writing a script to download and install a utility, then doing it manually many times on multiple machines. Automating the installation of tools also has some other benefits: (a) it ensures the consistent replication of environments and (b) it serves as documentation of exactly what was done for future reference.
Nowadays I make a lot of use of virtual machines (mostly using Hyper-V recently) for my development on Windows. This allows me to easily delete VMs and start over as often as I like. It also means I can keep my development environments separate: e.g. one VM for Java/Eclipse, one for an older version of Visual Studio, one for playing with Ubuntu, etc.
When you install a lot of development environments over and over, you need to be aware of the different tools available to help automate things. In the Linux world, automated/unattended installs are the norm (using things like apt-get), but in Windows it takes a bit more effort to automate the installation of applications.
Here's a few ideas for installing utilities/tools from the command-line (i.e. from scripts):
- Chocolatey - very cool tool to install lots of popular applications with a simple command like: cinst notepadplusplus
- Ninite - Pick the applications you want to install and it generates a single installer to package them all.
- DISM.exe - a Windows tool to Enable/Disable Windows Features from the command-line. Use this to enable things like IIS or Hyper-V from a script.
- WebPICmd.exe - Microsoft Web Platform Installer - install certain products like SQL Server Express from the command-line.
- In some cases it's easy enough to just write your own customer silent installer for a product. A lot of applications use InstallShield or other well-known installers and a lot of them behave the same way, so it's usually possible to figure out which command-line parameters to pass to the installer to do an unattend/silent install.
Using Chocolatey:
As an example of using Chocolatey on Windows, let's install the first two tools every developer needs on their machine: cURL and the 7-Zip Command Line tool for extracting archives from the command-line:
First, install Chocolatey itself (requires .NET Framework 4.0 to be installed) and then we use cinst to install curl and 7za:
C:\> powershell -NoProfile -ExecutionPolicy unrestricted -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" && SET PATH=%PATH%;%systemdrive%\chocolatey\bin
C:\>
C:\> cinst 7zip.commandline
C:\> cinst curl
And that's it!Using Web Platform Installer (webpicmd):
Let's install webpicmd with Chocolatey and then we'll install IIS Express using webpicmd:
C:\> cinst webpicmd
Now list all packages matching "IIS": C:\> webpicmd /List /ListOption:Available | findstr "IIS"
From the above we see that we're looking for the package called just "IISExpress", so install it: C:\> webpicmd /Install /Products:IISExpress /AcceptEula
Using PowerShell to install utilities:Now, for contrast, let's say you've got a clean Windows 7 machine and Chocolatey won't work yet (because the .NET framework ins't installed), then it's easy enough to roll your own automated installs of 7-Zip and cURL using PowerShell. Once we have 7za and curl, this bootstraps everything: next we can easily script the download and install .NET Framework and Chocolatey...
To download 7-Zip command-line version (7za) and extract it using PowerShell:
function Unzip-File
{
param ([string]$zipFile, [string]$destFolder)
New-Item -ItemType Directory -Force -Path $destFolder
$shell = New-Object -Com Shell.Application
$zip = $shell.NameSpace($zipFile)
$shell.NameSpace($destFolder).CopyHere($zip.Items(), 16)
}
Write-Host "Installing 7-Zip Command Line (7za)..."
$dest = "$env:ProgramFiles\7-Zip"
$destFile = "$env:ProgramFiles\7-Zip\7za.exe"
if (!(Test-Path $destFile))
{
Write-Host "Downloading 7za..."
$wc = New-Object Net.WebClient
$url = 'http://downloads.sourceforge.net/sevenzip/7za920.zip'
$file = "$env:TEMP\7za920.zip"
$wc.DownloadFile($url,$file)
Write-Host "Unzipping to: $dest"
Unzip-File $file $dest
Remove-Item $file
}
else
{
Write-Host "7za already installed."
}
Next, let's download cURL and copy it into the Windows directory (because it's a single file and then it's already in the PATH for easy use):function Unzip-File
{
param ([string]$zipFile, [string]$destFolder)
$7z = "$env:ProgramFiles\7-Zip\7za.exe"
if (Test-Path $7z)
{
$info = New-Object Diagnostics.ProcessStartInfo
$info.FileName = $7z
$info.Arguments = "x -y -o""$destFolder"" ""$zipFile"""
$info.Verb = "runas"
$proc = [Diagnostics.Process]::Start($info)
$proc.WaitForExit()
}
else
{
$shell = New-Object -Com Shell.Application
$zip = $shell.NameSpace($zipFile)
$shell.NameSpace($destFolder).CopyHere($zip.Items(), 16)
}
}
Write-Host "Installing cURL..."
$wc = New-Object Net.WebClient
$url = "http://www.paehl.com/open_source/?download=curl_732_0_ssl.zip"
$file = "$env:TEMP\curl.zip"
$wc.DownloadFile($url,$file)
Write-Host "Unzipping to: $env:windir"
Unzip-File $file $env:windir
Remove-Item $file
Now download the .NET Framework 4.5.1 using cURL (of course you can download it with PowerShell as well, but I like to use cURL):C:\temp> curl -L http://go.microsoft.com/fwlink/?LinkId=322116 -o c:\temp\NDP451-KB2858728-x86-x64-AllOS-ENU.exe
C:\temp> NDP451-KB2858728-x86-x64-AllOS-ENU /q
Resources:- Instructions for how to silently install MSI and InstallShield installers
- WPKG Silent Installers List - lots of examples of the silent install parameters for lots of popular applications.