0

I have several applications which are required to use the same assembly. This assembly may be changed regularly, and can be installed by different MSIs. For this reason, I do not want to put it in the GAC, it can become a deployment nightmare over time.

If I turn the CopyLocal attribute for this assembly to NO in the application, how do I tell the runtime where to look for the assembly?

E.g. the application is loaded in C:/Program Files/<some directory>/bin The DLL is in C:/<some other directory>

Is it thus possible to load the assembly in this way?

I've had a look at <codebase>, but I'm not sure the assembly can be strongly signed. And probing seems to work only for the private paths specified as subdirectories of the application?

Please let me know. Thank you.

rkhb
  • 14,159
  • 7
  • 32
  • 60
user1173240
  • 1,455
  • 2
  • 23
  • 50
  • Have you tried the `AppDomain.CurrentDomain.AssemblyResolve` event? – Matt Jacobi Nov 04 '14 at 03:48
  • Why does every application need to use the same copy of the dll? What is problem with each application using its own copy? – Mike Zboray Nov 04 '14 at 04:03
  • Avoid duplication, and have one place where it is ensured that the correct version of the assembly resides. – user1173240 Nov 04 '14 at 04:11
  • 1
    @user1173240: that's a wonderful ideal, especially with .NET where shared DLLs in the GAC can be loaded once for multiple processes. But unfortunately, DLL authors are not careful enough for this to be safe enough for many scenarios. When multiple programs share a DLL, that means multiple programs _maintain_ the installation of that DLL, and a program can wind up using a version of the DLL it hasn't been tested with, and with which it won't work. Disk space is cheap these days, and DLLs are small (especially in .NET). A private copy of a DLL is cheap insurance. :) – Peter Duniho Nov 04 '14 at 04:34
  • 2
    Honestly, I've deployed apps both ways and including all needed assemblies in each application is the way to go. "Avoiding duplication" is not a significant benefit. Disk is cheap. "Have one place where ... the assembly resides" is not a significant benefit either. This means there is one version that is shared by all applications. You've exposed your users to the possibility that when they upgrade app 1, app 2 will break. To avoid this, additional ongoing testing is needed for each new version *for each application*. It is just not worth it when the problem can easily be avoided. – Mike Zboray Nov 04 '14 at 04:35
  • All applications depending on this assembly are built together. Keeping this in mind, I want to avoid an application, in a different path, from having its own copy, and use the one commonly kept for all applications. – user1173240 Nov 04 '14 at 05:25
  • OK. Never mind. After evaluating pros and cons, I feel that having it in the GAC ( and local folder ) is probably a better way to go about this. I shall still mark the answer given below, as that is the answer to the question I had asked originally. – user1173240 Nov 06 '14 at 04:53

2 Answers2

2

Use Assembly.LoadFrom to load the assembly into memory, then you can use Activator.CreateInstance to create an instance of your preferred type. You need to user reflection for this:

Assembly assembly = Assembly.LoadFrom("c:\\path\\MyDll.dll");

Type type = assembly.GetType("MyClass");

object instanceOfMyType = Activator.CreateInstance(type);

Take a look on reflection in order to create instances with parameters.

Bakudan
  • 19,134
  • 9
  • 53
  • 73
rodrigogq
  • 1,943
  • 1
  • 16
  • 25
2

Why do you want to set CopyLocal to "No"? The usual way to avoid "DLL hell" (aka "deployment nightmare") is to ensure that DLL dependencies are copied into the same directory with your program. IMHO, this is the simplest, most straightforward way to guarantee you are loading the DLL you want.

Note also that if you sign the DLL, install it in the GAC, and then in your own program require a specific version (or a minimum version, depending on your needs), that should also address the "DLL hell" scenarios. I.e. the presence of other versions of the DLL won't conflict, because you've required a specific version and .NET can reliably distinguish the correct version from an incorrect one.

Barring those approaches...

It's not clear what your exact requirements are. However, if you are trying to provide a way to identify an assembly that's not in the usual assembly-loading paths, there are at least a couple of mechanisms you can use.

One way is to use ApplicationBase and PrivateBinPath to control how .NET searches for your assemblies.

Another way is to handle the System.AppDomain.AssemblyResolve event.

That event will be raised any time .NET tries to load a referenced assembly and can't find it. Your handler can then perform whatever search it needs to (or just use a fixed path for that matter), load the assembly itself (e.g. using Assembly.LoadFrom()), and then return that via the event's arguments object.

Note that the AssemblyResolve event is only raised if .NET can't find a DLL to load. So that would not be an appropriate solution if it's not tolerable to have a different instance of the DLL that satisfies the reference requirements for the program of that DLL.

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
  • The assembly might be changed frequently, depending on bug fixes. Also, it's possible another application which uses the assembly may not be updated alongwith the package which installs the updated assembly. if, the previous uninstallaion had failed to remove the old one from the GAC, and the new one installed a different version of the assembly, then I'll have a situation where one is accessing an old version, and another is accessing the new. There can be several such scenarios. And this is the reason why I'm not so much in favour of the GAC. – user1173240 Nov 04 '14 at 04:29
  • The GAC can handle different versions of an assembly. In any case, none of that makes clear why simply copying the DLL you depend on into the same directory with the program EXE isn't a useful or desirable solution for your scenario. – Peter Duniho Nov 04 '14 at 04:31