MZ-Tools Articles Series: HOWTO: Force files to open with a specific editor from a Visual Studio package

This other article also comes from one of my answers in the MSDN VSX forum:

HOWTO: Force files to open with a specific editor from a Visual Studio package

It explains how to overcome a limitation of the automation model (EnvDTE) forcing a ProjectItem to open in a specific editor even when the user has set the default to other editor (especially problematic if the editor is external, such as Notepad). It is also useful if you want to start getting rid of “EnvDTE” code in your package.

MZ-Tools Articles Series: HOWTO: Create two Visual Studio packages in a single assembly

The first MZ-Tools Articles Series that I have written this new year is this:

HOWTO: Create two Visual Studio packages in a single assembly

I did it as a pure exercise after a question in the MSDN VSX forum and I don’t think it has any practical use even for the problem of a package targeting multiple versions of Visual Studio with the maximum reuse of code at source and binary levels.

Currently the most notorious problem that I have found (and that I reported at Uservoice) is that you can’t provide a single .vsix package for VS 2010/2012/2013 with a single binary assembly and two .vsct tables with the following conditions:

  • The package uses one .vsct command table for VS 2010 (with colorful icons)
  • The package uses another .vsct command table for VS 2012/2013 (with gray icons)

So, you can create a single package in a single assembly with two .vsct tables, or two packages in a single assembly with a different .vsct file each one (like in the example provided in the article), but neither you can specify in the .vsct table or package attributes the target VS version, nor you can specify in the manifest of the .vsix file the target VS version of each .pkgdef file.

Code model of EnvDTE using Roslyn internally in VS 2015. Bugs ahead.

One of the things that I have done in the last weeks has been to run the integration tests that I have for my MZ-Tools extension (now converted to a package) in Visual Studio 2015 Preview. I have hundreds of them and pass successfully in VS 2005 / 2008 / 2010 / 2012 and 2013 (with some sporadic timing-related failures that I try to reproduce and fix forever, but that’s another subject). When I ran them on VS 2015 Preview, dozens and dozens of them failed, to my desolation, because I immediately knew that there was something very wrong in VS 2015. One after another, I clasified them, identified patterns and all of them were related to the code model (EnvDTE.ProjectItem.FileCodeModel, EnvDTE.CodeElement, etc.) which my add-in uses intensively in several features. Eventually I isolated the root causes and I identified several bugs in the implementation of the automation code model in VS 2015, which soon I learned was changed internally to use the .NET compiler platform (“Roslyn”). I even discovered and disassembled the new assemblies that provide the implementation because one of the bugs is so severe that it crashes Visual Studio:

FatalExecutionEngineError / InvalidCastException after sorting body-less properties in VB.NET file

Although I can reproduce it 100%, I have not isolated it to the minimal package because I think that with the information provided to Microsoft should be enough. I am still awaiting the acknowledgement of the problem.

Other ones, that are far less severe, don’t crash Visual Studio but cause exceptions, and would need some fix:

ComException getting start/end points of EnvDTE80.CodeEvent Adder/Remover/Thrower

EnvDTE.CodeParameter.StartPoint and EndPoint causes exception for “ByVal ParamArray” parameters

EnvDTE.CodeFunction.FunctionKind causes exception for methods of classes with explicit interface implementation

And yet another ones don’t cause exceptions, but return an incorrect value when in VS 2013 returned the correct values:

EnvDTE.CodeElement.FullName doesn’t return full name for constants, fields, methods, properties and events in VB.NET

EnvDTE.CodeClass.Members collection doesn’t include code elements for “Declare” methods of VB.NET class

EnvDTE.CodeFunction.FunctionKind doesn’t return vsCMFunction.vsCMFunctionDestructor for Protected Overrides Sub Finalize()

EnvDTE.CodeFunction.FunctionKind doesn’t return correct value for EnvDTE80.CodeEvent.Adder, Remover or Thrower

EnvDTE.CodeDelegate.Attributes and EnvDTE80.CodeEvent.Attributes returns 0 elements always

This change in the implementation of the automation code model to use “Roslyn” is quite surprising to me. I reported lots of bugs in the automation code model in the last years until I got tired of getting the same answer: no fix would be provided because a new API was being developed. Later I learned that the new API was Roslyn but I didn’t expect the automation code model bugs to be fixed by leveraging Roslyn. AFAIK, Microsoft hasn’t provide any information about this change, but the truth is that bugs have been introduced. I have implemented workarounds in my code for some of them until Microsoft fixes them (in VS 2015 CTP5 they are not fixed). There are also a couple of them (very minor) that I haven’t reported yet. So, if your extension uses the automation code model, I encourage you to test that area carefully and report the bugs that you find.

