Select right DLL referenced version at runtime - c#

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.

Related

DLL not being updated when building my solution

Strange situation.
inside a solution I have several projects. One of them is called Common, other is a web project (not a web application) called Internal.
Internal has a reference to Common, so every time I build the application, the common DLL is copied to the bin folder on the Internal website.
If I change a line of code on a class on the Common project and rebuilt it the DLL isn't updated on the Internal bin folder (even If I rebuild the internal) resulting in running the OLD code of the Common (If I have a breakpoint on Common, it show a warning saying that the code differs from the original and wont run). The only way I manage to solve it is manually deleting the Common DLL on Internal and then rebuilding.
My question is, how can I avoid it? How can the dll always be the same version on Internal?
Thanks
As requested by OP:
Try removing the reference and adding again though the 'Projects' option on the 'Add Reference' dialog. This should set up the DLL to be refreshed when it is rebuilt.
One of possible straightforward solutions could be the simple use of PostBuildEvent where you put batch-code that on successful build always copies files you need.
The bad about this that you increase your compilation time.
If you are using third party dll which has been developed been higher version VS2013/vs2015 (i.e .NEt 4.5 , 4.6 , 4.6.2) then it will not work properly in VS2010
Answer: Convert your project to VS2015 to resolve issue or install .NET 4.6.2 and user VS2013 and change framework to latest

DLL Not found: referencing dependent DLLs

I'm attempting to implement a C++ DLL (of my own creation) that uses the Intel Performance Primitives in a C# forms application. I'm getting a "DLL Not Found Exception" when I attempt to run the program. One possible reason put forward in other posts on this site is that there are dependent DLLs that must be referenced and in fact after downloading DpendencyWalker I found that my DLL uses "IPPS-7.0.DLL".
My problem is that it is unclear to me how to reference these dependent DLLs. I've added the IPPS-7.0.DLL containing folder to referenced paths as well as added references to the "IntelCppOptPkg" and "IntelLibOptPgk" assemblies but this has not solved the problem.
So, am I correct in believing this is the problem? And if so, how does one reference a depedent DLL in managed code?
Thank you.
You don't reference them, they are not .NET assemblies. You just need to make sure that the DLL(s) get copied to your build directory. Easiest way to do that is with Project + Add Existing Item, select the DLL from wherever it was copied. Then select the added file and in the Properties window set Build Action = Content, Copy to Output Directory = Copy if newer. Checking-in the DLL(s) in source control is generally a good idea btw.
Managed code can not reference unmanaged dll the same way it references managed assemblies. Managed references actually change the meta data of your assembly:
The compiler records static
references in the assembly manifest's metadata at build time.
...
The preferred way to reference an assembly is to use a full reference,
including the assembly name, version, culture, and public key token
(if one exists).
Native dlls simply don't have this .NET meta data associated with them. They have to be copied manually in the Post Build step or during deployment. There is a workaround but I don't think it will work if your managed app is platform independent (Any CPU) and you have x86 and x64 versions of unmanaged dlls.

Conditional AssemblyName causes C# project to always rebuild when using names other than "Debug"/"Release"

So I'm adding a "d" extension to my assembly name when building in debug mode. As far as I can tell the standard way to do this in C# is to edit the .csproj file and put in the following:
<PropertyGroup>
<AssemblyName Condition="'$(Configuration)' == 'V90 Debug'">$(AssemblyName)d</AssemblyName>
</PropertyGroup>
That has the desired effect, but now the darn project always rebuilds the output .dll, causing other projects that depend on it to relink, etc.. Without this change, I don't have any such problem.
So far increasing the verbosity of the project output hasn't helped.
Edit: An additional, important detail is that we're using names like "V90 Release", "V90 Debug", "V100 Release" etc.. for our configurations, so that we can target different versions of the Visual Studio runtime. I wrote a test app with the standard configuration names and found my problem doesn't happen in that case.
You are using an old standard in C/C++ development. The Big Difference with managed code is the absence of a linker. You used to configure the linker to use the "d" version of the library in the Debug build, the non-d version of the library in the Release build. That mechanism is completely absent in .NET, code in libraries are dynamically linked at runtime. Making the practically of having different names for different builds dramatically less.
One of the problems you'll encounter if you pursue this old strategy is that you'll have additional problems with the reference assemblies of a project. There is no decent way to use different names in different configurations. Dependent assemblies are listed in the Reference node of the project, this is a property of a project that is not configuration dependent. It is not impossible, you'll need a lot more Condition hacks to rename the reference assemblies. Build dependency checking is likely to be affected by this as well.
This is not actually necessary, the debug and release build of the assemblies will have the same metadata. But if you skip that, you'll now have a problem at runtime. The CLR will be told to use the wrong assembly name. Hacking around that is technically possible by hiding the assemblies in a sub-directory and using the AppDomain.AssemblyResolve event to load the correct one. You'll need a post-build event to rename and copy the assembly into this directory. This all gets ugly in a hurry when those assemblies have dependencies on other assemblies.
Long story short, your previous standard just isn't a good one for managed code.

Use different versions of referenced DLL

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.

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