Some implications of the new modular setup of Visual Studio 2017 for VSX developers

As you may already know, VS 2017 (formerly VS “15”) introduces a couple of very welcomed changes:

  • It provides a new modular setup that allows you to decide which tools (“workloads”) you want to install and, most importantly, which ones you don’t want at all. The consequence is that installing VS 2017 is much, much faster (unless you install a lot of workloads, of course). This suggestion had almost 2,000 votes on UserVoice. For VSX developers like me that already have six versions of Visual Studio installed (from VS 2005 to VS 2015) on the main dev machine (not counting isolated installations on virtual machines) and know how painful each installation is, this is big news.
  • Visual Studio 2017 allows to coexist several editions on the same machine. So, you can have VS 2017 Community Edition, VS 2017 Professional Edition and VS 2017 Enterprise Edition. This may not be very useful for end users, but for VSX developers it allows you to test your extension (which needs to declare the minimum supported edition in the Vsix manifest) on the three editions on the same computer. Here you can see my computer with the Community edition installed (notice the familiar “Common7” folder inside the “Microsoft Visual Studio\2017\Community” folder):

vs2017communityinstallation

If you want the details about the new setup experience, the official posts from Microsoft about this on the Visual Studio blog are the following:

Faster, Leaner, Focused on Your Development Needs: The New Visual Studio Installer

Visual Studio “15”: Installing Just What You Need

Anatomy of a Low Impact Visual Studio Install

On the Road to Release: Redesigning Visual Studio Installation

Visual Studio “15” Preview 4

But not only that. Visual Studio 2017 is also much more isolated and resilient. It doesn’t install Visual Studio assemblies in the Global Assembly Cache (GAC) and it doesn’t use for the most part the main Windows Registry. In the past (since VS 2010, see my post The strange case of the registry key HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0_Config\Projects\{C8D11400-126E-41CD-887F-60BD40844F9E}), Visual Studio redirected HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\<version> to HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\<version>_Config, to allow installation of extensions through .pkgdef files without admin rights, etc. Now, VS 2017 uses its own private registry. See how empty is the regular HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\15.0 key on my machine and notice that there is no 15.0_Config key:

vs2017config

Instead, the VS 2017 private registry is stored in your AppData folder:

privateregistry

Fortunately, you can use regedit.exe to load a private hive. You need to select the HKEY_USERS node, and click the File > Load Hive… menu. You select the privateregistry.bin file, give a name to the hive (I entered “VS2017PrivateRegistry”) and now you can see the 15.0<id>_Config key populated as usual (note: use File > Unload Hive when done):

vs2017privateconfig

Hopefully all this isolation and resilience can prevent the problems that I suffered with VS 2015 when my Surface Pro 4 crashed at boot time due to a buggy antivirus update (I never recovered VS 2015).

So far, so good, but all this will cause some issues to VSX developers. I adapted my MZ-Tools extension to run in Visual Studio 2017 some weeks ago and I am these days migrating my old .NET-based custom builder for MZ-Tools to fully embrace MSBuild and hopefully to use a separate Windows Azure build server, better environment/workspaces isolation, etc.

