The strange case of CreatePkgDef failing because of strong name validation

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=8.0.0.0, 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:

[assembly: AssemblyDelaySign(true)]

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:

VSPackageBuildWithNet45

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=1.0.0.0, Culture=neutral, PublicKeyToken=69b8a83eb37e3459' or one of its dependencies. Strong name validation failed. (Exception from HRESULT: 0x8013141A)

VSPackageBuildWithNet46

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

Visual Studio 2015 RTM just released

Finally Visual Studio 2015 RTM has been released today and I am installing now on my main dev machine, rather than on separate virtual machines as I have been doing until now. There is and there will be a lot of information about what’s new in this release, but as a developer of extensions for Visual Studio, this release introduces these changes that you must know:

  • Add-ins are gone and now packages are the primary way of extending Visual Studio for the typical need of creating some toolbar, menu, buttons, toolwindows, etc. or listening to events to do something. Migrating from an add-in to a package is not trivial due to the usage of services instead of the EnvDTE automation model (although you can still use the automation model) but also for the difficulties of the .vsct file. ElektroStudios StackOverflow user (and others): I do feel your pain. I will do my best to find time and provide decent tutorials and a GitHub sample about .vsct in the next couple of months.
  • The editions offering has been simplified a bit and now you have:
    • Community Edition, which supports extensibility and is free for some scenarios, at least “still free”, huh?
    • Professional Edition
    • Enterprise Edition
      All of them are already available. There is no Ultimate edition, but for some reason there are still Express editions for Windows Desktop, Web (both already available) and Windows 10 (coming soon).
  • The compilers for C# and VB.NET are now exposed to extensions through the .NET Compiler Platform (formerly “Roslyn”). This should replace the automation code models (EnvDTE.Project.CodeModel, EnvDTE.ProjectItem.FileCodeModel), although they can be still used and in fact their implementation has changed to use Roslyn under the hood, with quite a few bugs along the way that I have reported and most of them are fixed now.
  • There is new support for high resolution icons on buttons for high-dpi displays, although AFAIK it is not documented yet.
  • There is a new Common Project System (CPS) in the works.
  • The Visual Studio 2015 SDK is available as a separate download as until now, but it is also already included in the Visual Studio setup under the name Common Tools > Visual Studio Extensibility Tools:
    VS2015SDK
  • The way to create a package, to add commands and toolwindows has changed, as hinted in the setup:
    VS2015SDK_2
  • To create a package there is no longer a wizard as in Visual Studio 2013, but just a barebone VSIX project template, and later you add as many custom commands or custom toolwindows as you want using the Add > New Item dialog and selecting the corresponding item templates under the Extensibility node. This solves the old problem of how to add a second command or toolwindow to an existing package, at the cost of making it more difficult to know how to add the first ones.

I will elaborate on all these aspects in the next weeks (during my vacations, I’m afraid), and will provide new links on this site to VS 2015 specific stuff.

Did I mention that my extension MZ-Tools 8.0 is now a package for VS 2012, 2013 and 2015? It is also an add-in for VS 2005, 2008 and 2010, and they share 80% of code at binary level using the strategy of core plug-in +  host adapters that I outlined here. I have even released in the last weeks a restricted Beta 2 of MZ-Tools 8.0 for the VBA editor of Office and even for VB6 / VB5 sharing the same 80% of binary .NET code. This is an example of a complex add-in migrated to a package with a new good underlying architecture to accommodate not only future changes in the extensibility model of Visual Studio, but also to support other Microsoft IDEs.