Creating a Self-Updating Chocolatey Package

More and more applications ship with an automatic update mechanisms, which downloads new versions of the application as soon as they are available. A command line option such as myapp.exe --update looks nice, but the update process is tricky, as we cannot simply replace the application while its running.

A very minimalist approach, which can work for command line tools, relies on the Chocolatey package manager. Here's an example:

Package structure:

chocolateyInstall.ps1:

$ErrorActionPreference = 'Stop'

$toolsDir = (Split-Path -parent $MyInvocation.MyCommand.Definition)
$zipFile = Join-Path $toolsDir 'myapp.zip'
$batShimFile = Join-Path $env:ChocolateyInstall 'bin\myapp.bat'
$ps1ShimFile = Join-Path $env:ChocolateyInstall 'bin\myapp.ps1'

$appDir = "C:\SomeFolder\$($env:ChocolateyPackageName)\$($env:ChocolateyPackageVersion)"
$appFile = Join-Path $appDir 'myapp.exe'

Get-ChocolateyUnzip -FileFullPath $zipFile -Destination $appDir
Set-Content -Path $batShimFile -Value "@echo off~ncall ~"$appFile~" %*" -Force
Set-Content -Path $ps1ShimFile -Value "& '$appFile' ~$args" -Force

chocolateyUninstall.ps1:

$ErrorActionPreference = 'Stop'

$batShimFile = Join-Path $env:ChocolateyInstall 'bin\myapp.bat'

if (Test-Path $batShimFile) {
    Remove-Item $batShimFile -Force
}

$ps1ShimFile = Join-Path $env:ChocolateyInstall 'bin\myapp.ps1'

if (Test-Path $ps1ShimFile) {
    Remove-Item $ps1ShimFile -Force
}

$appDir = "C:\SomeFolder\$($env:ChocolateyPackageName)"

if (Test-Path $appDir) {
    Remove-Item $appDir -Recurse -Force
}

The technique works like this:

Published: 2019-06-19