When I first heard about the SDK for widgets in Visual Studio Team Services (VSTS) I wanted to make a couple of widgets, one of these was a GitHub widget that would show some info from any GitHub repo on your VSTS dashboard. This can can be helpful when you have your source open on GitHub but still work out of VSTS.

The implementation is very simple and you can see it and contribute on GitHub on one of my projects VSTS.GitHubWidget.


Go to the Visual Studio Marketplace and head over to the Integration section and look for GitHub Widget


You can also follow this link for GitHub Widget. Now all you need to do is hit Install


Click Continue


and then click on Confirm to install the extension


and you will now have the extension installed in the account you selected.



On your dashboard click the add widget button


This will popup the widgets catalog and you will notice the GitHub widget in the list of widgets in the catalog, click on it and then click Add.


Your new widget will appear on your dashboard blank


Click on the Configure icon and the settings will fly out from the right. Enter a name for the widget as well as the username and repo that you want to get information for


Now click Save and your widget configuration will be applied to your widget and it will show you the counts for Stars, Watches and Forks on your dashboard.


When you are finished editing your dashboard the tick icon to complete editing your dashboard


Now every time you land on your dashboard you will automatically gain insights into your GitHub projects.




So if you haven't heard yet VSO Extensions are now in a private preview where you can sign up to get into the preview on extensions integration site. These extensions in the shortest sentence a supported way of doing customizations to VSO that will replace any of the "hacky" extensions that you may be playing around with at the moment like Tiago Pascal's Task Board Enhancer or maybe you have even created your own following similar steps to what I show in my TFS 2013 Customization book.

This post aims to give you a super quick guide on how to get started, you will need to go through the integrations site to really get into detail. It has most of what you will find in most posts but gives you a little something extra that most posts wouldn't have like tips on free stuff Smile

File, New Project

The easiest way to get a basic something in VSO is to just create a new project.

Create/Configure Project

We are going to create a new Type Script project


You should have something like below now


Configure SSL in IIS Express

When you have the VSO Time Ticker project selected head over to the properties window


Change SSL Enabled to True


Take note of the SSL Url that is now available to you.

Add a extensions.json

Let's add a extensions.json manifest file that will be used to inform VSO what our projects actually about


and drop in the content below, replace the baseUri property to include the port you have been assigned for SSL for the project.

