Category Archives: MZ-Tools Articles Series

MZ-Tools Articles Series: HOWTO: Guessing the IDE mode (design, debug or run-time) from a Visual Studio package

As I am moving from add-ins to packages, I always like to learn how to do things using native services of Visual Studio instead of using the automation model (EnvDTE). There is an area of Visual Studio extensibility, the debugger, that is very powerful but normally extensions don’t have to use, except maybe to know which mode (design-time, debug-time, run-time) the IDE is, and when the mode changes, because maybe some commands or features should be enabled/disabled based on the IDE mode.

Eight years ago I wrote how to do that using the automation model in this article:

HOWTO: Guessing the IDE mode (design, debug or run-time) from a Visual Studio add-in or macro

Today I have written a small equivalent article doing the same using the IVsDebugger native service:

HOWTO: Guessing the IDE mode (design, debug or run-time) from a Visual Studio package

MZ-Tools Articles Series: HOWTO: Get supported frameworks and profiles of a Visual Studio version from a package

Since Visual Studio 2008, a project can be built against different .NET Framework targets, versions and profiles. When you create a Visual Studio project, you get the first chance of selecting the target .NET Framework in the New Project dialog:

NewProject

If you change your mind later, you can go to the project properties dialog and change the target .NET Framework:

ProjectProperties

