C
C#13mo ago
zed

✅ Resolving an ambiguous assembly reference

We recently upgraded an included NuGet package from version 2.0.1 to 3.0.1 (Spring.NET, in case it matters). Now we get this exception:
Could not load file or assembly 'Spring.Services, Version=2.0.1.45000, Culture=neutral, PublicKeyToken=65e474d141e25e07' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
Could not load file or assembly 'Spring.Services, Version=2.0.1.45000, Culture=neutral, PublicKeyToken=65e474d141e25e07' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
This indicates, that we missed upgrading one of our components, but we cannot find out which one. We're also including some third party components, which have (ostensibly) also been updated to use Spring.NET 3.0.1. But the provider assures us, that all projects in their solution were upgraded to use version 3.0.1. Now we're at a loss. Is there a way to get more detailed information on which of our assemblies or components tries to reference the older version? A plain text search across all our .csproj and .config files revealed no reference to 2.0.1, and we're not sure what else to do.
27 Replies
zed
zed13mo ago
Oh, to be clear, this is about .NET Framework 4.8
reflectronic
reflectronic13mo ago
what does the FusionLog property on the FileLoadException contain?
zed
zed13mo ago
Sorry, was asleep... the property shows this (unfortunately it's in German... fuck knows why):
=== Zustandsinformationen vor Bindung ===
LOG: DisplayName = Spring.Services, Version=2.0.1.45000, Culture=neutral, PublicKeyToken=65e474d141e25e07\n (Fully-specified)
LOG: Appbase = file:///C:/Code/xxx/
LOG: Ursprünglicher PrivatePath = C:\\Code\\xxx\\bin
Aufruf von Assembly : (Unknown).
===
LOG: Diese Bindung startet im default-Load-Kontext.
LOG: Die Anwendungskonfigurationsdatei wird verwendet: C:\\Code\\xxx\\web.config
LOG: Die Hostkonfigurationsdatei wird verwendet: C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\aspnet.config
LOG: Die Computerkonfigurationsdatei von C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\config\\machine.config wird verwendet.
LOG: Verweis nach der Richtlinie: Spring.Services, Version=2.0.1.45000, Culture=neutral, PublicKeyToken=65e474d141e25e07
LOG: Download von neuem URL file:///C:/Windows/Microsoft.NET/Framework64/v4.0.30319/Temporary ASP.NET Files/xxx/14409dfc/ee30ea1/Spring.Services.DLL.
LOG: Download von neuem URL file:///C:/Windows/Microsoft.NET/Framework64/v4.0.30319/Temporary ASP.NET Files/xxx/14409dfc/ee30ea1/Spring.Services/Spring.Services.DLL.
LOG: Download von neuem URL file:///C:/Code/xxx/bin/Spring.Services.DLL.
WRN: Der Vergleich des Assemblynamens führte zum Konflikt: Hauptversion.
ERR: Das Setup der Assembly konnte nicht abgeschlossen werden (hr = 0x80131040). Die Suche wurde beendet.
=== Zustandsinformationen vor Bindung ===
LOG: DisplayName = Spring.Services, Version=2.0.1.45000, Culture=neutral, PublicKeyToken=65e474d141e25e07\n (Fully-specified)
LOG: Appbase = file:///C:/Code/xxx/
LOG: Ursprünglicher PrivatePath = C:\\Code\\xxx\\bin
Aufruf von Assembly : (Unknown).
===
LOG: Diese Bindung startet im default-Load-Kontext.
LOG: Die Anwendungskonfigurationsdatei wird verwendet: C:\\Code\\xxx\\web.config
LOG: Die Hostkonfigurationsdatei wird verwendet: C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\aspnet.config
LOG: Die Computerkonfigurationsdatei von C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\config\\machine.config wird verwendet.
LOG: Verweis nach der Richtlinie: Spring.Services, Version=2.0.1.45000, Culture=neutral, PublicKeyToken=65e474d141e25e07
LOG: Download von neuem URL file:///C:/Windows/Microsoft.NET/Framework64/v4.0.30319/Temporary ASP.NET Files/xxx/14409dfc/ee30ea1/Spring.Services.DLL.
LOG: Download von neuem URL file:///C:/Windows/Microsoft.NET/Framework64/v4.0.30319/Temporary ASP.NET Files/xxx/14409dfc/ee30ea1/Spring.Services/Spring.Services.DLL.
LOG: Download von neuem URL file:///C:/Code/xxx/bin/Spring.Services.DLL.
WRN: Der Vergleich des Assemblynamens führte zum Konflikt: Hauptversion.
ERR: Das Setup der Assembly konnte nicht abgeschlossen werden (hr = 0x80131040). Die Suche wurde beendet.
It says, essentially, that it looks for Spring.Services, Version=2.0.1.45000, Culture=neutral, PublicKeyToken=65e474d141e25e07 and the paths it looks for that in, then finds it, but with a different version But it doesn't say which assembly requires that lookup in the first place
reflectronic
reflectronic13mo ago
what about the stack trace, that should tell you which code tried to load Spring.Services
zed
zed13mo ago
Unfortunately it doesn't catch the exception as it happens >< I only see it caught in our outer exception handler in the global ASP.NET request handler (I have all exception type checkboxes ticked... not sure why it doesn't catch it as it happens) Fwiw it happens during the initialization of our IoC context Which is what we use Spring.NET for Actually, I had "just my code" enabled in the debugging options Gonna try again after adjusting the settings
reflectronic
reflectronic13mo ago
you should be able to access ex.StackTrace though, right? that does not change based on who catches it
zed
zed13mo ago
Good point... but I actually did get it to catch it live with the new settings
zed
zed13mo ago
Unfortunately, it doesn't help me much ><
zed
zed13mo ago
Actually, capturing it live might be helpful... going through the stack trace, I can access some member variables and parameters that may be helpful
reflectronic
reflectronic13mo ago
what is passed to Type.GetType this looks like the problem is in some kind of config file, where you specify the FQN of a type, and the FQN has Version=2.0.1.4500 in it though i don't know very much about WCF i would try to look through the System.ServiceModel parts of the stack trace to see if you can find a reference to the config file somewhere maybe you will get lucky and it's in a local variable somewhere
zed
zed13mo ago
Actually, for some reason I can't see any arguments or local variables when browsing the stack trace during an exception... I guess it's only preserved the stack information, but has already unwinded it?
zed
zed13mo ago
Or is there a way to obtain these values? Unwound? 🤔 This seems to be the case, just going by the info I'm getting >< But I don't see where, I already grepped the entire repository for 2.0.1 and found nothing :\
reflectronic
reflectronic13mo ago
try enabling these two options in the debugger settings
reflectronic
reflectronic13mo ago
(you will probablby want to turn them off after you are done)
zed
zed13mo ago
Thanks, will try Also, thanks for helping, really appreiate it Unfortunately, I'm still not seeing any local variables or parameters x.x I tried a few other things, still not getting very far. I just had an idea to set a breakpoint on mscorlib.dll!System.Type.GetType(string) but not sure if that works, do you happen to know what I have to do to be able to do that? If it works at all...
reflectronic
reflectronic13mo ago
does it not work if you just add that to the breakpoints window?
zed
zed13mo ago
It's just hollowed out, not sure... since that function is called a billion times, I added a condition, but debugging it will probably take an hour or so like this, so I'm still waiting, but it still shows only as hollowed out So not sure if it will work at all
reflectronic
reflectronic13mo ago
hm, if it's hollowed out then it probably won't work what if you just do GetType it should set a bunch of breakpoints and then you can disable all of them except for the one
zed
zed13mo ago
Did not know that was even a thing... I'll try it in a sec Sorry this is taking me so long >< This worked, that is a pretty great feature, thanks for telling me about it. It helped me narrow it down a bit further. I debugged the .NET WCF library in question, and I think it comes down to this code:
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
for (int i = 0; i < assemblies.Length; i++)
{
compiledType = assemblies[i].GetType(factoryType, false);
if (compiledType != null)
{
break;
}
}
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
for (int i = 0; i < assemblies.Length; i++)
{
compiledType = assemblies[i].GetType(factoryType, false);
if (compiledType != null)
{
break;
}
}
Unfortunately I can't be 100% sure, since my source mismatch is pretty wide. Not sure why, I downloaded the 4.8 reference source and tried to debug using that, but the file is nowhere close to the symbol information :\ But this is the only part of the code that could explain it, and I see this in the debug window Locals So it seems it's part of the assemblies referenced in the current appdomain? Which still doesn't help me narrow down how it got there :( Thanks for all your help so far, but if you don't know how to proceed from here, I'm willing to just give up and find some other workaround x.x
zed
zed13mo ago
Had to delete the image here, since it contained some internal assembly names 😅 But essentially this:
reflectronic
reflectronic13mo ago
i think to make it work you need to set the "Enable .NET Framework source stepping" option
zed
zed13mo ago
I saw that online, but I can't find that option anywhere
zed
zed13mo ago
These are all the options I have
zed
zed13mo ago
Maybe my VS install is missing some workloads...
reflectronic
reflectronic13mo ago
hm, it used to be there
Accord
Accord13mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
zed
zed13mo ago
Just for future reference, if anyone finds this - turns out it wasn't references anywhere and IIS just cached the files.... Deleting everything in the following two paths resolved the issue:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files