Saturday, 23 September 2017

Extending Team Explorer in Visual Studio 2017

Visual studio extensibility has always been a great feature in Visual Studio and enhance the entire development experience. With Visual Studio 2017, there were a bunch of very substantial changes made with respect to extensibility. Most of these changes comes from the fact that Visual Studio now supports a lighter installation version with bare minimum feature installation as default. There is also the option to have multiple installation on the same machine. So, what does it mean for for extensions? 

VS2017 extensions now following the vsix v3 file format. If you have an extension for earlier visual studio versions and you want to port it to VS2017, it means a whole bunch of changes. Here, I am going to write an extension that demonstrate extending Team Explorer. We will create a very simple extension that has a button on Team Explorer, which will open notepad.

Project Creation & Dependencies

Let's start with creating a new extensibility vsix project. You will only see the option if you had selected the VS SDK option while installing visual studio. Let's call our project TeamExplorerExtSample. Visual Studio 2017 uses .Net Framework 4.6.1, so we select this version.



Once the project is created, you will see a couple of web files and a file called source.extension.vsixmanifest, which contains extension information. We will come to this file later.

Now let's add references to the assemblies we would need to extend Team Explorer. Note that with visual studio 2017, assemblies are not added to GAC so we would need to make sure that all desired assemblies are included in the vsix. To display a navigation button in team explorer, we would need to implement the interface ITeamExplorerNavigationItem2, so we would need to add references to the following assemblies
  •     Microsoft.TeamFoundation.Controls
  •     System
  •     System.ComponentModel.Composition
  •     System.Drawing

VSIX Manifest file:

The manifest file contains information about the extension, it's dependencies, assets and pre-requisites. Double click on the source.extension.vsixmanifest to see details. To extend Team Explorer, the key thing to remember is to add the assembly containing classes that implement Team Explorer interfaces as a MEF component. This will ensure that visual studio loads it up when loading team explorer.

Our VSIX manifest file looks like this


Extending ITeamNavigationItem2

Our extension will create a button in Team Explorer that opens up the notepad application. To do this, we need to extend the ITeamNavigationItem2 interface. The interface is found in Microsoft.TeamFoundation.Control assembly that we have already referenced. We will also need to add TeamExplorerNavigationItem attribute. Our very simple class looks as below.


namespace TeamExplorerExtSample
{
       using System;
       using System.ComponentModel;
       using System.Diagnostics;
       using System.Drawing;
       using Microsoft.TeamFoundation.Controls;
       [TeamExplorerNavigationItem("C9B2CF74-0C87-4CEA-ACA9-8CC1C816D7F3", 1800)]
       public class NotepadNavigationItem : ITeamExplorerNavigationItem2
       {
              public bool IsEnabled => true;
              public int ArgbColor => 0;
              public object Icon => null;
              public string Text => "Open Notepad";
              public Image Image => null;
              public bool IsVisible => true;
              public event PropertyChangedEventHandler PropertyChanged;
              public void Dispose()
              {
                     this.Dispose(true);
                     GC.SuppressFinalize(this);
              }
              protected virtual void Dispose(bool disposing)
              {
              }
              public void Execute()
              {
                     Process.Start("notepad.exe");
              }
              public void Invalidate()
              {
              }
       }
}

As you can see, the only matter we have got in the class is a call to Process.Start to start up notepad. The navigation item appears as below


Click on the button and a new instance of notepad opens up.

Conclusion:

Admittedly. this is a very simplistic extension but contains all the steps you need to extend Team Explorer. You can add classes to add Pages, Sections and Links in Team Explorer, add icons \ images and menu items. The code sample from post is here

Friday, 22 September 2017

Shelveset Comparer now supports Visual Studio 2017

 The popular Shelveset comparer extension that I created a few years ago now support Visual Studio 2017 as well. 

It took me some time to create a compatible version due to load of things happening in personal life. There is also the added reason that I am not using Git for almost all projects I am working on, so the need for shelveset & comparisons wasn't felt as much as it would have. 

While working on creating the new version, I had to learn about very substantial changes in visual studio extensibility. I will write a blog about it. Please feel free to download the extension & give me your feedback


