Downgrade issue in MEF DLL hell - c#

I have an application, linked with other DLLs, according to MEF technology.
The "core" of that MEF looks as follows:
var cat = new AggregateCatalog();
cat.Catalogs.Add(new AssemblyCatalog(Assembly.GetAssembly(typeof(MyApp))));
cat.Catalogs.Add(new DirectoryCatalog(...));
ModuleCatalog = new CompositionContainer(cat);
MyAppModules = ModuleCatalog.GetExportedValues<IMyAppModule>();
I would like to downgrade one of the DLLs (from 84 to 83). I have done this in some of the DLLs which refer to the newest version.
However, the last line of code (with the GetExportedValues) generates an exception, mentioning Could not load file or assembly 'Relevant_DLL, Version=1.0.84.1.
This means that still at least one other DLL is referring to that 84 version. How can I know which one it is? (As you can see, I'm not able to launch the application, so debugging or using Process Explorer is out of the question)

You can use the Fusion logging to diagnose binding errors.
See this question for more info: How to enable assembly bind failure logging (Fusion) in .NET
I highly recommend this answer with using Fusion++: https://stackoverflow.com/a/56067961/6594467

Related

AssemblyLoadContext.Default in netcore 3.1 resolve the plugin type but can't excute its instance when the plugin use transitive dependency

I have a console application in netcoreapp3.1 that use a netstandard2.0 plugin.
The plugin reference a class library and implement an interface
All dll dependencies are in the the plugin folder and the plugin.dep.json include all referenced library.
When I run:
AssemblyLoadContext.Default.LoadFromAssemblyPath("path/to/main_myplugin.dll");//load plugin
it resolve the type of interface
When i try to run an instance as given below it fail:
if (type != null) //type is resolved and not null
{
var instance = (IContract)Activator.CreateInstance(type); //instance is created
Console.WriteLine($"Create instance : {instance.GetType()}"); // ok instance is created
var ret = instance.Execute(); //!!!fire exception here
Console.WriteLine(ret);
}
and fire error message:
System.IO.FileNotFoundException: 'Could not load file or assembly 'MyLibObjectsLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.'
If I loaded all dependencies, it works fine.
Should I load all dependencies when using AssemblyLoadContext.Default or it's a bug?
I asked this question in the dotnet project
All credit go to #vitek-karas.
The detailed answer is:
Currently this is by design. LoadFromAssemblyPath as well as any other LoadAssembly-like methods only ever load that assembly, they don't try to load a "plugin". For this case to work you would need the AssemblyDependencyResolver and hook it up to the Default ALC (probably via the Resolving event), and hope that there are no collisions between the host app and the plugin (since they will share all dependencies) and so on. Generally this is why it's better to load plugins into their own ALCs as that creates the necessary isolation and also makes it easy to hook up AssemblyDependencyResolver.
Higher-level answer - in 3.0 we didn't try to provide a "plugin load" API as there were too many open questions in how it should behave (the exact isolation behavior is very tricky to get right so that it would work for most use cases). Instead we provided the necessary building blocks (ALC, ADR, diag improvements, ...) and rely on users to write the cca 20 lines of code to implement the custom ALC. In 5.0 we are improving diagnostics by adding detailed tracing around the entire assembly binding process, that should help debugging issues when loading assemblies in general, but specifically when implementing custom ALCs.

Unable to debug into reference source for System.ServiceModel v 4.8.3825.0

I'm trying to track down a WCF issue, and something that would help would be to break into the framework source. I already found the section in the .net reference source that I want to step into, but the challenge is that I can't see to get the debugger to step into the code for System.ServiceModel. I've followed the steps outlined here for setting up VS (although in my case I'm on 2019 enterprise). I tried this:
var d=new Dictionary<int, int>().TryGetValue(3, out int x);
And was able to step into TryGetValue in mscorlib.dll, but this:
NetTcpBinding tcpBinding = new NetTcpBinding(SecurityMode.TransportWithMessageCredential);
BindingElementCollection outputBec = tcpBinding.CreateBindingElements();
Won't let me step into either the NetTcpBinding constructor or the CreateBindingElements method, which I know exists in the reference source.
The modules window shows that System.ServiceModel.dll is loaded from:
"C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.ServiceModel\v4.0_4.0.0.0__b77a5c561934e089\System.ServiceModel.dll",
and that the symbols are loaded from:
D:\SymbolCache\System.ServiceModel.pdb\0811c462ccbb4a418946598a612f96cd2\System.ServiceModel.pdb 6 4.8.3825.0 built by: NET48REL1LAST_B 5/31/2019 9:51 PM
I did notice that for mscorlib.dll the version was coming back as "4.8.3815.0 built by: NET48REL1LAST_C", but I'm not seeing any prerelease .net 4.8 versions installed. I've also tried disabling all symbol sources except for http://referencesource.microsoft.com/symbols, and clearing the symbol cache.
So at this point I have two questions:
1-Is there something else I should try to get .net reference source stepping to work in this case? I suspect a version mismatch, but the reference source pages don't specify the exact versions of assemblies that they're for.
2-Is there a way to verify the assembly version number from a C# PDB file? I have the PDB that I cached from the reference source, but I can't tell which assembly version this maps to.