The changes above can cause some trouble:

  • The location of devenv.exe for Visual Studio 2017 has changed, and can be several of them.
    As explained above, you can have now several Visual Studio 2017 installations on your machine. In the past (until Visual Studio 2015) you could query the HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\14.0, InstallDir entry, to get the (only) installation folder for Visual Studio (2015). Now, there can be several Visual Studio 2017 installation folders (Community, Professional, Enterprise), and you cannot query the registry directly. Instead, the official approach is to use some interop assemblies (Microsoft.VisualStudio.Setup.Configuration.Interop) provided by Microsoft to enumerate the Visual Studio 2017 installations. See the post Changes to Visual Studio “15” Setup and the Microsoft/vs-setup-samples samples on GitHub. Of course, for your own use on your own build script you can hardcode paths ;-).
  • External processes cannot read Visual Studio 2017 registry entries directly.
    Extensions can read Visual Studio 2017 registry entries from the private registry in a transparent way, because being dlls, they run in-process with devenv.exe and leverage the redirection provided by Visual Studio. But out-of-process executables or scripts need to use the  RegLoadAppKey function. See the section “Change: Reduce registry impact” in Breaking Changes in Visual Studio 2017 extensibility.
  • The location of MSBuild for VS 2017 has changed, and can be several of them.
    In the past (until Visual Studio 2015), the path of MSBuild was “C:\Program Files (x86)\MSBuild\<version>”, where <version> was “4.0”, “12.0” (VS 2013), “14.0” (VS 2015). There is no “15.0” folder there for VS 2017. Instead, MSBuild for VS 2017 is installed in the folder “C:\Program Files (x86)\Microsoft Visual Studio\2017\<edition>\MSBuild\15.0”, where edition can be “Community”, “Professional” or “Enterprise”. Again, for your own use on your own build script you can hardcode the path, but if you want to use a more proper way, you need to get the VS 2017 installation folder as explained above and concatenate “MSBuild\15.0”. Or you can wait until Microsoft releases a document about how to resolve MSBuild location (they are working on it and now that MSBuild is open source you can follow the progress on GitHub). BTW, you can download the MSBuild Tools for Visual Studio 2017 RC here.
  • The location of tf.exe (Team Explorer command-line) has changed.
    In the past, for Visual Studio 2013 and 2015 it was stored in the folder C:\Program Files (x86)\Microsoft Visual Studio <version>\Common7\IDE. For Visual Studio 2017, it is installed in the folder of the Team Explorer extension (C:\Program Files (x86)\Microsoft Visual Studio\2017\<edition>\Common7\IDE\Extensions\<random folder>). Fortunately, there is a shortcut in the folder C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer that point to that location. Did I mention that there can be several editions of Visual Studio 2017 installed?
  • The VsWebSite.Interop.dll automation file is not included in the Core Editor and causes FileNotFoundException.
    The EnvDTE automation assemblies don’t provide extensibility for all kind of projects (for example, you cannot get project references for VB/C# projects with that assembly). For VB/C# projects, you need the VSLangProj.dll family of assemblies. Both EnvDTE and VSLangProj are included by default with the Core Editor of Visual Studio 2017 and therefore your extension will work just declaring Visual Studio Code Editor as dependency in the new Vsix Manifest editor for version 3:vs2017coreeditordependency
    Those assemblies are also valid for Web Application projects. However, Visual Studio 2005 introduced Web Site projects, that lack a project file and Microsoft provided the VsWebSite.Interop.dll family of assemblies to deal with that kind of projects using automation (for example, to get their references). Alas, the VsWebSite.Interop.dll assembly is not included in the core editor, and therefore each time that a method of your extension uses its types (when the method is JIT-compiled) will cause FileNotFoundException. For example a method with this code:
foreach (EnvDTE.Project project in solution.Projects)
{
   langProject = project.Object as VSLangProj.VSProject;
   if (langProject != null)
   {
   ...
   }
   else
   {
       webProject = project.Object as VsWebSite.VSWebSite;
       if (webProject != null)
       {
       ...
       }
   }
}

I reported this to Microsoft through private channels and on Microsoft Connect (VsWebSite.Interop.dll extensibility assembly not installed by Visual Studio core editor) and the only answer so far has been that the extension must declare a dependency on the Microsoft.VisualStudio.WebTools (which installs that assembly), but that is not a solution for me since:

1) That component installs tons of files related to web development, not only VsWebSite.Interop.dll. The user should not be forced to install web-related stuff (project templates, etc.) that she doesn’t require and that would dirty the Visual Studio installation for that simple extension to work.

2) Even if only VsWebSite.Interop.dll was installed by that Microsoft.VisualStudio.WebTools component it would be annoying for users to install that component.

