MZ-Tools Articles Series: HOWTO: Initialize the usercontrol of a toolwindow from a Visual Studio package.

Although creating a toolwindow and hosting a usercontrol in a Visual Studio package seems easy (thanks to the package wizard), initializing the usercontrol to receive an instance of your package (or the value of some property of your package) is somewhat tricky.

I have seen this question from time to time in the forums and until now my (wrong) answer was to use the ShowToolWindow event handler method of the package to get the instance of the usercontrol from the ToolWindowPane (using its Content property for WPF usercontrols and its Window property for Windows Forms usercontrols). Once you have the usercontrol instance, you can call a method of the usercontrol to pass it any piece of information that you want to initialize it. I won’t show the code because it is an incorrect approach due to this: when using a toolwindow in a package, if the last time that you closed Visual Studio the toolwindow was visible, the next time that you open Visual Studio the toolwindow will be shown automatically without the ShowToolWindow event handler method being called (so your usercontrol wouldn’t be initialized in that scenario).

This didn’t happen with add-ins (toolwindows were not open automatically in the next session if left open in the previous session). But with packages it happens, so the ShowToolWindow method of the package is not the proper place to initialize the usercontrol. Then, it must be done in the MyToolWindow class, which creates the usercontrol and it is always called, and fortunately it has a Package base property that you can use to get the instance of your package. Alas, that instance is null in the toolwindow constructor. My latest article shows a workaround:

HOWTO: Initialize the usercontrol of a toolwindow from a Visual Studio package
http://www.mztools.com/articles/2014/MZ2014016.aspx

MZ-Tools Articles Series: HOWTO: Host a Windows Forms usercontrol in a toolwindow from a Visual Studio package.

When you create a toolwindow with the Visual Studio package wizard, a Windows Presentation Foundation (WPF) usercontrol is used. If you are migrating an add-in to a package, chances are that your toolwindows use Windows Form usercontrols and you don’t want to change the forms technology (migrating the add-in to a package is enough work…). It happens that the way to host a usercontrol in a toolwindow is different for WPF and Windows Forms. In the former case you only have to assign the Content property to the instance of the usercontrol. If you do the same in the latter case, nothing happens (you don’t even get an exception). For Windows Forms usercontrols, you need to override the Window property to return the instance of the usercontrol.

My latest article explain it with sample code:

HOWTO: Host a Windows Forms usercontrol in a toolwindow from a Visual Studio package.
http://www.mztools.com/articles/2014/MZ2014015.aspx

SLaks.Blog articles about Visual Studio extensibility and versioning

I have updated my web site Resources about Visual Studio .NET extensibility with some links to the SLaks.Blog (of former MVP fellow Schabse Laks) about Visual Studio extensibility and versioning.  They are the following:

MZ-Tools Articles Series: PRB: ‘Can not find the installation for VS SDK’ error using MSBuild of TFS to compile Visual Studio Package

I am using Visual Studio Online since a couple of months ago to great satisfaction adopting more and more of its features. One of them is continuous integration (CI) and gated check-ins. Yesterday I tried to check-in a modification of one of my add-ins converted to a Visual Studio package for the first time and the build failed with this error:

C:\Program Files
(x86)\MSBuild\Microsoft\VisualStudio\<version>\VSSDK\Microsoft.VsSDK.Common.targets
(line): Can not find the installation for VS SDK.

C:\Program Files
(x86)\MSBuild\Microsoft\VisualStudio\<version>\VSSDK\Microsoft.VsSDK.Common.targets
(line): The “FindVsSDKInstallation” task failed unexpectedly.
System.ArgumentNullException: Value cannot be null. Parameter name:
path1 at System.IO.Path.Combine(String path1, String path2)

C:\Program Files
(x86)\MSBuild\Microsoft\VisualStudio\<version>\VSSDK\Microsoft.VsSDK.Common.targets
(line): The “FindVsSDKInstallation” task’s outputs could not be
retrieved from the “IncludesPath” parameter. Value cannot be null.
Parameter name: path1

Searching the web I found several workarounds but some of them were too involved. I have documented the most easy ones to apply:

PRB: ‘Can not find the installation for VS SDK’ error using MSBuild of TFS to compile Visual Studio Package
http://www.mztools.com/articles/2014/MZ2014014.aspx

MZ-Tools Articles Series: HOWTO: Create a solution from a Visual Studio package.

During the last years I have written small, practical, articles with code samples about how to do things with Visual Studio add-ins like this:

HOWTO: Create a solution from a Visual Studio add-in
http://www.mztools.com/articles/2011/MZ2011001.aspx

