When Microsoft released Visual Studio 2010 with the new WPF-based toolbars and new look and feel, it didn’t update the Macros IDE to follow suit, keeping the same Macros IDE of Visual Studio 2008. Two years later, the Macros IDE was removed from Visual Studio 2012. Add-ins were deprecated in Visual Studio 2013 and removed in Visual Studio 2015. Add-ins are not going back (because they have packages as replacements) but macros didn’t have a simple replacement, and they filled a gap between having nothing and being forced to create an add-in even for the simplest automation task without user interface, that macros could create just recording actions. Add-ins were somewhat overkill for those tasks because even initializing them was tricky, not to mention if you wanted to create commands and buttons (if you have followed this blog all these years you already know). So, it’s not a surprise that the community used UserVoice, one of the channels to provide feedback to Microsoft, to open in 2012 this request to bring back Macros, which has now reached 6,000+ votes. In response, Microsoft created a Macros for Visual Studio extension for Visual Studio 2013 that now not only has been upgraded to support Visual Studio 2015, but also it’s open source. You have the code on GitHub and the official announcement on the Visual Studio blog here.
In the last months, I have had two or three reports of the users of my MZ-Tools extension about this exception:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: Loading of the ImageList did not succeed. at System.Windows.Forms.ImageListStreamer..ctor(SerializationInfo info, StreamingContext context) --- End of inner exception stack trace ---
With a full trace that is included in this StackOverflow question with the same problem.
Incidentally, I had seen that exception very sporadically in the last tests of a session of integration tests of MZ-Tools.
For Visual Studio, MZ-Tools has more than 3,000 integration tests (most of them reproduce user actions such as setting options, executing commands and getting results in code or in treeviews, etc.). It is my experience that no version of Visual Studio has been able to run all the tests without crashing due to out of memory errors, etc. so I tend to run them in sets of 500-800 tests, restarting Visual Studio after each session. In this scenario, I have never seen the exception above.
For VB6 and VBA, on the other hand, there are “only” 1,500+ integration tests, and both IDEs are very capable of running all of them in a single session (and much faster than Visual Studio). In this case, I have seen the exception in the last tests but very rarely. So, I finally decided to investigate this issue.
There is little information on the web about this exception with the ImageList. Some old MSDN KB articles mention problems with the ImageList and leaks:
FIX: ImageList Class Leaks GDI objects (for .NET Framework 1.0)
Memory usage increases for a .NET Framework 2.0-based application when you use the ImageList.ImageCollection.Item property to obtain an image or when you call the ImageList.ImageCollection.GetEnumerator method.
I am using .NET Framework 2.0 but it is fully patched. Since the problem could be related to GDI objects leaks, I used theTask Manager to check it:
To add the GDI Objects column you need to right-click on the column header and then select it on the list:
Then I ran the 1,500+ integration tests in Excel while watching the GDI Objects counter and, to my surprise, the counter increased and increased, never releasing objects. So, there is a GDI object leak somewhere that I will investigate in the next days. I don’t know yet if this is the same cause for the users of my extension (it could be that they use the IDEs for very long periods of time without restarting) but certainly I have now a a GDI object leak to find.
For many years I have used a custom localization approach for my MZ-Tools add-in: instead of using .resx files, I used a single embedded .xml document which had nodes for each term, and in turn each one had children nodes for each language (I currently provide six languages). Then I had some functions to retrieve the required term in the desired language. This approach has some advantages, such a centralized source of resources for localization, less size at run-time, and a simplified setup with no resource dlls to deploy (I am aware that *.resources.dll files can be embedded too, but the approach is tricky).
Recently I wanted to use a web-based platform for localization, and to use .resx files which are the “standard” approach for localization. There are also 3rd party extensions such as ResXManager that allows you to manage localized resources in a centralized way using a grid. For the web platform I decided to use OneSky (it’s great and it allows up to 5 users for free). On this platform you can use tons of formats to upload/download the resources to localize, including of course .resx files. So, finally I had all changes made and a new setup that deploys all the *.resources.dll files:
The localization worked during development, however it failed when installing the extension with the setup. The MZ-Tools add-in failed for VBA/VB6/VB5, it also failed for VS 2005-2010, and the MZ-Tools package also failed for VS 2012-2015. The strings were always shown in English, the default language. Why? I suspected it was somehow related to obfuscation, which I use in the “Release” configuration (used by the setup) but not in the “Debug” configuration (used during development). Using .NET Reflector I didn’t notice anything wrong with the deployed *.resources.dll files. So, I thought about replacing the installed obfuscated main dll by the original one before obfuscation, but before I had to disable strong name verification because at “Release” configuration you need to use delay signing to use obfuscation, and re-sign after obfuscation. To disable strong name verification you have to execute:
sn.exe –Vr *,<public key token>
Suddenly, before replacing the main dll, all worked. So, the problem was that the *.resources.dll files were using delay signing and .NET was refusing silently to load them. I guess that using the Assembly Binding Log Viewer (fuslogvw.exe) would have revealed this. By the way, you can know if a .NET assembly is using delay signing or not (even if it is set to skip strong name verification) using:
sn.exe –vf <assembly>
So, when a Visual Studio project is set to use delay signing, not only its main output assembly but also its *.resources.dll files lack the strong name, and the build process that you use to sign again the main assembly must re-sign also its *.resources.dll files.
In the past Microsoft Build 2016 conference a few weeks ago there were a couple of sessions that were of interest to VSX developers:
In the first one, “Visual Studio 2015 Extensibility”, Mads Kristensen “writes an extension from scratch live on stage, then integrates with GitHub, automates the build process and deploys the finished extension to the Visual Studio Marketplace”. I enjoyed it a lot and learned some things that I didn’t know. I encourage you to see it:
The second one is “The Future of Visual Studio”, by Amanda Silver. While this session doesn’t talk about VSX, it contains some good news: the new version of Visual Studio “15” will take much less time to install, like 180 seconds a minimal installation thanks to a new “streamlined acquisition experience”, with no MSI or GAC involved (this is mind-boggling, isn’t it?). Of course, adding components for development with different technologies will take considerably more time, so we will have to wait for the final result of the new setup experience:
She had also an interview with Seth Juarez about that session:
I currently have on my development machine six versions of Visual Studio (2005, 2008, 2010, 2012, 2013 and 2015), along with their service packs and Windows updates, which are required to ensure that my MZ-Tools extension (as add-in or as package) works correctly on each VS version. Also, I have different virtual machines with only one version of VS installed on each one, which is required to ensure that I am not using a reference that is missing in some VS version (which wouldn’t be noticed on the main development machine because all VS versions are installed). Each time that I have to create a new development environment of VS versions I know it will take me the whole day… watching TV shows or doing something else. On the one hand I think that Visual Studio has become a huge monster, still COM-based, with lots of internal technologies and dependencies. On the other hand, there is something in the MSI technology that makes it slow. For example, a setup created by InnoSetup for a Visual Studio add-in is faster than a setup created by MSI. Anyway, hopefully in the future the installation of Visual Studio will be less painful, now that Microsoft is aware of the pain.
Either if you are a new or a veteran developer of extensions for Visual Studio, chances are that at some point you will have to send feedback to Microsoft to report bugs, suggest enhancements or ask for new features. In the last years, the number of channels to do it has increased significantly. Here it is a recap:
The “formal” channels (with tracking) are the following:
- Microsoft Connect: this has been the traditional channel to send feedback to Microsoft about some of its products, specially for Visual Studio and .NET. I have reported tons of bugs about VSX through this channel in the last years.
- GitHub: with some portions of Visual Studio and .NET going open source, such as the .NET Compiler Platform (Roslyn), this is the preferred channel by those Microsoft teams to get reported issues.
- UserVoice (“Extensibility” category): to suggest new ideas, features or enhancements, this is one of the best channels. The most voted items have more chances of being implemented.
- Visual Studio feedback: recent versions of Visual Studio provide a feedback button at the top-right corner of the IDE.
You can either provide a suggestion (it redirects to UserVoice) or report a problem, which shows a dialog and you can select the “Integrated Development Environment” problem area:
- VSIP Partner Program: as I explained in Why to become a Microsoft Visual Studio Industry Partner (VSIP) “Basic” level, you can become a VS partner basic level for free. This opens a new channel to get in contact with program managers inside the VSX team, to a mailing list of Visual Studio Team Services monitored by the engineering group, to Dev Clinics, Dev Labs Online, etc. Paid levels allow you to get access to the Partner Developer Support Request benefit.
The “informal” channels are forums that are visited frequently by members of the VSX team:
- Gitter (Microsoft/extendvs): this is the community for developers of Visual Studio extensions. It can be used to get help, but since it is visited by the VSX teams you can provide feedback, bugs, etc. There is a monthly office hour every 3rd Thursday, 10am – 12pm PST, where members of the VSX teams can address your questions, suggestions, requests, etc.
- MSDN Visual Studio Integrate Forum: this forum is more suited to get problems solved, but it is also visited by members of the VSX team.
With more and more code samples on GitHub, better docs, and extensions and templates to help you to develop extensions, this whole range of options to get help, report bugs, send feedback, suggest improvements, etc. without cost is the another fundamental piece to improve your experience when developing extensions.
After appearing as the new C# / VB.NET compilers in VS 2015, “Roslyn” is gaining popularity, so I am enriching its sections on this web site.
There is now the first book (AFAIK) about Roslyn, by Alessandro Del Sole, which is even free thanks to Syncfusion:
Josh Varty published last month two new videos of his Learn Roslyn Now series on YouTube:
|Learn Roslyn Now – E08 – The AdHocWorkspace
By Josh Varty, YouTube, February 2016
|Learn Roslyn Now – E09 – Introduction to Analyzers
By Josh Varty, YouTube, February 2016
And I have found several new videos:
|Torment Your Colleagues with the ‘Roslyn’ .NET Compiler Platform
By Ivan Towlson, TechEd Europe, September 2015
|Roslyn and .NET Code Gems
By Scott Allen, DevDay, October 2015
|.NET Compiler Platform (“Roslyn”): Analyzers and the Rise of Code-Aware Libraries
By Dustin Campbell, Microsoft Build, May 2015
|Building a Diagnostic Analyzer with Code Fix in Visual Studio 2015
By Jeremy Clark, December 2014
|C# Inception: Using Roslyn and C# Code to Analyze C# Code
By Eric Potter, Stir Trek Conference, January 2016
As you may know by now, the Visual Studio family (Visual Studio, Visual Studio Team Services and Team Foundation Server) has a new member: Visual Studio Code. While still in its infancy (it’s not even 1.0 at the time of this writing), it is very promising by several reasons:
- It is portable, available on Windows, Mac OSX and Linux. I only buy Mac computers since some years ago, running Windows virtualized, so I like the idea of running some Visual Studio flavor on Mac OSX.
- It is modern, with a nice editor with intellisense, code assistance and navigation, debugger and themes.
- It is extensible, being built with extensibility in mind from the beginning. If you are old enough in the VS extensibility world, you may remember that the first version of Visual Studio (2002) was not extensible through packages, only through add-ins, and Visual Studio didn’t get a proper “VS SDK” until VS 2005.
- It has already tons of extensions on its own marketplace.
- It is open source, with a GitHub repository. If you are extending an IDE, it’s tremendously helpful to have the source code of that IDE, to know how it works internally. I can’t count the hours that I have spent guessing how the Visual Studio IDE works or trying to debug its assemblies with some 3rd party tools.
- It is clean, written in TypeScript and Node.js. The full Visual Studio was written originally in native C++, it was COM-based, and later it got a lot of managed C# code.
- Did I mention that it’s free?
It’s easy to see its potential, given that ASP.NET Core is also multi-platform and there will be more and more applications that won’t require the Windows desktop.
So, I have added new sections about Visual Studio Code extensibility on this site, which aims to be best resource center to extend all the Visual Studio products. They are the following:
- Overview > Visual Studio Code Extensibility
- Documentation > Visual Studio Code Extensibility
- Downloads > Visual Studio Code Extensibility
- Articles > Visual Studio Code Extensibility
- Samples > Visual Studio Code Extensibility
- Videos > Visual Studio Code Extensibility
I will populate them with more content in the next months as it becomes available. And hopefully there will be even a section for Books at some point.
In my post Visual Studio extensions and DPI-awareness I introduced the basics that you need to know to become DPI-aware. The final step once all the user interface of your extension handles high-DPI gracefully is to provide high-DPI images for the toolbars, as Visual Studio 2015 does since CTP 3. Apparently, support for high-DPI images through a new image service was in the Visual Studio 2015 RTM release, but it hasn’t been until a couple of days ago that Microsoft has published the MSDN documentation. Here you have the resources to learn and use it:
- Image Service and Catalog: This cookbook contains guidance and best practices for adopting the Visual Studio Image Service and Image Catalog introduced in Visual Studio 2015.
- Image Service Tools: The VS SDK includes several tools to help extension builders use the Visual Studio image service (Manifest from Resources, Manifest to Code and Image Library Viewer).
- Color Theming Tools: The VS SDK provides several tools to help you create and manage color themes (VSIX Color Editor and VSIX Color Compiler).
- VSSDK Samples: several samples have been updated to use the Image Service and Image Catalog.
- Visual Studio’s KnownMonikers: The images contained in Visual Studio’s IVsImageService.
UPDATE (Jan 26, 2016): The Visual Studio Image Library, which contains .zip files with VS images, has been updated with VS 2015 images.
It has been a long time since my last post here, and for a good reason. Since I released MZ-Tools 8.0 for Visual Studio 2015 last July 1 (converted from add-in to package), I have been very busy the last months to achieve a new huge milestone:
From the extensibility point of view, MZ-Tools 8.0 is a unique piece in the world, AFAIK: it provides the same feature set for four different IDEs (Visual Studio, VBA editor, Visual Basic 6.0 and Visual Basic 5.0) with different extensibility APIs reusing the same code at binary level:
As you can see in the images, in all cases there is the same big MZTools8PlugIn.dll file, which contains the feature set, and smaller host adapter dlls that “plug” the features into the IDEs. If you are interested, I outlined the strategy to achieve this in this other post.
After several days fixing bugs of my new MZ-Tools 8.0 version, today I have tried to run the build process that I have to generate the “Production” version and it has failed with this chain of errors:
Error 1 CreatePkgDef : error : ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information. MZTools8VSPackage Error 2 at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module) MZTools8VSPackage Error 3 at System.Reflection.RuntimeModule.GetTypes() MZTools8VSPackage Error 4 at System.Reflection.Assembly.GetTypes() MZTools8VSPackage Error 5 at Microsoft.VisualStudio.Tools.CreatePkgDef.ProcessAssembly(String fileName, Hive hive, PkgDefContext context, Boolean register, RegistrationMode mode) in f:\dd\VSSDK\VSIntegration\Tools\src\CreatePkgDef\CreatePkgDef.cs:line 260 MZTools8VSPackage Error 6 at Microsoft.VisualStudio.Tools.CreatePkgDef.DoCreatePkgDef(InputArguments inputArguments) in f:\dd\VSSDK\VSIntegration\Tools\src\CreatePkgDef\CreatePkgDef.cs:line 164 MZTools8VSPackage Error 7 at Microsoft.VisualStudio.Tools.CreatePkgDef.Main(String arguments) in f:\dd\VSSDK\VSIntegration\Tools\src\CreatePkgDef\CreatePkgDef.cs:line 85 MZTools8VSPackage Error 8 Could not load file or assembly 'MZTools8PlugIn, Version=126.96.36.199, Culture=neutral, PublicKeyToken=a756ad4bac8a0579' or one of its dependencies. Strong name validation failed. (Exception from HRESULT: 0x8013141A) MZTools8VSPackage
The first thing I noticed is that the errors show a location “f:\dd\VSSDK\VSIntegration\Tools\src” that is not on my hard disk. This is because the VS SDK tools (at C:\Program Files (x86)\Microsoft Visual Studio 12.0\VSSDK\VisualStudioIntegration\Tools\Bin) are shipped with the .pdb files for debugging.
The second thing that I noticed is that the CreatePkgDef.exe utility was failing because of a strong name validation that happened in the System.Reflection.RuntimeModule.GetTypes(RuntimeModule module) method of the .NET Framework. However, this had been working until a few days ago. My MZ-Tools package (MZTools8VSPackage.dll) uses .NET Framework 4.5 and it is not obfuscated, but it uses a core MZTools8PlugIn.dll that uses .NET Framework 2.0 and it is obfuscated. So, the things are arranged as follows:
- In “Debug” configuration, the MZTools8PlugIn.dll assembly is generated with a strong name because no obfuscation is performed.
- In “Release” configuration, the MZTools8PlugIn.dll assembly is delay-signed, because it requires obfuscation, and you can’t alter an assembly signed with a strong name. So, obfuscation is done in a post-build step and then the obfuscated assembly is finally signed. The details are documented here.
So, in “Release” configuration, CreatePkgDef.exe is failing because the package assembly is loading a required assembly that doesn’t have a strong name yet (delay-sign). I was well aware that normally you need to instruct the .NET Framework to skip strong name validation using sn.exe -Vr (which for sn.exe 32-bit adds a special registry entry under HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification) but somehow the CreatePkgDef step of the package assembly compilation of my build process has been working for ages until a few days ago without that strong name validation skipping step.
What has changed in the last days? My only suspect was Visual Studio 2015 and .NET Framework 4.6, that I installed on my main dev machine once they got RTM status. Since .NET Framework 4.5, 4.5.1, 4.5.2 and 4.6 are “highly compatible” with .NET Framework 4.0, they are not installed “side by side” but “on top” of the previous version. But it could be that one version introduces a breaking change to existing apps. To verify this hypothesis, first on my main dev machine where the issue was happening I created a package with Visual Studio 2008 (which uses .NET Framework 3.5 and CLR 2.0) and it compiled even setting the following delay sign in the AssemblyInfo.cs file:
The same was not true if I used Visual Studio 2010 or higher (which use .NET Framework 4.0 / CLR 4.0 or higher), but it was true in the past. So the suspicion increases.
Then, I setup a new virtual machine with only Visual Studio 2013 (.NET Framework 4.5.2) and lo and behold, a package compiles even if you use delay sign:
As soon as I downloaded and installed only .NET Framework 4.6 (no need to install Visual Studio 2015), the same package compilation gets this error:
CreatePkgDef : error : FileLoadException: Could not load file or assembly 'VSPackage1, Version=188.8.131.52, Culture=neutral, PublicKeyToken=69b8a83eb37e3459' or one of its dependencies. Strong name validation failed. (Exception from HRESULT: 0x8013141A)
So, .NET Framework 4.6 introduces a breaking change that I have not seen documented.
Now, there is at least a couple of solutions:
- You can build the package assembly with a strong name even in “Release” configuration, so CreakePkgDef doesn’t fail, and remove the strong name before obfuscating. Since the sn.exe utility doesn’t allow to remove strong names, you must search some other utility on the web (they exist).
- You can instruct the .NET Framework to skip strong name validation using sn.exe -Vr before the package assembly is built, not after the package is built and before the assembly is obfuscated. The utility sn.exe is so handy that it allows you to skip strong name validation for assemblies that don’t exist yet, specifying just the public key token that will be used to sign them:
sn.exe -Vr *,public_key_token