<ciao />

Monday, 19 December 2016

ALM Rangers blog - Sending Email Notification from VSTS/TFS Build

Please read my post on the Microsoft ALM Rangers blog regarding sending notification emails from Build vNext.

Blog Post 

Thursday, 27 October 2016

Running a VSO Build Agent on a Windows Container

In my previous blog post, I wrote about running a VSO build agent on a docker container. So, it was only logical to try it out on a Windows Container. I had a few pitfalls in my quest to do that and found an issue on my way, however. it all worked in the end.

Note: 

At the time of writing this blog, running vsts agent is not supported on Windows Nano server. I could only manage to run it on microsoft\windowsservercore image. 


Window Server 2016 and Windows Containers

Windows Server 2016 comes with a full container support powered by built-in operating system features. There is a great session on the internals of windows container on channel9. There are two mechanisms of setting up containers on Windows - Hyper-V Containers which are effectively light weight virtual machines and Windows Containers. I am going to use Windows Containers


1. Windows 2016 Virtual Machine

To host my containers, I got a Windows 2016 virtual machine going. At the time of writing this blog, Windows Server 2016 is still at Technical Preview 2 stage and new updates are coming frequently. They can be downloaded from the Microsoft website

The minimum build you will require is Windows 2016 Server build 14393.

Once you have installed windows and are on the virtual machine, open command prompt and type in winver. You will see a dialog like this. Make sure the build number is at least the required version



2. Install Containers Feature

Type in the following command in a PowerShell console window
Install-WindowsFeatures Containers
The feature needs a restart so type in the following
Restart-Computer -Force
Once the machine is restarted, continue with following 


3. Install Docker

The docker version deployed from the msi isn't supported on Windows Server 2016 yet. For me downloading the docker msi from the docker website didn't work and I got the following error


However, got it working by downloading the following zip file 
https://download.docker.com/components/engine/windows-server/cs-1.12/docker.zip 
and extracting it to Program Files. I did it by running the following in my PowerShell console 
Invoke-WebRequest "https://download.docker.com/components/engine/windows-server/cs-1.12/docker.zip" -OutFile "$env:TEMP\docker.zip" -UseBasicParsing
You will have two executable files in the extracted directory as shown



Add the directory to your path variable. 

Now register the dockerd service by typing the following
dockerd.exe --register-service

Alternate Installation Option

After installing docker, I found that the following was a better and easier way of install docker on Windows Server 2016. Type in the following in your powershell console.

Install-Module -Name DockerMsftProvider -Repository PSGallery -Force 
Install-Package -Name docker -ProviderName DockerMsftProvider
Restart-Computer -Force

Once installed, verify that docker is running fine your machine by type in the following 



docker run microsoft/sample-dotnet

You should see a message of the like "Welcome to .Net Core!" on your console window. This means that your docker instance is working fine.



4. Pulling microsoft/windowservercore image

So, this is where I got stuck a bit. I was trying to use microsoft/nanoserver, which is a fraction of a size of full windows image and support .Net Core. In the end, I found out that running vso agent on server on nano server is not supported yet.

So, I pulled the full server core image. You can do it by running



docker pull microsoft/windowsservercore

The image is about 8GB and takes some time to download. Once pull, run the image by typing in 


docker run microsoft/windowsservercore

At this stage, we are on a windows docker container running Windows 10. I checked in by typing [System.Environment]::OSVersion.Version and got the following version


Major  Minor  Build  Revision

-----  -----  -----  --------

10     0      14393  0


5. Running VSO Agent


Now that we have a running container, the steps to run VSO Agent is as simple as running it on any Windows 10 machine. 


The only complication is the lack of GUI, so I used powershell to download zip file and extract it as follows



Invoke-WebRequest https://github.com/Microsoft/vsts-agent/releases/download/v2.108.0/vsts-agent-win7-x64-2.108.0.zip -outfile vsts-agent-win7-x64-2.108.0.zip
Expand-Archive -Path .\vsts-agent-win7-x64-2.108.0.zip -DestinationPath C:\vsts-agent 

