Creating VSIX Chocolatey Packages

This post outlines how to create a Chocolatey package for a VSIX file based on the Cake for Visual Studio extension.

We will start with the package definition:

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd">
  <metadata>
    <id>my.vs2017.cake</id>
    <title>Visual Studio 2017 Cake Extension</title>
    <version>0.2.0.0</version>
    <authors>Cake Build</authors>
    <owners>Florian Winkelbauer</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Adds the Cake extension to Visual Studio 2017</description>
    <copyright>Copyright 2018</copyright>
    <tags>cake visual studio 2017</tags>
    <dependencies>
      <dependency id="chocolatey-visualstudio.extension" />
    </dependencies>
  </metadata>
</package>

Notice the declared dependency chocolatey-visualstudio.extension which allows us to install a VSIX file using PowerShell.

To create the install/uninstall scripts we will need the following information:

I have created a small helper function to fetch the above data. This function requires the checksum package to be installed:

function Get-VsixData {
    param($url, $checksumType)

    $page = Invoke-WebRequest -Uri $url

    $vsixId = ($page.AllElements |
        Where Class -eq 'vsixId' |
        Select -ExpandProperty innerHTML).Trim() -replace '"', ''

    $json = $page.AllElements |
        Where Class -eq 'vss-extension' |
        Select -ExpandProperty innerHtml |
        ConvertFrom-Json |
        Select -ExpandProperty versions

    $vsixVersion = $json.version

    $vsixUrl = $json.files |
        where assetType -match '\.vsix$' |
        Select -ExpandProperty source

    $file = Join-Path $env:TMP 'tmp.vsix'
    Invoke-WebRequest -Uri $vsixUrl -OutFile $file
    $checksum = checksum -f="$file" -t="$checksumType"
    Remove-Item $file

    return @{ VsixId = $vsixId; VsixVersion = $vsixVersion; VsixUrl = $vsixUrl; Checksum = $checksum; ChecksumType = $checksumType }
}

Here's the console output for the Cake extension:

Get-VsixData 'https://marketplace.visualstudio.com/items?itemName=vs-publisher-1392591.CakeforVisualStudio' 'sha256'

Name                           Value
----                           -----
VsixId                         3cf9b016-d63f-44ee-849d-6f3efc996134
VsixVersion                    0.2.0.0
VsixUrl                        https://vs-publisher-1392591.gallerycdn.vsassets.io/extensions/vs-publisher-1392591/cakeforvisualstudio/0.2.0.0/1503436806448/229353/4/Cake.VisualStudio.vsix
Checksum                       752A01E2A40A5DED7BED6FC16930B347205030AE693C75D3D5DC76DCCE407D02
ChecksumType                   sha256

With this information we now can create our install logic:

$ErrorActionPreference = 'Stop'

$parameters = @{
    PackageName   =  $env:ChocolateyPackageName
    VsixUrl       = 'https://vs-publisher-1392591.gallerycdn.vsassets.io/extensions/vs-publisher-1392591/cakeforvisualstudio/0.2.0.0/1503436806448/229353/4/Cake.VisualStudio.vsix'
    Checksum      = '752A01E2A40A5DED7BED6FC16930B347205030AE693C75D3D5DC76DCCE407D02'
    ChecksumType  = 'sha256'
}

Install-VisualStudioVsixExtension @parameters

And the uninstall logic:

$ErrorActionPreference = 'Stop'

$parameters = @{
    PackageName   = $env:ChocolateyPackageName
    VsixId        = '3cf9b016-d63f-44ee-849d-6f3efc996134'
}

Uninstall-VisualStudioVsixExtension @parameters

Creating and updating several VSIX packages could be further automated using the above helper function in combination with tools such as the Chocolatey Auto Updater.

Published: 2018-11-26