Visual Studio Team Services or VSTS is a great tool for continuous integration and continuous deployment. It is a cloud based SaaS offering from Microsoft. So most of the time you would be navigating it using a web browser like google chrome, firefox or Edge. In this blog post, we will learn how to treat VSTS like a file system using PowerShell.
Pre-requisites
You must have PowerShell version 5 or later or PowerShell core installed on your operating system for this to work.
Few words about SHiPS
SHiPS or Simple Hierarchy in PowerShell is a PowerShell provider that allows any data store to be exposed like a file system as if it were a mounted drive. In other words, the data in your data store can be treated like files and directories so that a user can navigate data via cd or dir. SHiPS is a PowerShell provider. To be more precise it’s a provider utility that simplifies developing PowerShell providers.
It is an open source project available at https://github.com/PowerShell/SHiPS. Here, you can view more details on this project as well as start contributing to it.
VSTeam PowerShell Module
VSTeam is a PowerShell module that exposes portions of the REST API for Visual Studio Team Services and Team Foundation Server. It is purely written in PowerShell only and available for Mac, Linux or Windows operating systems.
Since we must have PowerShell v5 or later installed, we can simply use Install-Module cmdlet to download and install it.
Install-Module -Name VSTeam -Confirm:$false -Verbose
Above command will also download and install dependent module SHiPS for it to work:
Create Personal Access Token or PAT in VSTS
For VSTeam module to work, we need to provide a personal access token which have proper access to VSTS projects. To create a PAT, open VSTS account, go to your profile and then select security. After this, you can create PAT. Do note that since VSTS does not stores PATs, you need to save it for later before refreshing the page.
Connecting VSTeam Module with VSTS account
We need to first import VSTeam Module into current PowerShell window before we can start using it. Let’s import it with verbose enabled so that we can also see what are the cmdlets and functions exposed by this module. Command to do the same would be:
Import-Module -Name VSTeam -Verbose
Next, we need to create VSTeam Profile. For this, we need to run the below command:
Add-VSTeamProfile -Account '[VSTSOrTFSAccountName]' -PersonalAccessToken '[personalaccesstoken]' -Name '[ProfileName]'
where VSTS account name would simple be your account name without the suffix visualstudio.com and https://:
As you might have guessed, this cmdlet basically stores your account name and personal access token as a profile for use with the Add-TeamAccount function.
Once this is done, we now need to create SHiPS drive named vsteam for our VSTS account. This can be done using:
Add-VSTeamAccount -Profile [profilename] -Drive vsteam New-PSDrive -Name vsteam -PSProvider SHiPS -Root 'VSTeam#VSAccount'
Navigate VSTS Projects like file system
First we need to navigate to the newly created PSDrive. We can do that by using below command:
cd vsteam:
Once its done, we can get list of projects in VSTS accounts by simply using get-ChildItem:

We can then see projects details as:
The ability to use VSTS as filesystem is very Powerful. Some of the more elaborate examples include getting list of builds and releases, getting list of failed and passed builds/releases, no of builds requested for a specific developer, etc.
Few examples released from Microsoft in one of the blog posts are as below:
#region find all rejected releases for specific requestor Get-ChildItem ..\Releases | Where-Object {$_.createdByUser -eq 'Stefan Stranger'} | Where-Object {$_.Environments.status -eq 'rejected'} | Select-Object createdByUser | Group-Object -Property createdByUser -NoElement #endregion #region find all rejected releases grouped by creator Get-ChildItem ..\Releases | Where-Object {$_.Environments.status -eq 'rejected'} | Select-Object createdByUser | Group-Object -Property createdByUser -NoElement | Sort-Object -Property Count #endregion #region overview of failed releases per release definition Get-ChildItem ..\Releases | Where-Object {$_.Environments.status -eq 'rejected'} | Select-Object createdByUser, @{'L' = 'Name'; E = {$_.Environments.releasedefinition.name[0]}} | Group-Object -Property Name | Sort-Object -Property Count -Descending #endregion