It is a good thing that Microsoft uses EnvDTE / VSLangProj internally and therefore they needed to include them in the Core Editor. Otherwise they wouldn’t be there either. You know that I am not very fan of EnvDTE/VSLangProj although I still use them very heavily (Microsoft has insisted that they are not going to disappear or be deprecated).

Fortunately, there is a workaround, that is what I used. I refactored the methods of MZ-Tools that use the types of VsWebSite.Interop.dll to move the code inside the method that uses the types to a new method and then handled gracefully the FileNotFoundException. For example:

public Collection References
{
   get
   {
      Collection references = new Collection();

      AddLangProjReferences(references);

      if (references.Count == 0)
      {
         try
         {
            AddWebSiteReferences(references);
         }
         catch (System.IO.FileNotFoundException)
         {
            // This can happen in VS 2017 if the web development workload is not installed 
         }
      }
      return references;
   }
}

I hope this post helps you. Happy coding!

Email this to someoneTweet about this on TwitterShare on LinkedInShare on FacebookShare on Google+

Visual Studio 2017 RC announced. Extensions need some changes

Today at the Connect(); // 2016 conference Microsoft has announced the Release Candidate of Visual Studio 2017, formerly known as Visual Studio “15” whose last public beta was Preview 5. I think that this is going to be a great release, because Visual Studio 2015 was very heavy, bloated and slow unless you had a powerful machine and this new version has been greatly optimized and made granular so you only install the pieces (“workloads”) that you need.

To learn what’s new in VS 2017 RC read: Visual Studio 2017 RC

Now, if you are a developer of extensions for Visual Studio, you have work to do. Visual Studio 2017 introduces version 3.0 of the manifest (which is backwards compatible with previous versions) but requires that your extension declares the components required in the new modular setup.

To learn how to migrate your extension to VS 2017 read How to: Migrate Extensibility Projects to Visual Studio 2017.

To learn what’s new in the Visual Studio 2017 SDK read What’s New in the Visual Studio 2017 SDK.

See also:

FAQ for Visual Studio 2017 extensibility

Breaking Changes in Visual Studio 2017 extensibility

Ngen support in VSIX v3

Installing to external directories

Measuring extension impact in startup

The Visual Studio Gallery is also being revamped and renamed to Visual Studio Marketplace and you can manage your extension using the URL https://marketplace.visualstudio.com/manage, although some features are not migrated yet from the Visual Studio Gallery.

I have migrated my MZ-Tools extension to work with VS 2017 RC and I have sim-shipped it with Microsoft publishing it today on the Visual Studio Gallery/Marketplace. In a next post I will explain the issues that I have found in the process.

Email this to someoneTweet about this on TwitterShare on LinkedInShare on FacebookShare on Google+

HOWTO: Diagnose a Visual Studio startup hang problem

For the most part, I love Visual Studio, but some weeks I hate it very deeply :-). In its current incarnation VS 2015, but also from its origins in VS.NET 2002, it is such a huge piece of software, composed of so many parts, that it’s quite fragile and not very resilient. Microsoft knows it and so it recommends to install betas and previews on non-production machines, that is, on virtual machines. Also, it is painfully slow to install unless your computer is fast and has a SSD. The other day I created a Hyper-V virtual machine on the Surface 4 Pro that I use at work to install VS “15” Preview 5. I don’t know how it happened exactly: I think that I deleted an existing Hyper-V virtual machine with the Visual Studio emulator for Android that I installed days ago for a Xamarin course and that I had to uninstall because in turn I had uninstalled Xamarin because it slowed my VS 2015 startup quite noticeably and Xamarin projects took minutes to create using the New Project menu (I want to love Xamarin, so I will use Xamarin Studio on my Mac). Anyway, my Surface laptop suffered a horrible BSOD at startup (APC_INDEX_MISMATCH or similar).

Update Nov 9, 2016: The BSOD crash APC_INDEX_MISMATCH was caused by an update to the Trend Micro Antivirus+ 2016. The solution is to update to Trend Micro Antivirus+ 2017, as explained in their web page Getting stuck on Windows Startup Repair after updating Trend Micro Security.