SimpleITK Windows Universal App - does not build in release, strange behaviour in debugging and TypeLoadException

TL;DR version: Could not load type 'System.Runtime.InteropServices.HandleRef while trying to use SimpleITK on Universal Windows App.
So, right now I have to make simple school project using SimpleITK, and, I got interested in new Universal Windows Applications. I am using Visual Studio 2015 Enterprise.
So, I created a sample project, added references to SimpleITKManaged, copy&pasted SimpleITKNative to obj/Debug catalog and tried to do some tutorials. However, I learned that mixing two new technologies together may be a bad idea.
The ITK libraries I use seem not to work with Universal Windows App. After putting this snippet anywhere in the code, I can not get to debug the method. Code is not hitting breakpoint at the beggining of the method. What is inside is not important, as any type from SimpleITK is causing code to fail.
private void TestMethod()
{//breakpoint here
ImageFileReader reader = new ImageFileReader();
reader.SetFileName(FileName);
var image = reader.Execute();
}
The exception seems to be thrown before code gets to method, probably at level of XAML. I tried first implementing a call as ICommand, then as event handler in the code behind, with no differences. The exception is also not too helpful:
Could not load type 'System.Runtime.InteropServices.HandleRef' from assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
Neither is StackTrace:
at Pomwjo.Universal.MainPage.ButtonBase_OnClick(Object sender, RoutedEventArgs e)
The same libraries work well in WPF. I tried both x64 and x86 libraries, with the same problem. The build target and library architecture are matching. I'm using SimpleITK C# x86 wrapper 0.9.0, compiled with .NET v2.0.50727, using ITK 4.7.2. I got them pre-built from Sourceforge. Just after that, I found a 0.9.1 version, which I downloaded and tried to use it, to no avail.
Next step was ok, I'm a pro programmer - I'll build it myself!. I will spare describing what it is to build a huge library, let's just say it didn't work either.
Any ideas, how to fix this problem?
EDIT 1
I just realized, that if code is unreachable, it doesn't complain. Well, at least that is working as expected. But, what is even stranger, this snippet fails only if condition is met:
if (new Random().Next(1, 10)%2 == 0)
WrapperMethod(); //inside is snippet from above.
else return;
Also, when building in release, I get this error:
1>C:\Program Files (x86)\MSBuild\Microsoft\.NetNative\x64\ilc\IlcInternals.targets(791,7): error : MCG0024: MCG0024:UnresolvableTypeReference Unresolvable type reference 'System.Runtime.InteropServices.HandleRef' in 'Assembly(Name=mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)' found. Check the references in your build system. A reference is either missing or an assembly is missing an expected type.
When this question was first written, it was impossible to use simpleITK in Universal Apps because it lacked some of classes required for it to work - including System.Runtime.InteropServices.HandleRef.
Also, because all apps are run in sandbox, my guess (educated, but still guess) is that it is downright impossible to use native C++ code which is used by SimpleITK. This link describes a way to import native code into app, however this would require quite a bit of tinkering around ITK libraries itself - which was not a point in my project.

Method 'ExecuteAsync' in type 'System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy' does not have an implementation