This capability is known as framework multi-targetting and in recent versions of Visual Studio has exploded to allow tons of different combinations of .NET Framework versions and profiles (.Net Framework, Silverlight, Windows Phone, XBox, .NET Microframework, .NET Portable, etc. You can read more in this post of MVP fellow Stephen Cleary: Framework Profiles in .NET.

Now, we will get to the code:

A combination of .NET Framework name, version and profile is known as .Net Framework “moniker”, and it has a display name (friendly name).

You can get the .Net Framework moniker that a project is targeting using automation (EnvDTE.Project.Properties.Item(“TargetFrameworkMoniker”).Value) or using the native services of Visual Studio (IVsHierarchy.GetProperty method with the __VSHPROPID4.VSHPROPID_TargetFrameworkMoniker property)

But more difficult is to know which are the available .NET Framework monikers, the display name of a moniker, the available assemblies for that moniker, etc. The interface to use is IVsFrameworkMultiTargeting and this new article of mine shows some sample code:

HOWTO: Get supported frameworks and profiles of a Visual Studio version from a package

The interface has more methods, so check the documentation.

MZ-Tools Articles Series: BUG: Visual Studio 2008 crashes if unloaded when an add-in executes DoEvents statement on startup

Although this article applies only to the old Visual Studio 2008, I am writing it for completeness of the body of knowledge that I have built over the years about add-ins. And if you are a VSX developer who cares about your users/customers, chances are that your extension still supports Visual Studio 2005 / 2008 (which are widely used yet at companies because for some reason developers don’t always migrate to the latest version. See How many old Visual Studio versions does my add-in/package have to support?). Recently I encountered an issue in one of my scripts that remove add-in commands, and it took me a while to find that the root cause was a bug in Visual Studio 2008:

BUG: Visual Studio 2008 crashes if unloaded when an add-in executes DoEvents statement on startup

If you were in the VSX world in the VS 2008 era of add-ins, you may remember that there was another bug that caused VS 2008 to crash on startup:

BUG: Add-in causes Visual Studio 2008 crash when loaded

Fortunately both bugs were fixed in next releases.

MZ-Tools Articles Series: HOWTO: Use the Browse for Folder dialog of Visual Studio from a package

Another question in the MSDN VSX Forum about the browser for folder dialog was intriguing enough for me to investigate. If you are using the .NET Framework since version 1.0 (like me), you may remember that that version didn’t provide a class, you had to use the native class of the Win32 API Shell, which was tricky. The FolderBrowserDialog was added in .NET Framework 1.1, and since then it has this appearance:

NetFolderBrowserDialog

Despite being in Spanish (the computer that I am using to write this post), you can guess that it provides a title, a description, a treeview and an optional button to allow the creation of a new folder without leaving the dialog.

However, Visual Studio uses this other dialog to select a folder in several places:

VisualStudioFolderBrowserDialog

Again, despite being in Spanish, you can guess that it provides a treeview to the left and a listview to the right, along with the button to create a new folder and, overall, somewhat better usability.

So, the question was how to leverage that Visual Studio dialog from a package. The answer lies in the IVsUIShell.GetDirectoryViaBrowseDlg method, and in this new article of mine you have a working example, because the API is awful, with arrays of structures, memory allocation, marshaling, etc:

HOWTO: Use the Browse for Folder dialog of Visual Studio from a package

MZ-Tools Articles Series: HOWTO Unload/Reload a project from a Visual Studio package

I have created two new articles/samples from a question that I addressed in the StackOverflow forum, about unloading / reloading a project programmatically. Using the automation model (EnvDTE) I knew the answers since many years ago:

DTE.ExecuteCommand(“Project.UnloadProject”)
DTE.ExecuteCommand(“Project.ReloadProject”)

However, that approach requires that the project is selected previously in the Solution Explorer. Furthermore, having migrated my MZ-Tools add-in to a Visual Studio package I am no longer happy when I have to use the old automation model and I am eager to investigate how to do things using native services. Alas, the investigation is never easy. In this case the IVsSolution interface provides the CloseSolutionElement method, which is not intuitive because it serves to unload many things, from the solution to a document, and certainly a project too. And it doesn’t seem to provide a method to reload a project. So, I opened the MSDN documentation for IVsSolution2, IVsSolution3, IVsSolution4, IVsSolution5 and IVsSolution6 interfaces and lo and behold, the IVsSolution4 interface has the answers in the UnloadProject / ReloadProject methods. If you remember, Visual Studio 2012 introduced asynchronous solution loading (something that seemed to start in Visual Studio 2010), so the new IVsSolution4 interface introduced quite a few methods that helps with that area. So, here are the samples:

HOWTO: Unload a project from a Visual Studio Package

HOWTO: Reload a project from a Visual Studio Package

Both methods require the project guid that identifies the project in the solution (not to confuse with the project type guid). You can get the project guid from a IVsHierarchy that represents a project calling the GetProperty method with the __VSHPROPID.VSHPROPID_ProjectIDGuid property. For VS 2010, alas, when the project is unloaded the “hierarchy stub” that represents the unloaded project in the solution doesn’t implement that property (it does in VS 2012 and higher). So, the second article applies to VS 2012 and higher (because it starts with an unloaded project as the initial condition), while the first could apply also to VS 2010.

Finally, for completeness sake, given a IVsHierarchy that represents an unloaded project you can get the unload reason calling the GetProperty method with the __VSHPROPID5.VSHPROPID_ProjectUnloadStatus property, which should return a value of the _VSProjectUnloadStatus enumeration.

MZ-Tools Articles Series: HOWTO: Get Git Branches, Commits, Changes, Conflicts, etc. in the Team Explorer of Visual Studio

The next five articles / samples that I have created about Team Explorer extensibility are about getting the information contained in the Git-related pages of the Team Explorer of Visual Studio 2013.

The Branches page contains the current branch and the Published and Unpublished sections:

TeamExplorerGitBranches

To get that information from a package you need to use the Microsoft.TeamFoundation.Git.Controls.Extensibility.IBranchesExt interface. See the article:

HOWTO: Get the Git Branches in the Team Explorer of Visual Studio from a package

The Commits page contains the Incoming Commits and Outgoing Commits sections:

TeamExplorerGitCommits

To get that information from a package you need to use the Microsoft.TeamFoundation.Git.Controls.Extensibility.ICommitsExt interface. See the article:

HOWTO: Get the Git Commits in the Team Explorer of Visual Studio from a package

The Changes page contains the Included Changes, Excluded Changes and Untracked Files sections:

TeamExplorerGitChanges

To get that information from a package you need to use the Microsoft.TeamFoundation.Git.Controls.Extensibility.IChangesExt interface. See the article:

HOWTO: Get the Git Changes in the Team Explorer of Visual Studio from a package

The Resolve Conflicts page contains the Conflicts and Resolved Conflicts sections:

TeamExplorerGitConflicts

To get that information from a package you need to use the Microsoft.TeamFoundation.Git.Controls.Extensibility.IConflictsExt interface. See the article:

HOWTO: Get the Git Conflicts in the Team Explorer of Visual Studio from a package

The Commit Details page contains the commit properties and Changes section:

TeamExplorerGitCommitDetails

To get that information from a package you need to use the Microsoft.TeamFoundation.Git.Controls.Extensibility.ICommitDetailsExt interface. See the article:

HOWTO: Get the Git Commit Details in the Team Explorer of Visual Studio from a package

MZ-Tools Articles Series: HOWTO: Get the Builds / Pending Changes in the Team Explorer of Visual Studio from a package

The two first samples that I have created about Team Explorer extensibility are about getting the information contained in the Builds and Pending Changes pages.

The Builds page contains three sections: My Builds, Favorite Builds Definitions and All Build Definitions:

TeamExplorerBuilds

To get that information from a package you need to use the Microsoft.TeamFoundation.Build.Controls.Extensibility.IBuildsPageExt interface. See the following article:

HOWTO: Get the Builds in the Team Explorer of Visual Studio from a package

The Pending Changes page contains the Comment, Related Work Items, Included Changes and Excluded Changes sections:

TeamExplorerPendingChanges

To get that information from a package you need to use the Microsoft.TeamFoundation.VersionControl.Controls.Extensibility.IPendingChangesEx interface. See the following article:

HOWTO: Get the Pending Changes in the Team Explorer of Visual Studio from a package

MZ-Tools Articles Series: HOWTO: Create a toolwindow WITHOUT a ToolWindowPane class in a Visual Studio package

The usual way to create toolwindows in a package is described in my last post HOWTO: Create a toolwindow with a ToolWindowPane class in a Visual Studio package. While with add-ins only a usercontrol was required, with packages you need the usercontrol and a class that inherits from ToolWindowPane. That is, two files. When I first learned this, I found it somewhat overkill. But when I started to migrate my MZ-Tools add-in to a package, which has quite a few toolwindows, I found it totally overkill. Furthermore, requiring to decorate the package with a ProvideToolWindow attribute for each toolwindow defeats the 3rd strategy that I exposed in Strategies migrating from Visual Studio add-ins to packages, in which a core plug-in provides the features (and therefore the usercontrols for toolwindows) and a host adapter provides the communication between the host (Visual Studio) and the core plug-in. The host adapter is not aware of the features implemented by the core plug-in, and therefore it shouldn’t use specific toolwindows classes or attributes. I am aware that the ProvideToolWindow attribute and the class that inherits ToolWindowPane serve a purpose which was not available for toolwindows created by add-ins: to show automatically when VS is launched the toolwindows that were open in the last VS sessions. So, the initialization of the toolwindow must be contained in a class and not in the “click event” of the command that shows the toolwindow. But it happens that add-ins can provide that functionality too with minimal effort: when unloaded the add-in stores which toolwindows were open and when it is loaded again it shows them. Version 7.0 of MZ-Tools, being an add-in, offered this feature since it was released in 2012.

So, I wanted to create toolwindows in my MZ-Tools package like I was doing in my MZ-Tools add-in. While you can use the automation model (EnvDTE) from a package, alas, the EnvDTE80.Windows2. CreateToolWindow2 method is among the few ones that cannot be used from a package because it requires an EnvDTE.AddIn parameter, that a package cannot provide. Fortunately, the the IVsUIShell interface provides a CreateToolWindow method that can be used from packages. In this new article (equivalent to HOWTO: Create a dockable toolwindow from a Visual Studio .NET add-in) I show how to use it:

HOWTO: Create a toolwindow without a ToolWindowPane class in a Visual Studio package
http://www.mztools.com/articles/2015/MZ2015005.aspx

MZ-Tools Articles Series: HOWTO: Create a toolwindow with a ToolWindowPane class in a Visual Studio package

Creating a package with a toolwindow using the package wizard is easy because the wizard provides you an option to do it:

PackageWizard

However, the steps to create a second toolwindow are not evident. And even if you figure out the steps, knowing what they do may be difficult. And if you come from the add-ins space (where toolwindow creation uses an easier approach), toolwindows of packages is difficult stuff. This question has appeared twice in the StackOverflow forum in the last days.

I have written the following article to explain the stuff generated by the wizard when you request the toolwindow option, how the pieces are connected, and why each piece is required:

HOWTO: Create a toolwindow with a ToolWindowPane class in a Visual Studio package
http://www.mztools.com/articles/2015/MZ2015004.aspx

In my next post/article I will explain a different approach to create toolwindows in a package, without a ToolWindowPane (hence the title of this article).

MZ-Tools Articles Series: BUG: Toolwindow guid attribute value hardcoded in code generated by Visual Studio package wizard

I am these days working on a couple of articles about toolwindows. As you know, the package wizard has an option to create a toolwindow for you that creates a lot of stuff with guids, ids, attributes and so on. One thing that you notice when you learn about packages with commands is that there are duplicated declared Guids for the package guid and command set guid in the .vsct file (<symbols> section, guidVSPackagePkg / guidVSPackageCmdSet guid symbols) and in the Guids.cs file (guidVSPackagePkgString / guidVSPackageCmdSetString constants). That duplication is unfortunate but required, because those two files are compiled by different tools (the .vsct file is compiled by the Vsct.exe tool of the VS SDK and the Guids.cs file is compiled by the C# compiler). However, when you create a package with a toolwindow, you get a third guid value duplicated, but that duplication is not required.

I have documented it in this article:

BUG: Toolwindow guid attribute value hardcoded in code generated by Visual Studio package wizard
http://www.mztools.com/articles/2015/MZ2015003.aspx

and I have opened a bug report at Microsoft Connect:

VS SDK package with toolwindow: constant guid not used in code, hard-coded guid instead
https://connect.microsoft.com/VisualStudio/feedback/details/1138161/vs-sdk-package-with-toolwindow-constant-guid-not-used-in-code-hard-coded-guid-instead

To prevent the problem in the future packages that you create with toolwindows, you can fix the templates by yourself as explained in my article HOWTO: Changing the source code of Visual Studio Package project templates.

And since I have verified that this problem exists in the templates of the package wizard since VS 2005, chances are that if your package uses toolwindows it has the duplicated guid value if you haven’t noticed it.