Closed kiran-bobade closed 5 years ago
@kiran-bobade, I see similar behavior when referencing a .Net Standard 2.0 project (with the ConfigurationManager package) from a Xamarin project (see below).
Could not load file or assembly 'System.Configuration.ConfigurationManager' or one of its dependencies
However, if I add the ConfigurationManager package in Xamarin project, and move the code into the Xamarin project, it works fine. Ideally I'd like to keep the ConfigurationManager code out of the Xamarin project.
Same here. In my case, I created an ASP.NET Core 2 (.NET Core2) app and added an reference to an .netstandard2.0.2 class library, which then references EF6 through nuget. Then in startup.cs I tried to instantiate an DbContext by passing an IConfiguration as argument to its constructor. When the runtime callsbase(config.GetConnectionString("connsString"))
this exception is throw.
mm that is weird, ConfigurationManager in inbox on pretty much all platforms, so this doesn't make that much sense. What version of VS are you using to build? I ask because if you don't have VS15.3 or above then errors like this are expected since netstandard on netfx support was added then. If you do have a newer version of VS, can you try setting this property on your netfx .csproj:
<PropertyGroup>
<_HasReferenceToSystemRuntime>true</_HasReferenceToSystemRuntime>
</PropertyGroup>
I'm experiencing this exact issue with System.Configuration. Any news for participants on how this was resolved?
Which version of VS are you using? I would expect that if you are using a recent one (VS 15.3 or higher) this scenario should just work.
@joperezr : VS 2017 (15.4.4). It was the build coming off of our build server that was problematic, which doesn't use VS but has the latest SDK (2.0.3). It appeared to resolve when I explicitly added a reference to the System.Configuration.ConfigurationManager package to the top level (Net462) project. When it was indirectly referenced from the dependent NetStandard2.0 package, it was not resolving properly.
I see, I would have expected that you wouldn't need to add a reference to that package directly from your net462 project but I'm glad things worked out. Just as FYI, we are currently working on building a metapackage that will add a lot of compatibility between .NETStandard and .NET Framework, and this one includes assemblies like System.Configuration.ConfigurationManager.
@joperezr Agreed, not sure why that's the behavior I'm observing, but I can live with the extra package reference. Thanks for the additional info.
I'm having this same issue in vs 15.5.4 .net framework using a .net standard 2.0 both trying to use system.configuration.configurationmanager.
Also running into this with many (but, weirdly, not all!) .NET Framework 4.6.2 assemblies referencing a .NET Standard 2.0 class library that uses System.Configuration.ConfigurationManager 4.4.1. The workaround of adding a reference to the top-level assembly (EXE or NUnit test class library) seems to work.
I'm hitting this issue using VS 15.6.7.
The package that I mentioned above is Microsoft.Windows.Compatibility in case anybody hitting an issue wants to try it out. It is still in preview but might be a good workaround for folks hitting issues.
@joperezr Can you please confirm what the correct fix is for this issue?
I don't want to add a reference to System.Configuration.Configuration manager from my .NET 4.7.2 project to prevent runtime error. My main concern with this is that someone in the future may see this reference as "unused" and remove it, the project will still build but will lead to runtime errors.
Can you explain how the above package (Compatability) can be used as a proper solution?
Also in this situation - I am converting a class library to .NET standard for an enterprise solution - we may have 50+ projects that consume this - so potentially I need to add this reference in 50 places?
@nzandy
Can you explain how the above package (Compatability) can be used as a proper solution?
.NET Frameworks run on different platforms (for example .NET Framewrok 4.7.2 or .NET Core 2.1) and each platform defines types in certain assemblies. Some of the types will live on one assembly on one platform, but on a different one on another platform. One example is ConfigurationManager class, which lives in System.Configuration.ConfigurationManager
on .NET Core, and in System.Configuration
on .NET Framework. In order for types to unify when running a .NET Core app that consumes .NET Framework libraries you need some re-mappers that will make sure that all of these types unify to the same assembly. That is what the Compatibility package provides. It ensures that all of the types that live on different assemblies for different frameworks will unify to the same assembly at runtime. On this Compatibility package, System.Configuration.ConfigurationManager will also be includded.
I am converting a class library to .NET standard for an enterprise solution - we may have 50+ projects that consume this - so potentially I need to add this reference in 50 places?
If you are using the PackageReference
model in your project, MSBuild should automatically add these indirect dependencies for you. For example: if your library A.dll depends on the compatibility package, and your project B has a Project To Project reference to project A, then B will automatically get a reference to the compatibility package.
I hope this answers your questions but do let me know if you need any help.
@joperezr So I have a Dotnet Standard 2.0 project that depends on a Dotnet Framework 4.6.2 project. I have a dependency on System.Configuration.ConfigurationManager
and I'm trying to use the ConnectionStringSettings
type but I get this error:
error CS0012: The type 'ConnectionStringSettings' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
I tried adding the Microsoft.Windows.Compatibility
library to the Dotnet Standard project but I still get the same error.
Is this a supported use case?
It seems if I convert the Dotnet Framework 4.6.2 project to Dotnet Standard the error is fixed but that isn't feasible for me at the moment.
@AlexDenton who depends on the package System.Configuration.ConfigurationManager
? your .NetStandard lib or your .NET Framewrok one? From what I can see, it looks like the problem should be happening on your .NET Framework one, and seems like what you need is to add a reference to that project like:
<ItemGroup>
<Reference Include="System.Configuraiton" />
</ItemGroup>
Since that is the assembly where ConnectionStringSettings
lives for .NET Framework.
Is this a supported use case?
Technically no. What we support officially is for a .NET Framework project to depend on a .NET Standard one, but not the other way around. The reason is that .NET Standard should run on different platforms, while .NET Framework is only supported on Windows. So what you are doing is writing a .NET Standard lib (which should run everywhere where .NET Standard is supported) depending on a .NET Framework lib (which will only run where .NET Framework runs). The reason why we 'allow' these type of dependencies is because a lot of what lives in .NET Framework 4.6.2 is already part of .NET Standard, so we assume that you will only call those APIs and that your app should just work. On the other hand, .NET Standard runs everywhere that .NET Framework runs which is why having if you had your dependency go the other way it would just work.
@joperezr
who depends on the package System.Configuration.ConfigurationManager?
They both do. I have created a sample repo to demonstrate the issue: https://github.com/AlexDenton/DependencyProblem
Technically no. What we support officially is for a .NET Framework project to depend on a .NET Standard one, but not the other way around. The reason is that .NET Standard should run on different platforms, while .NET Framework is only supported on Windows. So what you are doing is writing a .NET Standard lib (which should run everywhere where .NET Standard is supported) depending on a .NET Framework lib (which will only run where .NET Framework runs). The reason why we 'allow' these type of dependencies is because a lot of what lives in .NET Framework 4.6.2 is already part of .NET Standard, so we assume that you will only call those APIs and that your app should just work. On the other hand, .NET Standard runs everywhere that .NET Framework runs which is why having if you had your dependency go the other way it would just work.
That all makes sense. I definitely understood I was getting into murky waters by going down this path but I'm trying to do a gradual migration and this seemed like the easier path for me right now. That being said, the specific library I'm trying to reference should work for both ways (System.Configuration
).
Having dug in a bit more on my own I think I kind of understand the issue. It seems the .NET Framework System.Configuration.ConfigurationManager
library depends on System.Configuration 4.0.0.0
while the .NET Standard System.Configuration.ConfigurationManager
library depends on System.Configuration 4.0.1.0
. And then the interesting thing is according to this (https://apisof.net/catalog/System.Configuration) those two libraries have two totally different `PublicKeyToken's. I could be wrong (I'm diving deeper than I've had to before) but that seems like it's probably the issue.
I'm not clear on if this is something the Microsoft.Windows.Compatibility
package is supposed to solve or if this is just an irreconcilable problem. Perhaps the repo I linked will explain better what I'm trying to do.
Oh, and thanks for your help! I'm eager to get migrated but I'm trying to do it one chunk at a time. Figuring this out would make that much easier.
Cheers!
@joperezr So having slept on it I think I have a clearer picture of what's happening. When I install System.Configuration.ConfigurationManger
on my 4.6.2 project it automatically references the System.Configuration 4.0.0
assembly that's installed on the machine. But when I install it on my Dotnet Standard 2.0 project it doesn't pull in that assembly and seems to reference this:
https://github.com/dotnet/corefx/blob/master/src/System.Configuration.ConfigurationManager/ref/System.Configuration.cs.
Because those two assemblies have different PublicKeyToken
s it's not compatible. However, I can't remove the System.Configuration
reference in the 4.6.2 project because then I can't use ConnectionStringSettings
. So I appear to be stuck.
Again, this may not be something you guys care to support but hopefully I at least articulated what I'm experiencing more clearly.
Thanks again!
The assembly versions have nothing to do with the problem you are seeing. The real problem here is the following: Your framework project thinks that the type ConnectionStringSettings
lives on System.Configuration.dll so it depends on that. For your StandardProject on the other hand, this type lives on System.Configuration.ConfigurationManager.dll. In order for both projects to agree that this type is the same, we need to pass a special System.Configuration.dll to our StandardProject that will redirect this type back to System.ConfigurationManager.dll. That way, when the compiler is resolving ConnectionStringsSettings
for both the standard project and the framework project it uses this logic: FrameworkProject.dll -> System.Configuration.dll -> System.Configuration.ConfigurationManager.dll
and StandardProject.dll -> System.Configuration.ConfigurationManager.dll
so they agree on the same type and the compiler is happy. Given that this is really a scenario that we don't support (referencing a framework project from a standard project) then we don't really have that System.Configuration.dll shim that would redirect the type to S.C.ConfigurationManager.dll but we do have the shim if instead of targeting netstandard2.0 you target netcoreapp2.0. This shim (or remapper) can be obtained by referencing the Microsoft.Windows.Compatibility package.
I took the liberty of adding these two changes into a fork I made from your repo so you can take a look at those changes here: https://github.com/joperezr/DependencyProblem/commit/c2c3670ede12428312bd291cd80f4eacda6d21c8
I know that this might be a bunch of info, but I hope that it all makes sense. If it doesn't please don't hesitate to ask questions. FWIW, in order for you to continue your progress of moving to .NET Standard, I would start with the leaf projects ( the ones that don't have other project dependencies) that way you will always be in supported land (since as I said before, referencing a .NET Standard library form a .NET Framework library is totally supported) so going the other way would definitely cause you less troubles.
Given that this is really a scenario that we don't support (referencing a framework project from a standard project) then we don't really have that System.Configuration.dll shim that would redirect the type to S.C.ConfigurationManager.dll but we do have the shim if instead of targeting netstandard2.0 you target netcoreapp2.0
I see! I hadn't considered trying the compatibility library with .NET Core. I assumed it worked the same for either but that's just my ignorance.
I know that this might be a bunch of info, but I hope that it all makes sense
I follow you at least at a high level. My curiosity has me wondering what Microsoft.Windows.Compatibility
is actually doing. I looked briefly at https://github.com/dotnet/corefx/tree/master/pkg/Microsoft.Windows.Compatibility but I didn't spend enough time to digest it.
FWIW, in order for you to continue your progress of moving to .NET Standard, I would start with the leaf projects
Yeah, I've been trying to do as you suggest. I was hoping to deploy one of my microservices independently on .NET Core but eventually ran into a shared dependency that started this whole problem. Unfortunately that project gets used by all of my microservices so I'll have to find another path.
Anyway. That's probably oversharing but at least I have a potential option to help me move forward.
Once again, thanks for your help!
I follow you at least at a high level. My curiosity has me wondering what Microsoft.Windows.Compatibility is actually doing. I looked briefly at https://github.com/dotnet/corefx/tree/master/pkg/Microsoft.Windows.Compatibility but I didn't spend enough time to digest it.
Glad to know it made some sense and that you know the path forward. As to for what the compatibility package does, among other things, it will restore package: Microsoft.Windows.Compatibility.Shims
, which if you download from here and inspect its contents, you'll find that inside the folder of lib\netcoreapp2.0
there is a System.Configuration.dll that will now be referenced by your project which will take care of the remapping of ConnectionStringsSettings
to System.Configuration.ConfigurationManager.dll. That is what makes the build with my changes to all start working and compiling now.
Glad to know it made some sense and that you know the path forward.
I'm sorry, but I don't understand why targeting .NET Core 2.0 is the "path forward". I thought the purpose of .NET Standard was to provide the standardization, and .NET Core is only for new hotness. Now it's really confusing to me that .NET Core 2.0 is the best way to target net461 dependencies. Can you please rephrase? ...because my brain has yet to accept/wrap my head around this mess.
I've been having all sorts of Dependency issue, this one System.Configuration was a big one. Honestly whoever suggested Microsoft.Windows.Compatability saved me a heap of time and time in the future. It's excellent. Thanks!
I just ran into this. I have
When I ran WebSiteB I was getting the cannot load System.Configuration exception detailed above. I added Microsoft.Windows.Compatibility to WebsiteB and the problem went away (at the cost of a lot of new packages and dlls being added to the project). Is this the right thing to do? I am confused because the docs for that package say it is only for .Net Core apps: https://www.nuget.org/packages/Microsoft.Windows.Compatibility
Or should I be adding Microsoft.Windows.Compatibility to the LibraryA?
Would really like some guidance on what we are supposed to do here, because LibraryA is used in about 100 other projects, most of which are still on Net Framework 4.6.2. I'm trying to port it to Net Standard in order to move forward.
UPDATE: I think I answered my own question, it doesn't work if you just add it to the LibraryA.
Still find the docs confusing though.
@PhilipDaniels I had the same exact scenario as you. .Net Framework 4.5 Class library that deals with databases - which is referenced into a .net Core project... I still don't understand why but I had to install https://www.nuget.org/packages/System.Configuration.ConfigurationManager/ in both projects to make it work.
@joperezr, I'm still not seeing the solution here. Perhaps I've just missed it since there have been multiple conversation threads here with multiple different scenarios.
I have the following setup:
Console App (.Net Framework 4.6.1)
-> Library (.Net Standard)
-> System.Configuration.ConfigurationManager.dll
In this case, the Console App
is not getting my System.Configuration.ConfigurationManager.dll copied to the bin and I'm getting the same exception as in the original post:
Could not load file or assembly 'System.Configuration.ConfigurationManager, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The system cannot find the file specified.
Adding a reference to System.Configuration.ConfigurationManager.dll
to the main console app is not a realistic solution for us and seems like a workaround at best.
@ryno1234
Are you able to convert your .NET 4.6.1 Console app to use
Following the advice here https://docs.microsoft.com/en-us/nuget/reference/migrate-packages-config-to-package-reference
You can right click your packages.config and click "Migrate packages.config to PackageReference"
I think this would solve your issue, note that there are specific projects that won't be unable to be converted to this format (I can find some more info on this if you require, but that migration tool above should alert you if this is the case for you)
For reference, here is the specific issue you are running into (with a very good explanation):
Had same issue.
Had a class library project built in dotnetstandard 2.0 and a Windows Service Application built in dotnet framework 4.6.1. Got same error:
Could not load file or assembly 'System.Configuration.ConfigurationManager, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The system cannot find the file specified.
Added library: Microsoft.Windows.Compatibility from nugget. Now I have access to DotNetFramework API's from DotNetStandard 2.0. Hope this helps someone.
Just to be clear here: System.Configuration.ConfigurationManager is not part of .NETStandard2.0. It's a package you're referencing. That package has to provide different implementations since in some cases it's providing an implementation and in other cases it's forwarding to existing desktop types. It needs to be referenced in applications consuming it, especially if those applications have a different target framework than the library using packages (eg: net4x vs netstandard) so that it can provide the correct implementation for your application.
NuGet 2 / packages.config did not flow packages across ProjectReferences: one of the big reasons NuGet3 was created. That is the cause of the FileNotFoundException: you will see that for any package you use from a .NETStandard library project. The folks who designed the .NETStandard SDK (/cc @livarcocc @nguerrera @dsplaisted) were very careful about not copying the netstandard implementation DLLs to the output directory so that you get a FileNotFoundException here, rather than bad runtime behavior due to choosing the wrong implementation. (see https://github.com/dotnet/corefx/issues/21197 where folks disable that behavior)
The solution is to reference the package in one of many ways:
I'd really love it if PackageReference was the default. @rrelyea and @rido-min and others working on NuGet have reasons we can't do that. As a result we're in this place where we have this common pitfall.
@ericstj Thanks for the thoughtful reply. Would I be tongue-in-cheek if I suggested that in order for Rob and Ricardo to consider their work accomplished, they handle scenarios like the ones FluentMigrator deals with when exposing its library logic as an MSBuild task? :) A PR would be even nicer...
Here are a couple issues. Also adding @jainaashish. https://github.com/NuGet/Home/issues/4942 https://github.com/NuGet/Home/issues/5877
I'm honestly not sure where NuGet stands on changing the default from packages.config to PackageReference. I suspect there will always be some old projects that don't migrate and folks want to work with new projects/packages. I wonder if we got NuGet, SDK, or MSBuild to identify a problematic case and raise an error if it would help. If you had an MSBuild error that could be suppressed that told you that you had a projectreference to some project using PackageReference but you were not, do you think that would help with this issue?
I think MSBuild tasks as an app model need some love as well, which is part of what we're discussing https://github.com/Microsoft/msbuild/issues/1309. Let's try to keep that discussion separte, I think it has some unique problems since it adds the host/plugin problem space.
For what it's worth, I think you should put in a packages.config to PackageReference converter for web application projects (that have a global asax) before you default anything like that.
@timdoke That's not a bad suggestion, but it would probably belong as part of https://github.com/RSuter/DNT#solution-commands - I realize that isn't a Microsoft-sponsored project, and Visual Studio tooling is probably a must for most, but if you're a library author on .NET SDK projects, @RSuter 's DNT extensions are a MUST.
@jzabroski Nice.. If that works to convert to PackageReference from packages.config for web application projects, that would be great. It does say it can perform that operation against all csproj files.. I might have to test it out.
@jzabroski thanks for mentioning dnt! New commands are always welcome! 🙂
But maybe you should checkout this converter which migrates to new sdk-style projects - it looks promising: https://github.com/hvanbakel/CsprojToVs2017
If its only about packages.config to PackageReferences then it would be quite easy to do in dnt - probably everything needed is already there somewhere...
I agree, @RSuter 's switch-assemblies-to-projects
command is not quite what you're looking for but it's close. I think I've seen one that converts CsprojToVs2017 besides that one, too, though, but can't remember where I saw it.
EDIT: Found it. It's the same one. @natemcmaster has it in dotnet-tools repo: dotnet-migrate-2017
@joperezr : VS 2017 (15.4.4). It was the build coming off of our build server that was problematic, which doesn't use VS but has the latest SDK (2.0.3). It appeared to resolve when I explicitly added a reference to the System.Configuration.ConfigurationManager package to the top level (Net462) project. When it was indirectly referenced from the dependent NetStandard2.0 package, it was not resolving properly.
I was struggling with this whole f*** day. You saved my life!
Closing as the discussion seems to be resolved, and we have pre-existing tracking for the underlying issue (see https://github.com/dotnet/standard/issues/936#issuecomment-432548325)
Just one more idea if anyone isn't satisfied with Microsoft.Compatibility.Windows Nuget (it actually worked for me but I felt risky to commit so many new Nuget packages, especially taking into account package description didn't quite match my scenario, so I was not sure why it was working in fact).
I managed to make things work by making project, which uses ConfigurationManager, a multi-target framework project. So when my class library is used from .NET Framework project, it is compiled using native framework System.Configuration.dll, and when it is referenced by .NET Standard or Core-targeted project - it is compiled using Nuget System.Configuration.ConfigurationManager.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net471</TargetFrameworks>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="System.Configuration.ConfigurationManager" Version="4.5.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net471'">
<Reference Include="System.Configuration" />
</ItemGroup>
</Project>
Today I've found another workaround, that works for me, but I have no idea why. At the beginning of my application (in my case - in the [OneTimeSetUp]
of NUnit tests), I do
System.Reflection.Assembly.Load("System.Configuration.ConfigurationManager");
I have an assembly created in NetStandard2.0. It reads AppSettings using System.Configuration.ConfigurationManager. I have installed nuget package of System.Configuration.ConfigurationManager with version 4.4.X which is suitable for NetStandard2.0.
When I refer this assembly in console app (.Net Core) it is reading AppSettings properly, but when I refer this assembly in old .NetFramework(4.6.X) console app it is not working and throwing an exception.
Please see the code below.
Assembly 1: NetStandard 2.0
Nuget: System.Configuration.ConfigurationManager 4.4.0
Console App: NetFx 4.6.X
Exception After Run:
It will work with Console App developed using .NetCore.
Here is the other link I followed. #425
Please help!!!