Mock Function call to force loading an assembly - how elegant!

A quick (and handy!) hack to force referenced assembly to getting copied to a project

This post was most recently updated on November 28th, 2022.

2 min read.

Visual Studio failing to copy a referenced assembly to a project in build might lead to surprising runtime errors. This post will explain one method of fixing these issues, using Microsoft.IdentityModel.Clients.ActiveDirectory as the example – as earlier versions of that assembly had this issue!

Problem

After the build, you might get this kind of error:

Could not load file or assembly 'Microsoft.IdentityModel.Clients.ActiveDirectory.Platform, Version=3.13.1.846, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified. 

System.IO.FileNotFoundException at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) at System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) at System.Reflection.Assembly.Load(AssemblyName assemblyRef) at Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformPlugin.LoadPlatformSpecificAssembly()

In my case, I had referenced both of these DLLs in my “class library project”, which provided my console program with a lot of functionality:

  • Microsoft.IdentityModel.Clients.ActiveDirectory.Platform
  • Microsoft.IdentityModel.Clients.ActiveDirectory

I was expecting the referenced project to be built alongside with my console program, and did not expect any issues with referenced libraries – but BOOM! Suddenly none of the calls that happened in the referencing project, and required the Platform dll, worked anymore. They’d throw errors like the one above.

After a while of googling, I found a solution – that might apply to some other situations, too!

The authors of the package apparently kind of broke this functionality in the 3.13 version of the library (Microsoft.IdentityModel.Clients.ActiveDirectory), in August 2016. That’s understandable – Microsoft’s stack nowadays is quite a fast-moving beast, and hence things sometimes break. And since there’s a workaround, I guess the developer team wasn’t in a huge hurry to fix the issue…

The team will, however, fix the issue in the upcoming version 3.17.0. They’ll achieve this by combining the functionality of the Platform dll in the core dll, and hence eliminate the issue. Until then, there’s a hack we can use!

Solution: force copying the assembly during the build

Let’s take a look into how we can fix the issue. It’s luckily quite easy!

In your “class library project” (the one that Visual Studio will treat as a referenced project), you need to call a method or a class from the assembly that failed to be copied earlier. In Microsoft.IdentityModel.Clients.ActiveDirectory -assembly’s case, add the following piece of code. Add it somewhere, where it executes for sure:

        /// <summary>
        /// This should not be required, but alas.
        /// https://github.com/AzureAD/azure-activedirectory-library-for-dotnet/issues/511
        /// </summary>
        private static void MethodCallToForceLoadingOfPlatformDlls()
        {
            var creds = new UserPasswordCredential("MockAccount", "ImportantPassword");
        }

....

        Main function:

                // hack to include the dll in referencing projects
                MethodCallToForceLoadingOfPlatformDlls();

This “mock function” call – that actually does nothing, but creates an instance of a class defined in the referenced but originally not copied assembly – forces MSBuild to copy the assemblies even in the referenced project. Hence, the classes are suddenly accessible even during the runtime. This small hack worked at least for me :)

  • Conversation detailing the issue: https://github.com/AzureAD/azure-activedirectory-library-for-dotnet/issues/511
mm
4.7 3 votes
Article Rating
Subscribe
Notify of
guest

1 Comment
most voted
newest oldest
Inline Feedbacks
View all comments