And in the next years I hope to write lots of equivalent ones for Visual Studio packages, like this new one:

HOWTO: Create a solution from a Visual Studio package.
http://www.mztools.com/articles/2014/MZ2014013.aspx

MZ-Tools Articles Series: HOWTO: Get information about the loaded solution from a Visual Studio package.

Following with the second and third strategies migrating from Visual Studio add-ins to packages, after defining and implementing an IHost interface, likely you will continue with an ISolution interface with properties like:

public interface ISolution
{
   bool IsOpen { get;}
   string Name { get;}
   string FullFileName { get;}
   ...
}

Using the automation model (EnvDTE) you would use DTE.Solution to get the solution object and then the Solution.IsOpen, Solution.Name, Solution.FullName or Solution.Properties.Item(“Path”).Value properties and so on.

In this small article I explain how to use the IVsSolution interface of the SVsSolution service to avoid the use of EnvDTE.Solution to get some information about the loaded solution:

HOWTO: Get information about the loaded solution from a Visual Studio package.
http://www.mztools.com/articles/2014/MZ2014012.aspx

MZ-Tools Articles Series: HOWTO: Get information about the Visual Studio IDE from a Visual Studio package.

Two of the three strategies that I explained in my last post Strategies migrating from Visual Studio add-ins to packages involve to avoid the use of the automation model (EnvDTE). When you use an EnvDTE object, basically you do one of three things: to get/set properties, to invoke methods to perform actions and to get events. So, you need to learn how to do that with Visual Studio interfaces of services.

If you follow my third strategy, likely you will define an interface named IHost with some properties like this:

public interface IHost
{
   string RegistryRoot { get; }
   string InstallationFolder { get; }
   …
}

When implementing the RegistryRoot property of that interface using EnvDTE, you would use the DTE.RegistryRoot property. And to implement the InstallationFolder property, you would read the value “ProductDir” of the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\<version>\SetupVS.

When implementing those properties of the interface in your package, in this small article I explain how to use the IVsShell interface of the SVsShell service to avoid the use of EnvDTE.DTE to get some information about the Visual Studio IDE (the shell).

HOWTO: Get information about the Visual Studio IDE from a Visual Studio package.
http://www.mztools.com/articles/2014/MZ2014011.aspx

Strategies migrating from Visual Studio add-ins to packages

Since the next Visual Studio version (“14”) will remove add-ins, the time has come for those of us still providing our products as add-ins (such as my MZ-Tools productivity add-in) to move to Visual Studio packages. In my view, there are three strategies:

In the first one, you change the minimal number of things in your add-in to convert it to a package. For example, some areas that need to be changed are:

  • Creation of commands (remember that commands are not UI items).
  • Creation of UI items (toolbars, menus, context menus, buttons, etc.).
  • Creation of toolwindows.

Although they are tricky, the Visual Studio package wizard will get you started about those areas. But there is another thing that your add-in surely does: to respond to events to perform some actions. And for that it uses events provided by the automation model (EnvDTE). Furthermore, add-ins are totally based on the automation objects (EnvDTE.DTE, EnvDTE.Solution, EnvDTE.Project and so on). Although you can get an instance of the root DTE object as explained in HOWTO: Get an EnvDTE.DTE instance from a Visual Studio package, there is a another way.

In the second strategy, you get rid of the Visual Studio automation (EnvDTE). The automation model was provided initially in Visual Studio .NET 2002 to support add-ins, macros and wizards. Macros were removed in Visual Studio 2012. And add-ins will be removed in Visual Studio “14”. Microsoft packages don’t use very much EnvDTE. So, which will be the future of EnvDTE? Not a brilliant one, I guess. Likely in some Visual Studio version it will be deprecated and in some other version it will be removed and then you will have to change again your package because of its heavy dependency on EnvDTE. So, you can leverage the migration from a Visual Studio add-in to a package to do things in the natural way of packages, using Visual Studio services and interfaces. They are not easy because 1) there are tons of services and are difficult to discover (in the automation model you can use the Object Browser to discover classes, methods, etc.) and 2) they still show its C++/COM nature in some cases (not a friendly API).