I could only recover it going back to a restore point. Visual Studio 2015 got an inconsistent state as a result. So I uninstalled it. And I uninstalled VS 2010 too, which anyway was suffering a crash for months each time I tried to show the properties page of any project. And I went to the Control Panel and I removed tons of stuff that were related to Visual Studio. But I forgot to delete the Visual Studio entries in the Registry and remaining folders on disk. When I reinstalled VS 2015 and launched it, the main window did not respond to mouse clicks, only a “ding” sound, as if it was shown an invisible modal dialog. So I uninstalled VS 2015 again and this time I deleted registry entries and remaining folders on disk. After reinstallation, just after the splash screen I got this empty modal dialog (and the main screen was not shown):

vs2015hang

I tried to uninstall, repair, execute devenv.exe with all kind of “reset” flags, etc. to no avail. Since the alternatives are to reinstall Windows, or to give up VS 2015 and wait for the RTM of next VS “15” version, I decided to troubleshoot the problem. There are at least three approaches to diagnose Visual Studio startup problems:

  • The first one is to use the own activity log of Visual Studio. To use this approach, click the Start button of Windows, type “Developer” and the result should appear in the first positions:

developercommandprompt

At the Developer Command Prompt, type:

devenv.exe /log C:\Users\<your user>\Desktop\MyVSLog.xml

developercommandpromptcommand

That will launch Visual Studio and will create the log on your desktop (by default Visual Studio would create it on another location). Close or kill Visual Studio and two files should appear on your desktop: MyVsLog.xml and ActivityLog.xsl.

The ActivityLog.xsl file is a XML stylesheet that allows the XML file to be viewed nicely formatted on a browser (the XML file has this line for this magic to work: <?xml-stylesheet type=”text/xsl” href=”ActivityLog.xsl”?>). In the output, focus first on red items:

connecteduserpackagefailedtoload

So, in my case the problem is:

Could not load file or assembly ‘Microsoft.VisualStudio.Services.Client, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a’ or one of its dependencies. The system cannot find the file specified.
  • The second approach is to use the Assembly Binding Log Viewer (aka “fuslogvw”). This tool applies to any application that uses .NET (not only to Visual Studio) and allows you to know which assemblies couldn’t be loaded and which paths were probed. To launch it, open the Developer Command Prompt of the previous approach but this time with admin rights (right-click “Run as administrator”). Then click the Settings button:

assemblybindinglogviewersettings

If the radiobuttons are disabled it means that it wasn’t launched with admin rights. Select the “Log bind failures to disk” and “Enable custom log path” settings, typing as custom log path “C:\Users\<your user>\Desktop”. Click the OK button, launch Visual Studio, and close or kill it once the error has happened. You will get some assembly binding failures:

assemblybindinglogviewerfailures

Important: do not forget to click the Settings button again and select the “Log disabled” setting.

In my case, I got binding failures  for the assembly:

Microsoft.VisualStudio.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a

and:

Microsoft.VisualStudio.Services.Client, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a

Clicking on any item of the list opens your browser with an .htm file with the details of the failure, the folders where it was searched for, etc.:

assemblybindinglogviewerfailuredetails

  • The third approach is using the Process Monitor tool by Microsoft (formerly by Sysinternals). This approach can be used with any application, managed (.NET- based) or native. It allows you to find failures locating files or registry entries. However, the volume of information can be very big, so it should be used as a last resort. To use it, when launched configure the filter to monitor only devenv.exe:

processmonitorfilter

And in the output you need to dig into the results finding PATH NOT FOUND or similar errors for files that never appear as SUCCESS:

processmonitorfilenotfound

So, using any of these approaches I know now that my Visual Studio installation doesn’t have the assemblies Microsoft.VisualStudio.Services.Client.dll and Microsoft.VisualStudio.Services.WebApi.dll. I haven’t solved the problem yet (the repair option of Visual Studio doesn’t reinstall them) but at least I have more information.

