Category Archives: VS Packages

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.

MZ-Tools Articles Series: HOWTO: Get the icons of files in the Solution Explorer

After explaining how to navigate the files of the Solution Explorer using the IVsHierarchy interface (which can be done from a package or from an add-in), as I stated I am going to show how to get the icons of the Solution Explorer items (solution, projects, files, folders, etc.):

HOWTO: Get the icons of files in the Solution Explorer
http://www.mztools.com/articles/2014/MZ2014010.aspx

I have done it with a package rather than with an add-in, but once you understand the technique you can adapt it to your extension.

Once loaded, the package provides a toolwindow that shows a treeview filled similarly to the Solution Explorer.

MZ-Tools Articles Series: HOWTO: Get an EnvDTE.DTE instance from a Visual Studio package

Two extension approaches (add-in, packages), two APIs (automation model, services)… and four combinations:

It happens that add-ins not only can use its more natural API (the EnvDTE automation model), but can also use services provided by the Visual Studio shell and packages. The EnvDTE automation model doesn’t provide a direct way to get a service but you can do it as I explained long time ago in this article:

HOWTO: Get a Visual Studio service from an add-in
http://www.mztools.com/Articles/2007/MZ2007015.aspx

And packages not only can use its more natural API (services), but can also use the EnvDTE automation model. In fact, the EnvDTE*.* reference dlls are added by default to VS Package projects!. Getting the DTE instance from a package is not difficult except for a little detail: if the package is marked to load on startup (autoload), rather than using delayed loading, it can happen that the IDE is not initialized yet and the package can’t get the DTE instance. This IDE initialization problem happens also with add-ins, which have an OnStartupComplete method and therefore there is pattern to initialize correctly an add-in. Alas, packages need to use a more complicated pattern to get notified when the IDE is fully initialized, with a trick that Microsoft explained originally in this post:

Dr. eX: Why does GetService(typeof(EnvDTE.DTE)) return null?
http://blogs.msdn.com/b/vsxteam/archive/2008/06/09/dr-ex-why-does-getservice-typeof-envdte-dte-return-null.aspx

Since I found the code of the package class somewhat dirtied with that approach, I have rewritten it with a more clean approach (using a separate class for the task):

HOWTO: Get an EnvDTE.DTE instance from a Visual Studio package
http://www.mztools.com/articles/2013/MZ2013029.aspx

MZ-Tools Articles Series: HOWTO: Autoload a Visual Studio package

One of the first things that you learn about Visual Studio packages is that by default they are loaded on demand (delayed loading), not when Visual Studio launches (because there are tons of them and it would take a lot of time, CPU and memory to load all of them).

To show their user interface (for those that have one) without loading them, Visual Studio uses a trick: the UI is created and persisted on disk at installation time; the same “permanent UI” approach that is also available to add-ins, although add-ins have also the “temporary UI” approach.

However, what if you really need to load a package on startup? (for example because it needs to listen to VS events). It happens that the answer is more complicated than just a binary flag. It is made with an attribute with a special Guid. My second article about packages explains it, with some insight of the whole mechanism from that attribute and Guid to the Windows registry where Visual Studio locates which packages to autoload and when:

HOWTO: Autoload a Visual Studio package
http://www.mztools.com/articles/2013/MZ2013027.aspx

Announcing the MZ-Tools Articles Series about Visual Studio SDK packages

One of the consequences of my decision to move to SDK packages (apart from changing the title of the blog “Visual Studio Extensibility with Add-ins” at some point) is to start the MZ-Tools Articles Series (about Visual Studio SDK packages). I have created a new section on my Resources about Visual Studio .NET extensibility page for the MZ-Tools Articles Series (about packages) that I plan to write in
the next years. My first impression is that if extensibility with add-ins is tricky, extensibility with packages is hard, because of the lack of an object model, the COM roots of Visual Studio, etc. You only have to compare the code of the projects generated by the add-in project and the package project wizards… so there is a lot to learn and to write about :-). My approach will be the same than in the MZ-Tools Articles Series about add-ins: many small articles, with sample code, focused on specific things (HOWTO, INFO, BUG, etc.), classified by area. I hope they will help not only developers starting with Visual Studio extensibility from scratch, but also developers moving from add-ins to packages.

Since all this means that I will create a lot of packages for
the articles samples, the first article is how to customize the templates used by the package wizard:

HOWTO: Changing the source code of Visual Studio Package project templates
http://www.mztools.com/articles/2013/MZ2013026.aspx