I am newer about using Code First in c#.
After I enabled Migration in my project and launch my site, I get an Error:
Method 'ExecuteAsync' in type 'System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy' from assembly 'EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' does not have an implementation.
I have defined the context class as below.
namespace MyOA.Migration.Contexts
{
public class OADBContext : DbContext
{
public OADBContext() { }
}
}
and I tried to create the DB in Global.asax as below.
protected void Application_Start()
{
// Forces initialization of database on model changes.
using (var context = new Migration.Contexts.OADBContext())
{
context.Database.Initialize(force: true);
}
}
I tried to search the reason but got no idea.
Any suggestions?
Thanks in advance.
If you check the .NET version of the two asseblies:
EntityFramework (v4.5)
EntityFramework.SqlServer (v4.0)
You will see that EntityFramework.SqlServer has v4.0 .NET dependency, but EntityFramework uses v4.5. That is the root of the issue. I use dotpeek tool for checking the assembly version (there are other options from stack overflow to check .net vestion of an assembly).
Note: and really when you decompile EntityFramework.SqlServer.dll using jetBrains reflector tool you will find that there is no ExecuteAsync method.
What we have to do to fix the issue is to use nuget.exe (from visual studio or from stand alone nuget executable: please find "latest nuget.exe"). And run it from command line:
cd "[path to your nuget.exe]"
nuget Install EntityFramework
A set of EF 6 assemblis will be downloaded. Use the EntityFramework and EntityFramework.SqlServer from .net v4.5 folder.
I +1'd #Spirit's answer for pointing me at the root of the issue, but I was able to fix it for myself by searching through all of the *.csproj files in the solution and replacing
packages\EntityFramework.6.1.3\lib\net40\EntityFramework.dll
^^^^^
with
packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll
^^^^^
I had a mix of usages in the projects. My symptom was that NCruch would get the exception on a test, but running the same test from NUnit test runner would pass just fine.
I faced this issue in my work, and tried suggested solutions with no luck, but the solution that worked out for us was to use a relatively older version of Entity Framework, we used version 6.0.0 while the latest (as of the time I'm writing down this answer) is 6.1.3
The issue with me was that my project was targeting .Net Framework 2.0, and suddenly when upgraded to .Net Framework 4.6.1 a warning appeared so I tried to update Entity Framework package which was on the latest 6.1.3, but it stopped working properly, and got the exception mentioned above.
Hope this will help somebody later.
I had this same problem but the cause was different. In the "C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files" folder, there were several versions of the entityframe dlls. No doubt older versions. I had already recycled the iis pool and restarted the computer but that didn't work. I had to delete all the files in that folder and that did the trick.
Since all similar S/O questions are being directed to this one, I'll leave another idea to consider. Check to make sure that EntityFramework hasn't been installed into you GAC by chance. IIS will take the GAC version over your bin version leading to some serious head scratching.

System.MissingMethodException in NInject

When running our unit tests on our TFS build server, we get this error:
SetUp : System.MissingMethodException : Method not found: 'Void
Ninject.ModuleLoadExtensions.Load(Ninject.IKernel, System.Reflection.Assembly[])'.
at Ninject.Extensions.Conventions.AssemblyScanner.Process(
Assembly assembly, IKernel kernel)
which, as far as I can tell, is saying that one part of NInject can't find another part of Ninject.
The problem occurs on all three of our build servers.
Locally, it works fine.
All systems (local & remote) appear to be using the correct version of all the Ninject assemblies (as well as all the other in the application)
Any ideas?
UPDATE: Ooops thought I mentioned this in the original message:
Ninject ver 2.2.0.0
Ninject.Extensions.Conventions ver 2.2.0.5
Moste likely you use different versions of Ninject.dll and Nnject.Extensions.Conventions. E.g Ninject 3.0.0 and Conventions 2.2.0
MissingMethod exception is a deployment problem. Use the Fusion log to check what is really loaded. E.g one assembly could be in the GAC.
OK, we figured it out.
TFS build server likes putting all DLLs in the same folder. This causes a problem if you have both .Net and Silverlight assemblies with the same name (such is the case with Ninject.dll)
The solution was to change the "Output Path" on the Silverlight projects' properties page (under the "Build" tab), from the standard "bin\Release\" to something like "bin\Release\Silverlight" so the DLLs are kept separate.

Categories