In the third strategy you realize that your Visual Studio extension has a strong dependency on the Visual Studio assemblies, either EnvDTE or the ones used by packages (Microsoft.VisualStudio.*). Furthermore, they can change on each Visual Studio version. To avoid this, my approach is to split my “plug-in” in two assemblies:

  • One assembly has the features of my product and depends only on abstractions such as IHost, ISolution, IProject, IProjectConfiguration, etc. with the methods, properties and events that I define. This assembly only references some assemblies of the .NET Framework. In my case (for the future MZ-Tools 8.0), this assembly has 80% of the code and has only five references: System, System.Data, System.Drawing, System.Windows.Forms and System.Xml.
  • The other assembly is an “adapter” for a Visual Studio version that provides the implementation of the interfaces IHost, ISolution, etc. In my case it has 20% of the code and I have adapters not only for Visual Studio (all versions as add-in), but for the VBA editor (32-bit & 64-bit) of Office, VB 6.0 and VB 5.0. I even have a stub adapter to be used in ultra-fast “integration” tests. So, I only have now to create an adapter for Visual Studio as a package. But the core of my product (80%) is not affected.

To get you the idea, this is the structure of the solution:

MZTools8SolutionExplorer

And my object model has 30 interfaces approx.:

ObjectModel

Needless to say, my implementation of those interfaces in the adapter for VS as package will not use the automation model EnvDTE. In the next posts and articles of the MZ-Tools Articles Series I will explain how to do things in the native way of packages, as I learn about it.

Visual Studio “14” CTP: add-ins are gone

I blogged some time ago about Add-ins officially deprecated in Visual Studio 2013 and given that MZ-Tools is still an add-in, after the announcement of Visual Studio “14” CTP I was curious yesterday if it would still support add-ins. I had a very busy day at the office so I couldn’t check it until night at home. In the past it would mean to download the .iso file, setup a virtual machine on my computer, install it, etc. but now with Windows Azure I was already at bed about to sleep when I grasped my iPad, connected to my Windows Azure account, created a virtual machine with the VS 14 CTP from the gallery, installed the Microsoft Remote Desktop client app for iPad, connected to the machine and launched Visual Studio (amazed that all that was possible with a tablet and 10 minutes of time, really cool). Then I clicked the Tools menu and I saw that the Add-In Manager is gone, which means that Visual Studio “14” won’t support add-ins at all and you will have to migrate your add-in to a Visual Studio package. Incidentally, Microsoft has just released the Visual Studio 2013 SDK Samples.

Extending Visual Studio Online

Since I adopted Visual Studio Online a few weeks ago, I am more and more happy with it. I have also recently adopted a help desk online software called SmarterTrack (from SmarterTools, the same company that provides SmarterMail) to support questions from users of my MZ-Tools family of add-ins. I am now at the point of automating the creation of TFS work items from some help desk tickets (bugs or feature requests). SmarterTrack allows you to include custom menus in the window of a ticket than can make an http get call (although not a http post call with JSON). But I can make an http get call to some page of my server and then make whatever I want once I extract the parameters.

Fortunately Microsoft made Visual Studio Online fully extensible, as recently announced at TechEd North America 2014. There is a new Visual Studio Online Integrate portal with the scenarios that you can use:

  • Calling Visual Studio Online from any other tool through REST APIs with OAuth.
  • Make Visual Studio Online to call any tool when an event happens (without the need of polling).

There is also a lot of 3rd party tools that provide integration with Visual Studio Online, as explained in this TechEd session:

Using Third-Party ALM Solutions along with Visual Studio Online
http://channel9.msdn.com/Events/TechEd/NorthAmerica/2014/DEV-B368

Investigating how to use the REST APIs of Visual Studio Online I found yesterday this upcoming ebook of MVP fellows Jeff Bramwell and Mike Douglas:

TFSVSOExtensibility

Extending Team Foundation Server And Visual Studio Online
http://www.codesmartnothard.com/2014/05/19/ExtendingTFSAndVisualStudioOnlineEBook.aspx

And to buy it:

https://leanpub.com/tfsapibook

Only some chapters are already written but the table of contents is promising and I am sure it will be great:

Part I – The Basics

Chapter 1: Overview of Team Foundation Server
Chapter 2: A History of Team Foundation Server APIs
Chapter 3: A REST Primer

Part II – Using the Team Foundation APIs

Chapter 4: Our First REST API Call
Chapter 5: Work Items
Chapter 6: Team Foundation Version Control
Chapter 7: Git
Chapter 8: Build Definitions
Chapter 9: Builds
Chapter 10: Workspaces
Chapter 11: Team Room Management
Chapter 12: Team Room Activities
Chapter 13: Reporting and Charts
Chapter 14: Projects and Teams
Chapter 15: Service Hooks

Part III – Other Resources

Chapter 16: Using Fiddler
Chapter 17: Using OAuth

Resources

Given the lack of books about Visual Studio Extensibility (add-ins, packages, DSL, etc.) after all these years it is great that a book about Visual Studio Online Extensibility is appearing so early (and so cheap!).

VS SDK, packages, add-ins, macros and more…