Past, present and future challenges for developers of Visual Studio extensions

It has been a while since my last post. In this time I have spent four weeks of vacations (although working a lot on my MZ-Tools extension), I have got a new laptop (MacBook Pro 13″ Retina), a new year has come and I have been awarded Microsoft MVP again (my 12th award). Most of the time working on my extension has been in two painful tasks, which reminds me how challenging is to develop extensions for Visual Studio, specially when Microsoft releases new major versions. This is the history of difficulties that I recall since Visual Studio (.NET) was born:

  • In Visual Studio .NET 2002/2003 you had to learn a new extensibility model (EnvDTE), different from the one used by Visual Basic 6.0. Also, creating toolwindows was extremely tricky because you needed to create a shim ActiveX control in C++. A native satellite dll for custom bitmaps was required.
  • In Visual Studio 2005 you had additional automation assemblies (EnvDTE80), you had to convert all the icons from 16 colors to 256 colors and you could create COM-free add-ins (with the .AddIn file). A satellite dll for custom bitmaps was still required, but no longer native.
  • In Visual Studio 2008 there was no much change, apart from the tricky magical colors to get transparency in bitmaps of buttons and toolwindow icons.
  • Visual Studio 2010 was the most stressful version ever released. The introduction of WPF-based commandbars (instead of the previous Office-based commandbars) caused tons of bugs in add-ins that I reported to Microsoft. A satellite dll for custom bitmaps was no longer required. You could use WPF for your dialogs, but chances were that you kept using Windows Forms. In the packages area, new APIs and deployment mechanisms were introduced.
  • In Visual Studio 2012 macros were removed, a new icon style was introduced (which forced your extension to follow suit) and a new dark theme was introduced, which also forced you to theme your toolwindows and dialogs if you wanted to follow suit. Applying a dark theme to Windows Forms forms is hard.
  • In Visual Studio 2013 there was no much change.

At the present time, Visual Studio 2015 introduces these new challenges:

  • Add-ins are removed (the Add-In Manager is gone), which means that a migration to a package is required.
  • The code model (EnvDTE.Project.CodeModel and EnvDTE.ProjectItem.FileCodeModel) are reimplemented internally to use the .NET compiler platform (“Roslyn”). So, expect bugs, small bugs with possible workarounds and serious ones as to crash Visual Studio. I have reported several of them to Microsoft Connect in the last weeks (one of the two painful tasks that I mentioned). This will be the subject of my next post.

Also, I have mentioned that in the past weeks I have adquired a new laptop. I had a MacBook Air 11″ which has served me well in the last 2.5 years but it had its limits (128 GB SSD, 4 GB memory and 1280 pixels of resolution), and I wanted something more powerful. So, I got a MacBook Retina 13″ with 16 GB of memory and 256 GB SSD. The first thing that I noticed is that at native resolution and 100% DPI icons and texts are tiny, so you have to increase the DPI level to 150%. And at that level my MZ-Tools extension behaves badly. So I have spend a lot of time in the last weeks (the other painful task) making it fully DPI-aware, which means 1) correcting layouts, 2) scaling low resolution images to the correct size, and 3) providing high resolution images (for VS 2010 icon style and for VS 2012/2013/2015 icon style in light/dark themes). Applying high-DPI awareness to Windows Forms is tricky. This will be the subject of another post, but high-DPI awareness is another area that developers of Visual Studio extensions will need to learn and implement because retina displays will become mainstream for laptops this year, and 4K monitors for computers are also starting to appear. And you don’t want to contribute to the painful lifestyle of high-DPI desktops.

In the future at the very least I still think that the automation model (EnvDTE) used even by packages is at risk, despite Microsoft updating it in VS 2015 using Roslyn internally to provide more accurate results in the code model with the current API. The EnvDTE automation model was created in an era (Visual Studio .NET 2002) when add-ins and macros were the only form of Visual Studio extensibility (you couldn’t create packages until Visual Studio .NET 2003 and the VS SDK was not introduced until Visual Studio 2005). Ten years later, macros were removed in Visual Studio 2012 and add-ins will be removed in Visual Studio 2015. The VS SDK provides interfaces for most EnvDTE stuff, except the code model (that will be provided by Roslyn from now on) and another small areas (such as to create and edit solution configurations). I think that at some point Microsoft will consider another step in simplifying APIs removing EnvDTE. And getting rid of awful APIs and interfaces in the VS SDK when creating packages is long overdue, so expect new challenges.