You will see the usual vsts agent's files in the destination directory. Simply type in .\config.cmd and follow instructions.









Sunday, 2 October 2016

Set up a VSO Build Agent on a Docker Container

In my last blog post, I wrote about setting up .Net core on an Ubuntu 16.04 machine. In this post, I will go a step forward and explain how to set up a container to run as your build agent.

Containers are brilliant in that they provide a rather lightweight mechanism of setting up desired software in your build agent without installing it on host machine or in a virtual machine. In this post, I will explain setting up a Docker container on a Windows 10 machine, install all the desired software  for build agent and running a build to compile an ASP.net core application on it.

This post is split into following areas
  • Setting up Docker on a Windows 10 machine
  • Create a Docker image to run Build Agent.
  • Configure and run a Build Agent on Docker.
  • Run a Build on the newly setup Build Agent.


Set up a Docker container on a Windows 10 machine

Docker on windows uses Hyper-V to create a linux virtual machine, The Docker daemon is run on this virtual machine.This means that you need at least Windows 10 professional to run Docker. We are using Windows 10 Enterprise. 
 
To install Docker visit the site https://docs.docker.com/docker-for-windows/ and install the .MSI by clicking the "Get Docker for Windows (stable)" button. The installation will setup Docker for you, by setting up a VM called MobyLinxuVM. It would also add Docker's bin directory to your path, so that the Docker command is available in your command window.
 
Every docker deployment has a "hello-world" image. To test docker, type in
docker run -it hello-world
You should see the text "Hello from Docker!" in your response.


Create a Docker image to run Build Agent

Now that docker we have a Docker instance running, lets set up a Docker image with all the software needed to run a build agent. The VSO build agent is Node.js based so installing Node.js and it's pre-requisites is a requirement. Also, since the build agent is going to build .Net Core core, we would also be installing .Net core.
 
To start with, we get a Docker image with the latest version of Ubuntu. At the time of writing this post, the latest version available was 16.04. So we start with getting this version. To do this run
docker run Ubuntu:16.04.
It would look for the instance locally and if it's not found download it from Docker hub. Once the command is complete, the Docker Ubuntu 16.04 image will appear in your “docker images” command

We now install Node.js, npm and vso agent onto the image and store it as another image. To do that the first step is to run the Ubuntu:16.04 image as a container. To do that, run the following command.
docker run -t -i Ubuntu:16.04
You will now be on command prompt of root. To run the desire software, run the following commands one after another
apt-get update
apt-get install npm nodejs
apt-get install nodejs-legacy
npm install vsoagent-installer –g
My Ubuntu 16.04 instance didn't have https protocol installed, so installed it by running
apt-get install apt-transport--https
We will also need to install git on it
apt-get install git
Now, to install .Net Core run the following
sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet-release/ xenial main" > /etc/apt/sources.list.d/dotnetdev.list'
apt-key adv --keyserver apt-mo.trafficmanager.net --recv-keys 417A0893
apt-get update
apt-get install dotnet-dev-1.0.0-preview2-003131
At this stage, the container contains all the software that you need to run a vso build agent.

Configure and run Build Agent


The only thing left to do now is to configure the build agent. The agent installer allows us to easily create multiple agents on a single server. Each agent will run inside its own folder. We create a folder called MyBuildAgent1 and uses it to run the agent. To do this run the following commands
mkdir MyBuildAgent1
cd MyBuildAgent1
vsoagent-installer
All commands so far has been run using the root user. We don't want to run the build agent to run as root, so will create a user called buildagentuser and switch to it to use it. Below are the command that you need to run.

adduser buildagentuser
chown -R buildagentuser /MyBuildAgent1

The build agent is almost ready to run. At this stage we want to commit this container to save the image. This way we can use it again.

Step out of Docker container by pressing CTRL+P followed by CTRL+Q. You will be back to command prompt. Now type in "docker ps" to view the list of containers running. You will see a response like following




Here, the ubuntu:16.04 running container has the Id "aea7e12541d5". We will commit this container to create a new image. To do this, type in the following on your command prompt
docker commit -a "Hamid Shahid" -m "Basic vso .net core build agent" aea7e12541d5 basicvsogent:v1
If you are following instructions, please use your container id. You can verify it by running "docker images". You will see the new image in the list of images



