Adding Visual Studio 2022 to Azure DevOps Server 2020
Tags: visualstudio2022, azuredevopsserver, visualstudio, azuredevopsazurepipelines
Published: 2021-12-14 18:49:04

---
title: Adding Visual Studio 2022 to Azure DevOps Server 2020
published: true
date: 2021-12-01 10:12:08 UTC
tags: VisualStudio2022,AzureDevOpsServer,VisualStudio,AzureDevOpsAzurePipelines
canonical_url: https://jessehouwing.net/adding-visual-studio-2022-to-azure-devops-server-2020/
---

 ![Adding Visual Studio 2022 to Azure DevOps Server 2020](https://jessehouwing.net/content/images/2021/12/updates.jpg)

I suspect that either the next major version of Azure DevOps Server (2022?) will bring official support for Visual Studio 2022, or - if we're lucky - the next update pack, Azure DevOps Server 2020.2.

## Download the tasks from Azure DevOps cloud

If you have access to an Azure DevOps organization, you can download the original zips straight from its stores and install them into your target project collection:

```
$tasksToDownload = @("VSBuild", "VsTest", "VsTest", "VsTestPlatformToolInstaller", 
                  "MSBuild", "DotNetCoreInstaller", "DotNetCoreCLI")

$org = "<<insert source org>>"
$pat = "<<insert PAT | Agent Pool Manage>>"
$projectCollectionUri = "https://yourtfs/yourcollection"

$url = "https://dev.azure.com/$org"
$header = @{authorization = "Basic $([Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(".:$pat")))"}

$tasks = Invoke-RestMethod -Uri "$url/_apis/distributedtask/tasks" -Method Get -ContentType "application/json" -Headers $header | ConvertFrom-Json -AsHashtable

foreach ($taskName in $tasksToDownload)
{
    $taskMetadatas = $tasks.value | ?{ $_.name -ieq $taskName }
    foreach ($taskMetadata in $taskMetadatas)
    {
        $taskid = $taskMetadata.id
        $taskversion = "$($taskMetadata.version.major).$($taskMetadata.version.minor).$($taskMetadata.version.patch)"
        $taskZip = "$taskName.$taskid.$taskversion.zip"
        Invoke-WebRequest -Uri "$url/_apis/distributedtask/tasks/$taskid/$taskversion" -OutFile $taskZip -Headers $header

        & tfx build tasks upload --task-zip-path "$taskZip" --service-url $projectCollectionUri
    }
}
```

_Download the prebuilt tasks straight from an Azure DevOps organization_

## Manually build the tasks and install them directly

If you want to use Visual Studio 2022, you can manually push the latest version of the tasks to your server. I've created a script that will do that for you:

```
# Update the list of tasks you need below
$tasksToBuild = @("VSBuildV1", "VsTestV1", "VsTestV2", "VsTestPlatformToolInstallerV1", 
                  "MSBuildV1", "DotNetCoreInstallerV1", "DotNetCoreCLIV2")
                  
# Update the collection uri below
$projectCollectionUri = "https://yourtfs/yourcollection"

$outputDir = md _build -force

& git clone https://github.com/microsoft/azure-pipelines-tasks.git --quiet
cd azure-pipelines-tasks

& git config --local pager.branch false
$branches = & git branch -r
$version = (($branches | Select-String -pattern "(?<=origin/releases/m)\d+$").Matches) | %{ [int32]$_.Value } | measure-object -maximum
$version = $version.Maximum

& git reset --hard origin/releases/m$version

& npm install
& npm install tfx-cli -g

foreach ($task in $tasksToBuild)
{
    & node make.js build --task $task
    
    $taskDir = "$outputDir/$task"
    copy "./_build/Tasks/$task" $taskDir -Recurse

    & tfx build tasks upload --task-path "./_build/Tasks/$task" --service-url $projectCollectionUri
}
```

_Install tasks directly into Azure DevOps Server project collection_

## Manually build the tasks and install them through an extension

Alternatively, build a custom extension pack and upload that (privately) to the Azure DevOps Marketplace. you'll need to create an extension manifest:

```
{
  "manifestVersion": 1,
  "name": "Visual Studio 2022",
  "version": "1.196.0",
  "publisher": "jessehouwing",
  "targets": [
    {
      "id": "Microsoft.VisualStudio.Services"
    }
  ],
  "public": false
  "description": "Visual Studio 2022",
  "categories": [
    "Azure Pipelines"
  ],
  "files": [
    {
      "path": "_build"
    }
  ],
  "contributions": [
  ]
}
```

_Create an extension manifest for your private extension._

Then run the script below to update the manifest above and package the extension with the tasks you have specified. Upload the extension to your server's local marketplace or upload the extension to the Azure DevOps Marketplace under your own publisher.

```
# Update the list of tasks you need below
$tasksToBuild = @("VSBuildV1", "VsTestV1", "VsTestV2", "VsTestPlatformToolInstallerV1", 
                  "MSBuildV1", "DotNetCoreInstallerV1", "DotNetCoreCLIV2")
                  
# Update the marketplace details below
$publisherId = "jessehouwing"
$extensionId = "visual-studio-2022-tasks"

$outputDir = md _build -force

$extensionManifest = gc "vss-extension.json" | ConvertFrom-Json
$extensionManifest.contributions = @()

& git clone https://github.com/microsoft/azure-pipelines-tasks.git --quiet
cd azure-pipelines-tasks

& git config --local pager.branch false
$branches = & git branch -r
$version = (($branches | Select-String -pattern "(?<=origin/releases/m)\d+$").Matches) | %{ [int32]$_.Value } | measure-object -maximum
$version = $version.Maximum

& git reset --hard origin/releases/m$version

& npm install

foreach ($task in $tasksToBuild)
{
    & node make.js build --task $task
    
    $taskDir = "$outputDir/$task"
    copy "./_build/Tasks/$task" $taskDir -Recurse

    $extensionManifest.contributions += @{
        "id" = "$task"
        "type" = "ms.vss-distributed-task.task"
        "targets" = @("ms.vss-distributed-task.tasks")
        "properties" = @{
            "name" = "_build/$task"
        }
    }
}

cd ..

$extensionManifest.version = "1.$version.0"
$extensionManifest | ConvertTo-Json -depth 100 | Out-File "vss-extension.json" -Encoding utf8NoBOM

& npm install tfx-cli -g
& tfx extension create --manifests vss-extension.json --output-path visual-studio-2022-tasks.vsix --publisher $publisherId --extension-id $extensionId
```

_Build private extension pack for the required tasks_

When Microsoft releases its updated tasks, simply uninstall the extension from your project collection.

# Required agent version

You will need to install the most recent agent from the [azure-pipelines-agent repository](https://github.com/microsoft/azure-pipelines-agent/releases) for it to auto-detect Visual Studio 2022, or alternatively add the capabilities to the agent manually.

These tricks will work for most tasks in the [azure-pipelines-tasks repository](https://github.com/microsoft/azure-pipelines-tasks), as long as it doesn't depend on a UI extension or service connection type that isn't available in your version of Azure DevOps Server.