Email this to someoneTweet about this on TwitterShare on LinkedInShare on FacebookShare on Google+

SAMPLE: How to create a Visual Studio context menu

For the sake of completeness, I have added another sample to the list of samples about creating top menus, submenus, toolbars, etc. that I created a few days ago on GitHub:

HOWTO: Create a Visual Studio context menu
Demonstrates how to create a context menu that is shown when right-clicking on a toolwindow. To show the toolwindow click the View > Other Windows > My toolwindow command.

contextmenu

contextmenudark

That is, in this case we don’t want to add a menu entry to an existing context menu, but we want to create a whole context menu with entries to be shown when right-clicking on something, typically a control of a modal dialog or a toolwindow that belongs to our package.

There are a couple of ways to accomplish this:

The first one is using automation (EnvDTE): you create by code a commandbar that you show using the CommandBar.ShowPopup method. This was the only approach for add-ins and you have a sample in the article HOWTO: Create a context menu using a Visual Studio commandbar popup from an add-in. Since packages can use DTE, this approach is suitable. The commandbar can even have menu entries without an underlying command. But this approach is not the focus of this post.

The second one, only for packages, is using a .vsct file. The Menu element of the .vsct file can be of several kinds, and one of them is “Context”. Then you add commands to it through a group, like any other type of menu. But how is shown?. You need to use either the IOleComponentUIManager.ShowContextMenu method or the IVsUIShell.ShowContextMenu method. I have used the latter method, which receives several parameters such as the Guid of the command set, the Id of the context menu (both defined in the .vsct file) and the point where to show it.

The sample also shows the correct approach to initialize the usercontrol of a toolwindow (to pass it the package). Take into account that a toolwindow in Visual Studio can be shown in two cases:

  1. Clicking the command that shows the toolwindow.
  2. Automatically when Visual Studio is launched if the toolwindow was shown when Visual Studio was closed the last time. Visual Studio is smart enough to know the package owner of the toolwindow to show, then it loads the package and shows the toolwindow.

The initialization of the usercontrol cannot be done in the constructor of the toolwindow when the usercontrol is created because at that point the base.Package is null in the case 2:

public MyToolWindow() : base(null)
{
   this.Caption = "My toolwindow";

   m_toolWindowControl = new ToolWindowControl();

   this.Content = m_toolWindowControl;
}

Instead, you need to override the OnToolWindowCreated method since at this point the base.Package is already initialized:

public override void OnToolWindowCreated()
{
   VSPackageContextMenu package;

   base.OnToolWindowCreated();

   package = (VSPackageContextMenu)base.Package;

   m_toolWindowControl.Initialize(package);
}
Email this to someoneTweet about this on TwitterShare on LinkedInShare on FacebookShare on Google+

The strange case of VBA / VB6 editor prompting to repair Visual Studio (revisited 3rd time)

This is the nth time that I find this problem (and I am not the only one), so I am going to document in this 3rd post another cause for it, that happens on Window 10. The problem is that suddenly, the VBA editor of Office or VB6 prompts you to repair some version of Visual Studio. In this case, VB6 prompts to repair Visual Studio 2005 (that I have installed on my main development machine) but it can also happen with Visual Studio 2010, etc.:

vb6prompttorepair

I already talked about this back in 2012, where the root cause was the installation of Visual Studio from a removable hard disk (since then I always copy the setups of Visual Studio to the fixed hard drive before installing) and in 2014, where the cause was the deletion of partition D: of the hard disk (actually a variation of the previous cause). In both cases I was unable to fix the problem until I uninstalled all versions of Visual Studio and reinstalled them, which for a developer of extensions like me that need all Visual Studio versions to test is the most painful experience.

Since I adopted Windows 10 as my main OS, I have seen this problem twice, in 2015 and in 2016, and it has the same cause in both cases as I will explain, but different to the ones of 2014 and 2012. To diagnose this issue, you need to follow the procedure explained by Heath Stewart in his blog. So I started looking for events with ID 1001:

eventviewer1001

As you can see, the error doesn’t tell you exactly which is missing. The events with ID 1004 provide the actual cause:

eventviewer1004

So, the file C:\Windows\Microsoft.NET\Framework\v2.0.50727\RedistList\VSList.xml is missing. This is a file likely installed by Visual Studio inside a folder that belongs to the .NET Framework, not to Visual Studio. I would say this is a bad idea. And it is not the only .xml file installed by Visual Studio, there are a lot of them.

But which is the root cause that makes that a file suddenly disappears from that folder? It is the installation of the major updates of Windows 10: Update “1511” in November 2015 and “Anniversary Update” 1607 in October 2016. As you know, the next one announced a couple of days ago will be “Creators Update” in 2017 and the issue will reappear in 3D ;-). Each time that a major Windows 10 update is installed, the previous Windows installation is stored in a backup folder “Windows.old” (which includes the .NET Frameworks folders, and the .xml files in question). It seems that the Windows 10 update is smart to detect that you had .NET Framework 2.0 installed (it’s an optional feature of Windows 10, not installed by default) and it installs it for you, but not smart enough to detect the missing files. So, alas, the .xml files are not restored and cause this issue. In 2015 I still had the Windows.old backup folder and I was able to restore all the missing .xml files using BeyondCompare, the folder comparison utility that I love. Now in 2016 I deleted the Windows.old backup folder before I realized the issue, so I had to provide the .msi files to the prompt dialog, copying them to the hard disk before, of course!

I hope this helps you if you encounter this issue.

Email this to someoneTweet about this on TwitterShare on LinkedInShare on FacebookShare on Google+

The strange case of System.NotImplementedException “The method or operation is not implemented.” using SQL Server database projects

Yesterday I got a bug report from a user of my MZ-Tools package for Visual Studio 2015:

System.NotImplementedException “The method or operation is not implemented.”

The exception happened calling the EnvDTE.ProjectItem.IsOpen Property (viewKind) method when using SQL Server Database Projects provided by SQL Server Data Tools (SSDT):

databaseproject

As you may know, SQL Server Database projects are quite good automation-friendly projects, that is, they implement EnvDTE interfaces (EnvDTE.Project, EnvDTE.ProjectItem, etc.) so you don’t need to use the low level IVsHierarchy, etc. interfaces of Visual Studio. But somehow, they missed to implement something somewhere.

I tried to reproduce the problem on my side to no avail. My extension worked happily with the .sql files (EnvDTE.ProjectItem) of that kind of project. So, which kind of EnvDTE.ProjectItem didn’t implement the IsOpen property? The user sent me a helpful clue: he was using a database reference. I was not aware of that thing, but certainly in SQL Server database projects you can add references to databases:

databasereference