Since, we just "stepped out" of Docker container we were working now, we will now reattach it and run the build agent. To do this type in
docker attach aea7e12541d5
Now start the build agent by running
node agent/vsoagent
You will be prompted about your VSO url and the credentials to connect to. I used the following options in the prompt



The user you specify must have the service "Service Account" role in the agent pool you specified. In my case, I had added them to the VSO group "Agent Pool 1 Service Account Users".


.
Now that my build agent is now running, I will create now create a simple build definition to run the build. We had already created a simple .Net core Asp.net application.


Run a build on the new build agent

We will now create a very simple build definition and execute it on the new agent. Our build definition has three simple steps.
 
 
1) In the first step, invoke dotnet with the argument "restore".
2) In the second, invoke dotnet with the argument "build". Make sure, you set the working folder to the source directory
3) In the third step, set the contents to "**/*.dll".
 
Since, we used the Default Build Pool, set it to use the default build agent.  Now run the build and let's monitor the build agent command window. We should see messages regarding the statue of the build job.
 
 

This is so awesome. Now that we have the Docker image captured as well, we can start other build agents and distribute our build load across containers. This is far more efficient than running virtual machines as build agents.
 
The above would only work for dot net core applications. In my next post, I will write about how to set up VSO agents on Windows Containers, where we would also have the ability to build .Net applications.

Friday, 27 May 2016

Installing .Net Core on Ubuntu 16.04 LTS

The recent development by Microsoft in the ASP.Net core space is fascinating. With the introduction of ASP.Net Core 1.0 at the start of the year and then the recently released ASP.Net Core 1.0 RC2, I thought it would be a good idea to try it out on a Linux box.

The installation proved to be a bit trickier than I thought, so sharing my experience so as to help other out. The flavour of Linux I used was Ubuntu 16.04 LTS.

At the time of writing this post, the instructions present on Microsoft .Net Core website are for Ubuntu 14.04. Tried to follow the steps described on the website. However, execute dotnet failed with the following error on my machine
Failed to initialize CoreCLR, HRESULT: 0x80131500

So tried to proceed with some other steps. In general, installing .Net on Ubuntu require the following steps

1) Add .net repo to trusty sources list
2) Add key for the newly added trusted source
3) Install dotnet


To do the above, open up a terminal on your Ubuntu machine.

To add repo, run the following command
sudo sh -c 'echo "deb [arch=amd64] http://apt-mo.trafficmanager.net/repos/dotnet/ trusty main" > /etc/apt/sources.list.d/dotnetdev.list'
To add the key, run the following command
sudo apt-key adv --keyserver apt-mo.trafficmanager.net --recv-keys 417A0893
Once, the above done, it's bes to update everything by running
sudo apt-get update
 Now that everything is done, .Net can be installed by running
sudo apt-get install dotnet

The above command, however, didn't work for me. It failed with the following error


The following packages have unmet dependencies: dotnet : Depends: libicu52 (>= 52~m1-1~) but it is not installable E: Unable to correct problems, you have held broken packages.

The error is quite self-descriptive, and the answer is to install libicu package. Ran the commnad
sudo apt-get install libicu-dev

The above command installed the libicu55 on my machine, whilst .Net core has a dependency on libicu52. Fortunately, the package is available for download here.

Once downloaded, the package can be installed by running
sudo dpkg -i libicu52_52.1-3ubuntu0.4_amd64.deb 

Now that the pre-requisite is installed, installing dotnet is simply a matter of running the following
sudo apt-get install dotnet

The above worked for me this time around. To test that it installed correctly, just type dotnet new in a new folder. It will create files for your .net project.

Please Note: Make sure that you set permissions to execute downloaded files described in this post. 

Saturday, 3 October 2015

Shelveset Comparer now supports Visual Studio 2015

Last year, I created a visual studio extension that allow users to compare two shelvesets. The extension has proved to be quite popular. 

The visual studio 2015 version of the extension is out today and can be download from here

Please free free to use it and give your feedback.