One of the promises of .NET, when it came out 15 years ago, was eliminating DLL hell. Back then it was more of an issue with registering COM DLL files. Fast forward to today and the world of mixing .NET Core, .NETStandard and .NET Framework projects have brought a whole new DLL hell.

Let me walk you through my .NET Core DLL hell problem.

Note: Please cry, curse and bang your head on the wall along the way to share my full experience.

My NetStandard Library

First up, I have a simple NetStandard library. It has a couple of simple classes in it that are used by an ASP.NET Core MVC app and a .NET Framework console application. So far, so good!

Notice that I have System.IO 4.3.0, the latest version.

My Other Class Library

My console app has a bunch of classes and business logic in it. So, we stuck it all in a separate class library. This .NET Framework library also references my CoreLibrary project which is .NETStandard 1.5.

This is where all of my problems begin. When I build, I get a bunch of wonderful messages like this for basic system DLLs.

2> Consider app.config remapping of assembly “System.IO, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a” from Version “4.1.1.0” [] to Version “4.1.2.0” [C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\

et461\ref\System.IO.dll] to solve conflict and get rid of warning.

2>C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets(2099,5): warning MSB3836: The explicit binding redirect on “System.IO, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a” conflicts with an autogenerated binding redirect. Consider removing it from the application configuration file or disabling autogenerated binding redirects. The build will replace it with: “<bindingRedirect oldVersion=”0.0.0.0-4.1.2.0″ newVersion=”4.1.2.0″ xmlns=”urn:schemas-microsoft-com:asm.v1″ />”.

My project references also show a bunch of warning icons.

One of the build errors says I need to change my binding redirect from to 4.1.2, it also mentions removing it from my application configuration. Guess what? Neither one of those works.

DLL Version Hell

Here is my favorite part. My .NETStandard class library is using System.IO 4.3.0, which you can see in a screenshot at the top of this article. My .NET Framework class library is using 4.3.0 as well.

<Reference Include="System.IO, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <HintPath>..\packages\System.IO.4.3.0\lib

et462\System.IO.dll</HintPath> </Reference>

So… why the DLL hell am I getting errors about 4.1.1 and 4.1.2?

So maybe the System.IO 4.3.0 package has different version DLLs in it? Sounds like a cruel way to torture all of us developers, but let’s double check. When I look at the System.IO.dll that gets copied to my bin folder after a build… it says 4.6.24705.1, just like the one in “..\packages\System.IO.4.3.0\lib

et462\System.IO.dll”.

Really? This is a cruel way to torture us. Who is on first? What is on second?

Why Do I Have 4 Versions of the Same DLL/Package?

Let’s recap where I am at in .NET Core DLL hell exactly. I have versions 4.1.1, 4.1.2, 4.3.0, and 4.6.24705.1. Except, the only one I have actually seen is v4.6 stuck in a v4.3 folder. But I get 4.1.1 and 4.1.2 build errors. #FML

Makes sense, right?

I don’t understand why the .NET team has a v4.6 dll in a v4.3 nuget package that is really v4.1.1.

I can only assume that mixing .NETStandard and .NET Framework projects together are my problem. Although, that is the point of .NETStandard, right?

How .NET Core 2.0 Rescued Me from DLL Hell

Since .NET Core 2.0 came out, I decided to bite the bullet and switch all of my projects. I was forced to use full .NET Framework before due to a couple of nuget packages that were not available for NetStandard.

The new pseudo support for .NET Framework packages from a .NET Core application is exactly what I needed.

Here is my same project below after the change. My .NET Core DLL hell is gone! #LML

You can see the couple warnings on projects that are not .NETStandard. These are just warnings, and they actually work just fine.

Summary: Is the 2nd DLL Hell Almost Over?

Having lots of different projects that reference each other with conflicting dependencies is complicated. I get it. The complexity of making .NET Framework, netcoreapp, and .NETStandard all work together is no doubt complicated.

Let’s hope that .NET Core 2.0 solves our current set of issues. I have no idea how they deal with a .NET Core 2.0 project referencing a .NET Framework package that then references standard .NET 4.6 Framework dependencies.

I don’t care how the internals of my watch works. I don’t really care how the .NET project dependencies all work either., and I don’t want to be in DLL hell any longer!

By the way, the inside of a mechanical watch is a thing of beauty.

If you’re using .NET core, check out Retrace, which fully supports .NET core, for a full lifecycle APM.