And as soon as I added a reference to the “master” database, I could reproduce the problem. So, my extension was treating the ProjectItem nodes below the References node as files that could be “opened”, and the ProjectItem.IsOpen method was not implemented (which is certainly right). But, how is that the nodes below the References node were being processed for database projects (which is incorrect) while they were not processed for regular (C#, VB.NET) projects?. The reason is that for regular projects, the EnvDTE.Project.ProjectItems collection of the project doesn’t return the References node, which is correct. For database projects, the EnvDTE.Project.ProjectItems collection does return the References node, which is a bug. I wanted to verify that the internal implementation of database projects has this bug so I used .NET Reflector to see the internals of the Microsoft.VisualStudio.Data.Tools.Package.dll package and I found that there is a ReferenceContainerNode type that has a GetAutomationObject that returns an OAReferenceFolderItem instance:

getautomationobject

There shouldn’t be a folder for references in the automation model (EnvDTE). The automation model provides the VSLangProj.References collection to handle the references of a project. I won’t report the bug because there is an almost zero chance of Microsoft fixing it, and anyway I needed to find a fix for the current version of the SQL Server Data Tools, which took me to the next problem: how can an extension identify reliably the “References” ProjectItem?.

I could check if the Name property of the ProjectItem is “References”, but that approach is always prone to errors due to localization (in Spanish would be “Referencias”). The SQL Server Data Tools doesn’t seem to be localized, but I wanted to investigate another approaches. It happens that the IVsHierarchy of the References node implements an interface named IReferenceContainer. So, one could cast that node to IReferenceContainer and if the cast is successful then it’s the References node. Alas, that interface is declared internally in database projects, and in MPF.Project.NonShipping.dll for other projects. At the end, I opted for getting the EnvDTE.ProjectItem.Object property, convert it to a string, and compare it to “Microsoft.VisualStudio.Data.Tools.Package.Internal.OAReferences”, which is as bad as comparing the Name to “References”, but anyway, it works for now.

Email this to someoneTweet about this on TwitterShare on LinkedInShare on FacebookShare on Google+

SAMPLES: How to create top menus, sub menus, context menus, toolbars

The questions of how to create a toolbar, a top menu, a sub menu, an entry on a context menu, etc. appear from time to time on the forums, so I have created a bunch of samples on GitHub:

visualstudioextensibility/VSX-Samples

They use what I consider best practice: the use of the CommandPlacements section in the .vsct file for centralized place to set parent-child relationships.

The code samples are the following:

HOWTO: Create a Visual Studio toolbar
Demonstrates how to create a toolbar.

toolbar

HOWTO: Create a Visual Studio top menu
Demonstrates how to create a top menu.

topmenu

HOWTO: Create Visual Studio commands on a submenu
Demonstrates the use of the CommandPlacements section of the .vsct file to place a command inside a new group on a submenu inside a new group on the Solution context menu and on the Standard toolbar.

submenutoolbar

submenucontextmenu

HOWTO: Create a Visual Studio command on the Solution context menu
Demonstrates the use of the CommandPlacements section of the .vsct file to place a command inside a new group inside the Solution context menu.

solutioncontextmenu

HOWTO: Create a Visual Studio command on the project context menu
Demonstrates the use of the CommandPlacements section of the .vsct file to place a command inside a new group on the context menu of a Windows project, Web project, or multiple projects selected.

projectcontextmenu

HOWTO: Create a Visual Studio command on the file context menu
Demonstrates the use of the CommandPlacements section of the .vsct file to place a command inside a new group on the context menu of a file or multiple files (belonging to the same project, or to different projects).

filecontextmenu

HOWTO: Create a Visual Studio command on the code window context menu
Demonstrates the use of the CommandPlacements section of the .vsct file to place a command inside a new group on the code window context menu.

codewindowcontextmenu

Email this to someoneTweet about this on TwitterShare on LinkedInShare on FacebookShare on Google+

SAMPLE: How to create a Visual Studio command that accepts parameters

Some weeks ago a user of my MZ-Tools add-in asked me how to automate the Review Quality feature. So far, this feature could be invoked on demand, or automatically when an output file is built using the user interface. The request was very reasonable: automated reviews when the code is built using some script, or when code is checked-in in source control (not in the context of a build). So, the requirement is to execute some feature programmatically with input parameters (feature name, log file, etc.) and generate output files (results file, log file, etc.). My last attempt at automating some feature of MZ-Tools was in 2007, when I wrote the post Frustrations with command-line add-ins for Visual Studio. So, it was time for another attempt.

If you try to execute a command with arguments, for example in the Command window, likely you will get this error:

commandwindow

It happens that there are four steps that you need to code to ensure that your command accepts parameters:

commandwithparametes

Rather than listing the steps here, I have created a sample on GitHub:

HOWTO: Create a Visual Studio command that accepts arguments

One of the steps (the magical “$” value that must be assigned to the ParametersDescription property of the OleMenuCommand) is so esoteric that it’s not properly documented anywhere, but some comments of Ryan Molden in a forum explains something about it.

Email this to someoneTweet about this on TwitterShare on LinkedInShare on FacebookShare on Google+

A new website about Visual Studio resources

I have launched a new website to help developers using Visual Studio / Visual Studio Code / Visual Studio Team Services / Team Foundation Server:

http://www.visualstudioresources.com/

visualstudioresources

And this is a cross post that explains my motivation to do it:

Back in 1995, when I started to work on a company, Internet didn’t exist as we know it today. At that time, Microsoft supplied its Microsoft Developer Network (MSDN) Library with technical information for developers in a couple of CDs that arrived to the office quarterly:

msdnlibrary

You could read the content of your interest in a few days, and then you didn’t receive more content until the next quarter. There were some printed magazines, but they were monthly and you read them in a few days. Content and resources were scarce. Today, more than 20 years later, the problem is the opposite: there is so many content in so many ways that we have to use search engines to find what we need. Also, the way we learn today is not the way we used to learn 20 years ago, at least not for every developer. Some people still prefer to read the official documentation from the manufacturer. Other people prefer to learn with thick, comprehensive, books. Other prefer small articles and posts. Others don’t like to read so much and prefer videos or courses. Yet others prefer to learn reading code of samples or other apps.

I’ve created this site with the goal of providing a huge directory of resources of any kind to learn about the Visual Studio family: Visual Studio, Visual Studio Code, Visual Studio Team Services and Team Foundation Server. It is not a website about .NET or about programming languages (C#, VB.NET, F#, etc.), but only about the “tooling”, the development environments and the application lifecycle management (ALM) systems that Microsoft provides to developers to become more productive.

This website starts small and modest, but hopefully it will grow in the next months and years to reach the depth of the Visual Studio Extensibility (VSX) that I created years ago for developers extending Visual Studio.

I hope you like it.

Email this to someoneTweet about this on TwitterShare on LinkedInShare on FacebookShare on Google+

Another two strange cases of MZ-Tools 8.0 for VBA could not be loaded

It seems that the path to load a .NET-based add-in in the VBA editor of Office is full of mines. In the last couple of days I have discovered two new scenarios (apart from this and this) that can cause “<Add-In> could not be loaded”. I will document them here for future reference for me or other people:

This first one happens if you are not using a COM Shim, you are using .NET Framework 2.0 and the version of Office is 2000, 2002 (XP) or 2003. It is due to a lockback policy that “prevents the .NET Framework 2.0 common language runtime (CLR) from initializing when the .NET Framework 2.0 is hosted in either the Word process space or the Excel process space. The policy restriction limits Word and Excel from loading versions of the .NET Framework that are later than version 1.1. Therefore, the .NET Framework 2.0 assemblies cannot load”. It is documented in the Knowledge Base article You cannot load a .NET Framework 2.0 assembly from Visual Basic for Applications in Word 2003 and earlier versions, or in Excel 2003 and earlier versions and fortunately has a solution through a registry key HKEY_CLASSES_ROOT\Interface\ {000C0601-0000-0000-C000-000000000046} that can be created. I was aware of this problem since long time ago and my setup created that registry key if Office 2003 or 2002 was detected. However, I noticed that my add-in was failing for Office 2000 (yes, I have users running Office 2000 on old PCs) because I added support for Office 2000 later and I didn’t update the setup to check that version. This case is difficult to diagnose because the following script works perfectly (I mean, the problem only manifests loading the assembly in Office):

Dim o
Set o = CreateObject("MZTools8VBA")

The other problem was also hard to diagnose. It happened when using a COM Shim to load the CLR using code from the COM Shim wizards provided by Microsoft, which calls the CorBindToRuntimeEx function passing NULL to the first pwszVersion parameter. A NULL value means to load the highest CLR installed below CLR 4.0, which should be CLR 2.0. However, on Windows XP I got HRESULT 0x80131700. Fortunately I found on a comments of the post COM Shim CLR Loader Bug that the problem could be solved passing the specific version “v2.0.50727”, which certainly fixed the problem for me.

Email this to someoneTweet about this on TwitterShare on LinkedInShare on FacebookShare on Google+

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