"namespace": "VSO-Time-Ticker",
"version": "0.0.1",
"name": "Time Ticker",
"description": "A simple extension for Visual Studio Online of a Time Ticker",
"provider": {
"name": "Gordon Beeming"
"baseUri": "https://localhost:44300/",
"icon": "https://localhost:44300/images/some-icon.png",
"contributions": {
"vss.web#hubs": [
"id": "time",
"name": "Time",
"groupId": "home",
"order": 22,
"uri": "index.html",
"usesSdk": true,
"fullPage": false

Get the SDK

Navigate to GitHub to the samples project and grab the VSS.SDK.js file. Save a copy of that to a scripts folder inside a sdk folder and add it to your project.


Include our App js files

While we here let's build the project, show hidden folders and add the app.js and app.js.map files to the project

If you are using source control you should also at this point undo those files being added source control and then also add them to be excluded otherwise you may get a weird error when it comes time to build your project on a build server (TypeScript : Emit Error: Write to file failed...).
The reason we want these as part of the solution is so that when we do web deploy later they are deployed as well Smile.

Add our app icon

Make a images folder and add a image called some-icon.png to it

Move App js file

Move your App.ts, App.js and App.js.map into a scripts folder. If you have source you might need to re undo and ignore those extra files.


Setup index.html

This is a rather simple step, replace the reference to app.js with one to sdk/Scripts/VSS.SDK.js so it will look something like


Add the following script just inside your body tag

<script type="text/javascript">
// Initialize the VSS sdk
setupModuleLoader: true,
moduleLoaderConfig: {
paths: {
"Scripts": "scripts"

// Wait for the SDK to be initialized
VSS.ready(function () {
require(["Scripts/app"], function (app) { });
So at this stage your full index.html page will look like
<!DOCTYPE html>

<html lang="en">
<meta charset="utf-8" />
<title>TypeScript HTML App</title>
<link rel="stylesheet" href="app.css" type="text/css" />
<script src="sdk/Scripts/VSS.SDK.js"></script>
<script type="text/javascript">
// Initialize the VSS sdk
setupModuleLoader: true,
moduleLoaderConfig: {
paths: {
"Scripts": "scripts"

// Wait for the SDK to be initialized
VSS.ready(function () {
require(["Scripts/app"], function (app) { });
<h1>TypeScript HTML App</h1>

<div id="content"></div>

Update App.ts

In your App.ts file remove the window.onload function and replace it with it's body so your App.ts file will look like below

class Greeter {
element: HTMLElement;
span: HTMLElement;
timerToken: number;

constructor(element: HTMLElement) {
this.element = element;
this.element.innerHTML += "The time is: ";
this.span = document.createElement('span');
this.span.innerText = new Date().toUTCString();

start() {
this.timerToken = setInterval(() => this.span.innerHTML = new Date().toUTCString(), 500);

stop() {


var el = document.getElementById('content');
var greeter = new Greeter(el);

Run App

Running your app with ctrl + F5 you will get a blank app that does nothing Smile


Changed the url to point to the SSL version of your site just to make sure everything is working


Our App is now complete Open-mouthed smile

Install your extension

If you have signed up for the private preview you should see a tab in the admin section of your account called Extensions like so


Click Install, and then Browse 

browse for your extension.json file

Click Open and then OK


Your extension is now installed


View it on VSO

Go to a team project home page and you should now see a Time hub, click on it


Once you land here you will the time Smile


That's 1 extension in the bag but having this run on your local machine is probable not want you would want because nobody else can see it.

Publishing you app

You could buy an SSL certification but that costs a lot and most people don't have that kind of money laying around for fun apps and extensions so we'll turn to Azure. We will now right click on our project and click publish


If you setup an Azure site already you can import the publish settings but I haven't so I'm going to click on Microsoft Azure Web Apps


and then click on New (again if you have a site already you can select it in this list)


Select a name and click Create


it will now take a small bit to setup your azure resource


and then auto magically configure everything you need Smile, click Publish


After the publish is finish your site will launch


Something that you will notice is that this is http but and not https as we said earlier we require. So let's see what happens if we add a s in there Smile


Everything still works Open-mouthed smile.

Last bit of manifest changes

Now that we have a publicly accessible website running on https (for FREE) we can take that url and replace what we currently have in our manifest so it will now look like this

"namespace": "VSO-Time-Ticker",
"version": "0.0.2",
"name": "Time Ticker",
"description": "A simple extension for Visual Studio Online of a Time Ticker",
"provider": {
"name": "Gordon Beeming"
"baseUri": "https://vso-hello-world.azurewebsites.net/",
"icon": "https://vso-hello-world.azurewebsites.net/images/some-icon.png",
"contributions": {
"vss.web#hubs": [
"id": "time",
"name": "Time",
"groupId": "home",
"order": 22,
"uri": "index.html",
"usesSdk": true,
"fullPage": false
Re-install your extension


and refresh your extension in VSO


You will notice now that it obviously still works Smile, if you close Visual Studio and it still works you know it working Smile and I suppose you can check fiddler for where it's reading the files from.


For more info on VSO Extensions visit http://aka.ms/vsoextensions.

A pretty neat getting started post is also on that site at https://www.visualstudio.com/en-us/integrate/extensions/get-started/visual-studio.

Microsoft has a project out on GitHub as well that is quite advanced in the API's that it uses and can be found at https://github.com/Microsoft/vso-team-calendar.

If you want a light overview over everything then you can get their VSO Extension Samples out on GitHub as well using the link https://github.com/Microsoft/vso-extension-samples.

Complete Sample code for this post is also out on Github at https://github.com/Gordon-Beeming/VSO-Time-Ticker



Today my DotNet Pretty articles were featured on @coding4fun by Greg Duncan and one of the comments by Niner bc3tech (@bc3tech) requested that I share this solution on Chocolatey. I decided that this was a good idea and decided to share my experience Smile.

Creating a Chocolatey Account

Creating the Chocolatey account was as simple as filling a couple of common fields at https://chocolatey.org/account/Register.


In the registration mail you are given a link to Rules to be observed before publishing packages which mentions that you can host your packages with MyGet


Creating a MyGet Account

Heading over to MyGet I saw that they had a Free subscription


But they also have an offer for MVP's, ASPInsiders, Windows Azure Insiders and ALM Rangers Smile. Fitting into 2 of these categories now I decided to head over to https://www.myget.org/mvp and request a NFR license Open-mouthed smile. The extra features available on this subscription made it perfect for my community project (and ones to follow Smile). In no time I had my DotNet Pretty Package Feed up.

MyGet Build Services

The DotNet Pretty project is currently hosted out on GitHub and so I decided that I'll try out MyGet's build services which is now in preview. This was as simple as clicking on BUILD SERVICES from the menu and then on Add build sources and then from GitHub.


this poped open the Link build source dialog where I selected the DotNet Pretty project from the list and clicked Add.


From here I clicked Build and in no time the build completed


2014-10-27_18-54-50 and I had a package hosted in MyGet



Updating GitHub project to show MyGet build status

From the build services page I was able to click on copy markdown


which gave me the markdown that I could insert into the readme.md file which I did with my new favorite Markdown editor MarkdownPad 2


A quick commit added this status to the public project on GitHub


Pushing the packaged to Chocolatey

The next thing I needed to do was add a new package source to my MyGet package feed Chocolatey. I went over to the Package Sources menu and clicked on Add package source and the NuGet feed.


The next bit was very simple, I simple clicked on Presets and then Chocolatey


This then went ahead and filled in the Name and Source for me


All that was left to do was provide my Chocolatey which was my Username, Password and API Key. I also filled in some of the extra meta data for my source


Next I headed over to build services again and clicked on Push upstream


this presented a window like below


where I just clicked on Push


And received the message saying they on it Open-mouthed smile. Headed back over to Chocolatey and my package was in the list


Installing Chocolatey "Client"

On the machine I'm using I didn't have Chocolatey installed so opened up a PowerShell Command Window as Administrator (just for in case Smile) and ran the command

iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))

Installing my package

To test if my package was installer I ran the command below

choco install DotNetPretty -Pre 

which confirmed that my package now now been installed


At this point my Chocolatey package "installs" by dropping the package contents in the Chocolatey folder


In a later post I will share how to configure the installation logic for a Chocolatey script.

Update: The post can be found here (Configuring a Chocolatey Install).


I use to make a lot of TFS customizations and had to apply the template changes to multiple team projects which took a bit of time. Depending on the method you use it could be a quick or loooong process Smile. When I first started doing customizations I used the TFS Power Tools to upload changes which is a lot of effort because you are uploading one work item definition at a time into one team project.

Using Command Line

After a while I started using command line (witadmin importwitd), this was slightly faster but I found myself keeping a list commands in a txt file and then searching for the one I need when needed and run it.

A Basic PowerShell Script

I follow Martin Hinshelwood on various social media and one day he posted a blog post titled Upgrading to Visual Studio Scrum 3.0 process template in TFS 2013, although I had been at this point playing a lot with upgrading from TFS 2012 to TFS 2013 there was one piece of magic in that post that changed the way I applied process template changes up until today. It was a script that simple looped through the work item definitions in a set folder and imported them into TFS

[string] $CollectionUrlParam = $(Read-Host -prompt "Collection (enter to pick):"),
[string] $TeamProjectName = $(Read-Host -prompt "Team Project:"),
[string] $ProcessTemplateRoot = $(Read-Host -prompt "Process Template Folder:")

$TeamProjectName = "teamswithareas"
$ProcessTemplateRoot = "C:\Users\mrhinsh\Desktop\TfsProcessTemplates\Microsoft Visual Studio Scrum 3.0 - Preview"
$CollectionUrl = "http://kraken:8080/tfs/tfs01"

$TFSConfig = "${env:ProgramFiles}\Microsoft Team Foundation Server 11.0\Tools\TFSConfig.exe"
$WitAdmin = "${env:ProgramFiles(x86)}\Microsoft Visual Studio 12.0\Common7\IDE\witadmin.exe"

witds = Get-ChildItem "$ProcessTemplateRoot\WorkItem TrackingType\Definitions"

foreach ($witd in $witds)
Write-Host "Importing $witd"
& $WitAdmin importwitd /collection:$CollectionUrl /p:$TeamProjectName /f:$($witd.FullName)
$WitAdmin importcategories /collection:$CollectionUrl /p:$TeamProjectName /f:"$ProcessTemplateRoot\WorkItem Tracking\Categories.xml"
$WitAdmin importprocessconfig /collection:$CollectionUrl /p:$TeamProjectName /f:"$ProcessTemplateRoot\WorkItem Tracking\Process\ProcessConfiguration.xml"

Small Script Evolution

This worked for a while but I still had keep a couple of PowerShell files for the different projects I want to import the process templates into. I ended up adding over the next while adding a couple of additions to the script like publishing new global lists

#if there is a file with the name GlobalLists-ForImport.xml import it as Global List info for the current collection
if (Test-Path "$ProcessTemplateRoot\GlobalLists-ForImport.xml")
Write-Host "Importing GlobalLists-ForImport.xml"
& $WitAdmin importgloballist /collection:$CollectionUrl /f:"$ProcessTemplateRoot\GlobalLists-ForImport.xml"

and imported linked types

#import each Link Type for the $CollectionName
foreach($witd_LinkType in $witd_LinkTypes)
Write-Host "Importing $($witd_LinkType.Name)"
& $WitAdmin importlinktype /collection:$CollectionUrl /f:$($witd_LinkType.FullName)

ALM Rangers - vsarUpgradeGuide & vsarSAFe


The first project I joined after joining the ALM Rangers was the TFS Upgrade Guide. The last part of my contributions for the upgrade guide was a PowerShell script that could help you easily upgrade your process templates (or at least publish them) after you have made the changes required to make them compatible with TFS 2013. And for some reason it wasn't until then that I made the script target multiple team projects in the same collection.


The latest small modifications that were made to the script were for the project vsarSAFe which looks at how to modify your process template to make them SAFe aware. If you aren't familiar with SAFe it stands for Scaled Agile Framework. As I'm writing this we are showing up as Delayed on the Flight Plan but will be landing soon Open-mouthed smile


Most of the changes included here were just around adding comments and cleaning the script up a bit to make it easier to read.

So what does the script look like?

The final script (as it is now) looks like below

# Copyright © Microsoft Corporation.  All Rights Reserved.
# This code released under the terms of the
# Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)
$server = "MyTfsServer"
$port = 8080
$virtualDirectory = "tfs"
$CollectionName = "DefaultCollection"
$TeamProjectNames = @("Team Project 1", "Team Project 2", "Team Project 7", "Sample Scrum Project 1")
$ProcessTemplateRoot = "C:\templates\Microsoft Visual Studio Scrum 2013.3"

$CollectionUrl = "http://$($server)$(if ($port -ne 80) { ":$port" })$(if (![string]::IsNullOrEmpty($virtualDirectory)) { "/$virtualDirectory" })/$($CollectionName)"
$API_Version = "12.0"

# don't edit below this line

#get a reference to the witadmin executable path for the current api version
$WitAdmin = "${env:ProgramFiles(x86)}\Microsoft Visual Studio $API_Version\Common7\IDE\witadmin.exe"

#if there is a file with the name GlobalLists-ForImport.xml import it as Global List info for the current collection
if (Test-Path "$ProcessTemplateRoot\GlobalLists-ForImport.xml")
Write-Host "Importing GlobalLists-ForImport.xml"
& $WitAdmin importgloballist /collection:$CollectionUrl /f:"$ProcessTemplateRoot\GlobalLists-ForImport.xml"

#get a reference to all work item type definitions
$wit_TypeDefinitions = Get-ChildItem "$ProcessTemplateRoot\WorkItem Tracking\TypeDefinitions\*.*" -include "*.xml"

#get a reference to all work item link types
$witd_LinkTypes = Get-ChildItem "$ProcessTemplateRoot\WorkItem Tracking\LinkTypes\*.*" -include "*.xml"

#import each Link Type for the $CollectionName
foreach($witd_LinkType in $witd_LinkTypes)
Write-Host "Importing $($witd_LinkType.Name)"
& $WitAdmin importlinktype /collection:$CollectionUrl /f:$($witd_LinkType.FullName)

foreach ($TeamProjectName in $TeamProjectNames)
Write-Host "Upgrading $TeamProjectName."

#import each Type Definition for the $TeamProjectName
foreach($wit_TypeDefinition in $wit_TypeDefinitions)
Write-Host "Importing $($wit_TypeDefinition.Name)"
& $WitAdmin importwitd /collection:$CollectionUrl /p:$TeamProjectName /f:$($wit_TypeDefinition.FullName)

#import work item categories for the $TeamProjectName
& $WitAdmin importcategories /collection:$CollectionUrl /p:$TeamProjectName /f:"$ProcessTemplateRoot\WorkItem Tracking\Categories.xml"

#import work item process configuration for the $TeamProjectName
& $WitAdmin importprocessconfig /collection:$CollectionUrl /p:$TeamProjectName /f:"$ProcessTemplateRoot\WorkItem Tracking\Process\ProcessConfiguration.xml"
Write-Host "Done upgrading team projects"

This script now targets unlimited team projects in 1 team project collection, updates the categories, configuration, global lists and link types. You can grab the script off GitHub as well under my Gists (upgrade-tfs-2013-process-templates.ps1).

This takes care of all the things I need when making process template changes as I now make what ever changes I need run the script and check my changes in the browser. It doesn't get much easier than this but if you have a easier way do let me know Smile.


I was looking for a PowerShell script that would remove all media tags (post coming) from a folder of music that I have and along the way I came across a blog post called PowerShell - Automatically organizing your mp3-collection. Although this wasn't exactly what I was looking for right now I gave it a try and then thought to share it after I made a couple of changes to make it work on my machine Smile with tongue out and categorize a bit more . You can grab the script off GitHub Gist organise-music.ps1.

Basically the script will take any structure of music and organize it into the structure below


%root% / %Album Artist%

%root%/ %Album Artist% / %Album Year%

%root%/ %Album Artist% / %Album Year%/ %Album Name%

You also don't need to have all your files in a single folder for this to work, it will recursively find matching file extensions ("*.m4a", "*.m4b", "*.mp3", "*.mp4", "*.wma", "*.flc") and then work out where each file should be placed, creating directories where needed and cleaning up empty directories and extra files when finished Smile