Context
I have an application which has a dependency graph which looks like...
My Application
Dependency1 v1.0
Microsoft.Extensions.Configuration.Abstractions v5.0
Dependency2 v3.1.22
Microsoft.Extensions.Configuration v3.1.22
Microsoft.Extensions.Configuration.Abstractions v3.1.22
Aka, two different dependencies rely on Microsoft.Extensions.Configuration.Abstractions. All dependencies are minimum versions, and are indicated as allowing higher versions. Seemingly, both should accept v5.0.
Nuget correctly picks version 5.0 as the version of the dll it put out in the bin folder. But, at runtime, when My Application tries to use Dependency2, it throws an exception:
Could not load file or assembly 'Microsoft.Extensions.Configuration.Abstractions, Version=3.1.22.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. The system cannot find the file specified.
What I've tried
Installing Microsoft.Extensions.Configuration.Abstractions v5.0 explicitly
This made the dependency graph look like:
My Application
Dependency1 v1.0
Microsoft.Extensions.Configuration.Abstractions v5.0
Dependency2 v3.1.22
Microsoft.Extensions.Configuration v3.1.22
Microsoft.Extensions.Configuration.Abstractions v3.1.22
Microsoft.Extensions.Configuration.Abstractions v5.0
and otherwise changed nothing. Still get the exception.
Downgrading Dependency1 to use an older version
I had a similar issue with another dependency, and resolved that by lowering the version of the dependencies until their subdependencies' versions matched.
However, Dependency1 does not have an older version that relies on Microsoft.Extensions.Configuration.Abstractions 3.1.22, so I could not do the same on this one.
Nor can I upgrade Dependendency2 to a newer version that relies on Microsoft.Extensions.Configuration.Abstractions 5.0, because then it breaks the other one I already fixed.
Setting the DependencyVersion behavior on Dependency2 to Highest instead of Lowest
The answers on this question suggested setting the DependencyVersion behavior on Dependency2 to Highest.
I did not have the UI option described in that question, so instead I ran this command in the PackageManagerConsole
Install-Package Dependency2 -Version 3.1.22 -DependencyVersion Highest
This seemingly made no difference. It still throws the exception, but also I'm not seeing any feedback that suggests the DependencyVersion was changed for that particular dependency. I'm not sure if I missed the place to check that, or if the DependencyVersion is just not available for PackageReference projects, but I'm not sure what else to try.
I am at the limit of things I can find to try. Is there a way to tell .NET which version of Microsoft.Extensions.Configuration.Abstractions to use explicitly, for all dependencies? Or something similar to Package.config's binding redirects that let you roll old versions of packages into new versions, but for PackageReference?
Related
* Introduction to the Issue
I am using a software that uses the .Net framework to perform some tasks.
We are trying to use the Mailkit.dll file but when using it we are faced with the message:
Internal : Could not execute code stage because exception thrown by code stage: Could not load file or assembly 'System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
and from what I have concluded so far the Mailkit.dll depends on Mimekit.dll that depends on System.memory.dll, something like that.
Mailkit.dll > Mimekit.dll > System.Memory.dll
Version details:
.Net framework installed on machine: 4.7.3190
.Net framework used by application: 4.7
Mailkit.dll version: 3.4.1
Mimekit.dll Version: 3.4.1
System.Memory.dll in application folder Version:4.6.28619.01
I don't Know what's the issue or why this is happening but I am pretty sure it has to do with version issue so any help is welcomed.
The version numbers you provided are a good starting point.
For .NETFramework 4.7, MailKit v3.4.1 depends on MimeKit v3.4.1 which depends on System.Memory >= v4.5.5.
System.Memory with NuGet version v4.5.5 has an AssemblyFileVersion of 4.6.31308.01 (the number that shows in windows explorer) but an AssemblyVersion of 4.0.1.2. The assembly number is what really matters when the CLR looks for assemblies. The CLR looks for v4.0.1.2 when loading MimeKit but can only find v4.0.1.1.
The version that ends up in your output is older than the version required. I found that the version that is actually in your output is from System.Memory v4.5.4. AssemblyFileVersion: 4.6.28619.01. AssemblyVersion: 4.0.1.1.
This is probably happening if you are referencing System.Memory nuget package directly. If you do have a direct package reference to System.Memory, then you need to upgrade it.
If you were using SDK styled projects, you would get an error preventing this from happening. But you should still be getting a build warning about version conflicts detected.
I have a console program that has two direct dependencies: ClosedXML v0.97 and ClosedXML.Report 0.2.4. The ClosedXML.Report dependency also depends on ClosedXML, but in a version 0.95.
When I try to compile the program in NET6 (basically only a reference to a class in the ClosedXml.Report),
_ = new XLTemplate(new System.IO.MemoryStream());
I get a compiler error
CS0012 The type 'IXLWorkbook' is defined in an assembly that is not referenced. You must add a reference to assembly 'ClosedXML, Version=0.95.0.0, Culture=neutral, PublicKeyToken=null'.
Why doesn't csc.exe recognize the 0.97 version to use and requests 0.95 (the indirect dependency)? The assembly version of package is same as the nuget version.
Nuget uses direct-dependency-wins mechanism and I though .net core also uses that for assemlby resolution. Is a mechanism different? How does roslyn resolve which version to use and when to throw an error?
Relevant piece of MSBuild
C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\Roslyn\csc.exe
/reference:C:\Users\username\.nuget\packages\closedxml\0.97.0\lib\netstandard2.0\ClosedXML.dll
/reference:C:\Users\username\.nuget\packages\closedxml.report\0.2.4\lib\netstandard2.0\ClosedXML.Report.dll
One possible explanation for this behavior would be if IXLWorkbook, which is apparently required by the call to new XLTemplate() no longer exists in Version 0.97 of ClosedXML.
If possible, try to rebuild ClosedXML.Report with ClosedXML 0.97. Since these apparently are early versions (Version < 1.0) breaking changes between versions seem possible. Also, can you make sure that the output bin directory actually contains Version 0.97?
I'm using these pacakges:
PackageReference Include="Polly" Version="7.2.2"
PackageReference Include="Polly.Caching.Memory" Version="3.0.2"
I have a testproject that uses these packages and the code works.
When I try to integrate my code in an existing application with lots of other nuget packages, suddenly I get a TypeLoadException.
The method TryGet in the type Polly.Caching.Memory.MemoryCacheProvider from the assembly Polly.Caching.Memory, Version=3.0.0.0, Culture=neutral, PublicKeyToken=c8a3ffc3f8f825cc doesn't have an implementation.
I have been checking everything, but I can't find the cause of this.
The versions of Polly and Polly.Caching.Memory are aligned across all projects involved.
In the bin folder the correct version appears.
I looked at the code of the assembly and the code has an implementation for TryGet
Any suggestion on what I can do to further investigate this?
The packages were all correctly configured.
I got on the right track when I saw that the method was returning a tuple.
I figured that perhaps this second application was not using the correct versions of the same packages.
I changed :
<HintPath>..\Solutions\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll</HintPath>
To
<HintPath>..\Solutions\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll</HintPath>
Bingo!
In my .Net Standard Library Project,
System.Configuration.ConfigurationManager does not seem to work.
Even the method Does not get called, which contains the Statement
object o = ConfigurationManager.GetSection(_strSectionName);
I have Installed the Nuget package
System.Configuration.ConfigurationManager version 4.6.0
But if I right click on ConfigurationManager in this statement,
object o = ConfigurationManager.GetSection(_strSectionName);
It shows me the metadata of version 4.0.2.0, namely
Assembly System.Configuration.ConfigurationManager, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
where I think the version it should go to is 4.6.0.
Maybe that is causing the problem.
The assembly version is correct, it should be 4.0.2.0, this is separate from the package version (here 4.6.0).
This is not the cause of your problem. The next thing to look at is the exception, or the incorrect behaviour.
There is a recent principle on Nuget package parsing. For details, see how NuGet parses package dependencies. A Microsoft diagram is used to explain:
This time you will choose the most recent package, which is the 2.0 version.
no problem.
One problem I encountered today is that one of my Nuget packages (called Package A current version 1.2.3) originally only supports the version of netstandard 2.0, which is defined in the csproj file.
<TargetFramework>netstandard2.0</TargetFramework>
I have another product, the ECS Nuget package (called Package B version 1.0.0), and Package B needs to reference Package A.
The relationship route is [Package B 1.0.0] -> [Package A 1.2.3]
At this time, the two packages in the program can be used normally.
Later, due to the support of the .net framework, I modified the original package A nuget package and changed it to the following.
<TargetFrameworks>netstandard2.0;net45</TargetFrameworks>
Package A package generation version is 1.3.2. At this time, I refer to the above two packages and find that the compilation is ok, but I am getting an error at runtime.
I can solve the above problem by upgrading Package B, but why is this error?
Is it because of the use of TargetFrameworks?
I also hope that the big men will give pointers.
When I compare the *.deps.json file, I found something helpful. Here is the first scenario get the following json file:
"aliyun-net-sdk-core/1.3.2": {
"dependencies": {
"Serilog": "2.5.0",
"Serilog.Exceptions": "4.0.0",
"Serilog.Sinks.File": "4.0.0"
},
"runtime": {
"lib/netstandard2.0/aliyun-net-sdk-core.dll": {
"assemblyVersion": "0.0.0.0",
"fileVersion": "0.0.0.0"
}
}
}
Because of the reference to version 1.3.2, however, the CLR can't find the DLL with Version 1.3.2 when loading the assembly, there is only assembly version 0.0.0.0, so the CLR looks for the 1.2.3 version referenced by the original project, but it is not found, so it reports an error.
Clearly understood.
After I make up the miss assembly version of the project, I got the
right result.