Use different versions of referenced DLL - c#

Somehow I've been lucky and never had to deal with this problem, even though I think it's a common one:
I've got a web project, let's call it SomeProject. SomeProject has a reference to a 3rd party library, let's call it SomeThirdParty, version 1.0. SomeProject also has a reference to a home-grown class library, let's call it SomeLibrary. SomeLibrary also has a reference to SomeThirdParty, but a different version (let's say 2.0).
Version 1.0 and 2.0 of SomeThirdParty share most of the same signatures, but are different implementations. I need SomeProject to use the 1.0 implementation, and SomeLibrary to use the 2.0 implementation if possible.
I compile SomeProject using its reference to log4net. The DLL that ends up in the bin directory is the one that SomeProject references. At runtime, when code from SomeLibrary runs, it attempts to execute the code from version 2.0 of SomeThirdParty, and of course fails, throwing a FileLoadException: Could not load file or assembly 'SomeThirdParty, Version=2.0.0.0, Culture=[etc.]' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference.
Obviously I could upgrade SomeProject to the newer DLL or downgrade SomeLibrary to the older DLL, but it wouldn't be ideal for many reasons.
I think the right answer involves installing SomeThirdParty in the GAC, but I'm not sure exactly how I'd go about doing this, and how it would affect other developers and servers.
Any suggestions you may have are appreciated.
Thanks for the help.

Putting both versions of SomeThirdParty into GAC should do what you want. Use gacutil utility or Start->Run->assembly then drag-n-drop.

From my answer earlier: https://stackoverflow.com/a/19576769/2367343
I ran into this yesterday for visual studio web developer using Oracle.DataAccess.dll.
My solution,
right click your project (*.csproj) and edit it.
Right underneath:
<PropertyGroup>
Place
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
Then rebuild your solution. You must separate the two version dlls into two different directories in your project when including them (required).
I did
ora11 >> Oracle.DataAccess.dll (Version 11)
ora9 >> Oracle.DataAccess.dll (Version 9)
Doing this allows your IDE to use both versions of DLLs.

Related

Select right DLL referenced version at runtime

I'm working on a mod for Mount and Blade 2 and having an issue with how it's dealing with modification.
Mods are used like plug-in and they are composed of one or a few DLLs, that can reference other DLLs.
The issue is that i reference a library NHloader version 1.0.1 in my own DLL and when testing on my own everything is perfect.
When i load with other mods it becomes a bit more messy as sometime NHloader is used by another mod and the version referenced is the 1.0.0, that lacks some of the methods i use.
So right now it's a bit random, as the first mod to load also load it's version of NHloader with no way to specify that i only want the latest version loaded. Is there a way to force this behavior? Or at least ensure that my DLL will only use the correct version or later?
Thank you for reading.

OCR Reader WS Upgrade from .Net Framework 2.0 to 4.0

I have been tasked with converting an old .Net 2.0 application to 4.0 and am running into a build error related to a missing dependency.
The build error is as follows:
Error 1 Could not load file or assembly 'Atalasoft.dotImage.Ocr.GlyphReader.DLL' or one of its dependencies. The specified module could not be found.
I was thinking that I needed to find a newer version of this DLL but I wanted to see if anyone knew an easier method for resolving this first.
Any help would be great!
A .NET 4.0 or later assembly can reference and use an assembly built on the .NET 2.0 framework. The problem is that the compiler cannot find the assembly, not that the assembly is the wrong version. Try the following steps, this should clear up your problem:
Highlight the reference in the project and go the the properties tab (F4 shortcut). Check the path that is used to reference the assembly and verify that it is actually located there.
Check if the project requires a specific version of the assembly. Go to the same properties page like mentioned in step 1 and see if specific version is set to true, change it to false if this is not a requirement for you.
If you are using NuGet ensure that the latest assemblies have been downloaded if you are not persisting your references to the source repository. You check this by going to the nuget project references and in the top right corner there will be a message asking you if you want to restore all package references if they cannot be found.
If you are not using nuget for this and it still does not work then remove the reference and manually re-add it to the project.

Use different versions of dll file in one app

I have an c# application with two libraries ( moon-apns, tweetsharp ) .. Each library has a reference for newtonsoft.json.dll but different versions ... My app build successfully but one library works fine and the other one throws an exception ( can't find the dll file ).
I think that when i build only one version goes to the bin folder, but i don't know what to do.
Thanks in advance.
You can force both libraries to reference the same version by using Assembly Binding Redirects in your app.config or web.config. Obviously this only works as long as the library versions are compatible.
Since you stated you have access to the source of the two libraries:
In both projects, set the reference to newtonsoft to not required Specific Version. Rebuild those projects.
Now, when you build your main project, the two libraries should be ok with the same version of the newtonsoft DLL as long as there is no compatibility issues

Could not load file or assembly in NHibernate

I recently had some problems with the hibernate.cfg.xml file as I hadn't had the following line in.
<property name='proxyfactory.factory_class'>NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>
Now that this is fixed I get the following error.
Could not load file or assembly 'NHibernate, Version=2.1.0.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
Why do I get this error and how do I fix it?
These files should be in the same directory as the referenced file, NHibernate.dll:
Antlr3.Runtime.dll
Iesi.Collections.dll
log4net.dll
Castle.Core.dll
Castle.DynamicProxy2.dll
Also you should add a reference or copy this one too:
NHibernate.ByteCode.Castle.dll
As a future reference:
If your're experiencing the same issues Randy Klingelheber pointed out (dependency problems between NHibernate and FluentNHibernate, or any other dependent library), you can specify a redirection for the assemblies that target the old version in app.config. This prevents one from having to recompile the dependent assembly.
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="NHibernate" publicKeyToken="aa95f207798dfdb4" />
<bindingRedirect oldVersion="3.0.0.3001" newVersion="3.0.0.4000" />
</dependentAssembly>
</assemblyBinding>
</runtime>
This code redirects requests for the old version (3.0.0.3001 in my case) to the one actually used (3.0.0.4000). The publicKeyToken is included in the error message.
I'm assuming you recently upgraded NHibernate to 2.1?
If so, my guess is you have different projects referencing different versions of NHibernate.
This happened to me and is harder to track down than you might think.
These are the steps I took to solve it:
Delete all files in all bin directories in your projects. Usually Clean Solution works well for this, but it doesn't, you may have to do it with a command line call or by hand
Edit all your .csproj files. Edit them either with a text editor or do the Unload Project then edit your .csproj file.
Make sure ALL your HintPath nodes point to the same (new) version of the DLL
That will hopefully clear up this issue for you.
I had this problem as well.
For me, the issue was that FluentNHibernate expected a different version of NHibernate (2.1.0.4000) than I was including in the project (2.1.2.4000). I stumbled on this by separately downloading the latest releases of each library.
To fix the issue, I changed my NHibernate reference to point to the older version of NHibernate that came with FluenNHibernate 1.0 RTM (2.1.0.4000).
Another solution may be to explicitly set your assembly bindings from the app.config file.
In my case, "Clean Solution", followed by "Rebuild Solution" solved the problem.
I recently upgraded our project with the 1.0 RTM version of FluentNHibernate, which required the latest NHibernate bits. This led to the same problem you are having.
Our project's structure was something like this:
Repository root
Solution
Web
References
DataAccess
... other projects/layers ...
DataAccess
References
..\ReferenceAssemblies\NHibernate.dll
..\ReferenceAssemblies\FluentNHibernate.dll
ReferenceAssemblies
(All external DLL's reside in the ReferenceAssemblies directory.)
My first attempt to solve the problem was by adding a reference to NHibernate.ByteCode.Castle.dll to the DataAccess project. This worked... but only in development...
When I published the web application to our customer acceptance test server (which happens automatically with the help of TeamCity and a script containing a call to aspnet_compiler.exe), the NHibernate.ByteCode.Castle.dll was nowhere to be found.
I am not sure why this is happening, but I suspect that it has something to do with the fact that no code whatsoever in our application actually calls code in that specific dll. Also, there's (correct me if I'm wrong) no hardcoded reference from NHibernate.dll to NHibernate.ByteCode.Castle, so somewhere down the line the (presumably unused) dll is overlooked.
The second (and successful) attempt was to add a reference to the missing dll directly to the web project. Now, I could remove the reference I added in the first attempt without any problems.
(I'm not particularly fond of having such a reference in that particular project, but hey!) :-)
You probably have code referencing two different versions of the NHibernate DLL. The NHibernate.dll that you download with NHibernate is likely a different version from the one you download with, say, Castle ActiveRecord. Try to stick with just the version of the NHibernate DLL that came with NHibernate.ByteCode.Castle. And make sure you don't have the NHibernate DLL (any version) in your GAC (at least until you get this problem resolved).
I had this problem after upgrading NHibernate to 3.0 and Spring to nightly build which used NH 3.0. The problem was that Spring.Data.NHibernate30.dll referenced older version of NHibernate.dll (v 3.0.0.2002) and I had v 3.0.0.4000.
My solution was to open project Spring.Data.NHibernate30 source, remove references to older version of NHibernate, add reference to version 3.0.0.4000, rebuild and now in my project add reference to this (newly built) version of Spring.Data.NHibernate30.dll.
I just had this happen to me -- in my case this was my first time trying out NHibernate (and Fluent NHibernate). I had implemented most of my application in a .dll assembly, referenced by a separate executable assembly. The executable, which didn't have references to NHibernate directly, was giving me the error.
I'm using NuGet to pull down Fluent NHibernate, so I added the Fluent NHibernate reference to the executable assemblies as well. Doesn't feel super clean, but it gets the dependencies into the .bin folder and resolves the error. (funny that it doesn't (seem to?) happen with other libraries, like NLog)
I was facing the same issue. I cleared ''Temporary Internet Files'', and this issue went away.
You should reference the dependent assemblies (I guess it's "NHibernate.ByteCode.Castle") and set their "copy local" attribute to true.
NHibernate has a few other assemblies other than nhibernate.dll. Did you have all of them in (from the same release)?
You might have different projects in your solution. Those project might be referencing different versions of NHibernate.dll. Checks versions in all projects and rebuild the project
It looks like the NHibernate dll isn't being copied to the bin directory of your application. Make sure it's referenced and exists in the bin directory.

Assembly names and versions

What is considered as best practice when it comes to assemblies and releases?
I would like to be able to reference multiple versions of the same library - solution contains multiple projects that depend on different versions of a commonutils.dll library we build ourselves.
As all dependencies are copied to the bin/debug or bin/release, only a single copy of commonutils.dll can exist there despite each of the DLL files having different assembly version numbers.
Should I include version numbers in the assembly name to be able to reference multiple versions of a library or is there another way?
Assemblies can coexist in the GAC (Global Assembly Cache) even if they have the same name given that the version is different. This is how .NET Framework shipped assemblies work. A requirement that must be meet in order for an assembly to be able to be GAC registered is to be signed.
Adding version numbers to the name of the Assembly just defeats the whole purpose of the assembly ecosystem and is cumbersome IMHO. To know which version of a given assembly I have just open the Properties window and check the version.
Here's what I've been living by --
It depends on what you are planning to use the DLL files for. I categorize them in two main groups:
Dead-end Assemblies. These are EXE files and DLL files you really aren't planning on referencing from anywhere. Just weakly name these and make sure you have the version numbers you release tagged in source-control, so you can rollback whenever.
Referenced Assemblies. Strong name these so you can have multiple versions of it being referenced by other assemblies. Use the full name to reference them (Assembly.Load). Keep a copy of the latest-and-greatest version of it in a place where other code can reference it.
Next, you have a choice of whether to copy local or not your references. Basically, the tradeoff boils down to -- do you want to take in patches/upgrades from your references? There can be positive value in that from getting new functionality, but on the other hand, there could be breaking changes. The decision here, I believe, should be made on a case-by-case basis.
While developing in Visual Studio, by default you will take the latest version to compile with, but once compiled the referencing assembly will require the specific version it was compiled with.
Your last decision is to Copy Local or not. Basically, if you already have a mechanism in place to deploy the referenced assembly, set this to false.
If you are planning a big release management system, you'll probably have to put a lot more thought and care into this. For me (small shop -- two people), this works fine. We know what's going on, and don't feel restrained from having to do things in a way that doesn't make sense.
Once you reach runtime, you Assembly.Load whatever you want into the application domain. Then, you can use Assembly.GetType to reach the type you want. If you have a type that is present in multiple loaded assemblies (such as in multiple versions of the same project), you may get an AmbiguousMatchException exception. In order to resolve that, you will need to get the type out of an instance of an assembly variable, not the static Assembly.GetType method.
Giving different names to different assembly versions is the easiest way and surely works.
If your assembly (commonutils.dll) is strong-named (i.e. signed), you can think about installing it in the GAC (Global Assembly Cache - you can install different versions of the same assembly side-by-side in the GAC), therefore the calling application automatically gets the proper version from there because .NET Types include assembly version information.
In your VS project you reference the correct version of the library, but you don't deploy it in the application folder; you install it in the GAC instead (during application setup).

Categories