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.

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);
}

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.

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.

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

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.