4

I'm new to using GAC and I am trying to get a handle on when you should and shouldn't use it. Here is my situation:

I develop software that is primarily add-ins to another commercial product so that product loads my products into it's code. There are several assemblies that I have developed that are used by all of my applications (my license module for example). The .dll file for these libraries get installed to the main application directory so the parent program loads them from there.

The problem is when a user has two of my software titles installed, there can be a conflict since the parent program only loads the first copy of an assembly it finds regardless of version. So if they have Software A version 1.0 with License1.0.dll in it and Software B version 2.5 with License 2.0 in it that has different methods and/or arguments than License1.0.dll it only loads 1.0 and then throws an exception on Software B because it can't find the right license methods.

In initial research it seemed like GAC was intended to be the answer to this and several sites seem to say it is, but then I also found this subject and the link in the answer that seems to be saying no don't use GAC for this.

I'm confused. Can someone give some direct guidance on if I should look into using GAC for this?

Community
  • 1
  • 1
sfaust
  • 2,089
  • 28
  • 54
  • 1
    I think you'll run into more issues using GAC. Sounds like the consuming application should be configured to point to the correct version DLLs either through assembly redirects in the config file or by setting the specific path on the reference at compile time. I am not sure and quite interested seeing what the answers are. – TyCobb Nov 03 '14 at 23:43
  • Unfortunately I have no control over the parent application but from what I understand that is standard behavior for a single application loading .NET assemblies. I.E. if I had 3 separate applications running it would load into separate domains and wouldn't have a problem, but since my 3 apps are loading underneath a single application (and it's domain) it only loads one copy of it. Again I am fairly new at this so I may be wrong but that's my understanding... – sfaust Nov 03 '14 at 23:57
  • Well, it isn't up to you to make this change, given that the host appears to be in charge of deployment. Sensitive issue, pretty doubtful anybody is going to lift a finger to make it easy for you to enforce a license. All you can do is make it easy for them to fall back to the GAC to solve this issue. That's very simple, just ensure it is strong-named. You probably ought to consider writing an installer. – Hans Passant Nov 04 '14 at 00:11
  • I have installers and I can place the assemblies into GAC easy enough. I control my installers and my installers just have to write a registration file to a specific location to register with the parent program, the rest of my program can be placed wherever I want. The question is if I SHOULD place my assemblies in GAC (or some of them at least)... – sfaust Nov 04 '14 at 14:50
  • Well, if you have a choice between A: use the GAC, B: do not use the GAC and you find out that B doesn't work then there's no question. Nobody can help you with B with the info you provided. Use A. – Hans Passant Nov 05 '14 at 11:24

1 Answers1

1

I wouldn't recommend use the GAC at all as you depend on registered dlls and I often had problems with that. Anyway, you can load the assembly that you like manually. I have a parent application that is either 64 bit or 32 bit and I have to load the corresponding SQLite x64 or x86 dll. The referenced assembly has copy local false. That's the first place where the runtime will look to resolve the reference. If there is anything then it checks the GAC. The dll isn't registered there so the AssemblyResolve event will happen where I can say what I want to load:

AppDomain.CurrentDomain.AssemblyResolve += ResoveAssembly;


private static Assembly ResoveAssembly(object sender, ResolveEventArgs e)
{
   string fullPath = Assembly.GetExecutingAssembly().Location;
   string path = Path.GetDirectoryName(fullPath);

   if (e.Name.StartsWith("System.Data.SQLite"))
   {
      return Assembly.LoadFrom(Path.Combine(path, Environment.Is64BitProcess
                                                  ? "x64\\System.Data.SQLite.DLL"
                                                  : "x86\\System.Data.SQLite.DLL"));}
       return null;
   }
}

In case someone wonders why I'm doing that: As far as I know the new SQLite NuGet package handles this issue now. But it wasn't available when we want to use it.

KCT
  • 287
  • 1
  • 10
  • I've used assembly resolve in certain cases. However in this case I need one program to load version 1.0 of the dll file and the other to load version 2.0, and they are both running under the parent application (same domain). Is this possible? – sfaust Nov 06 '14 at 17:17
  • I've never tried it with assembly resolve. I know I had a problem when the parent app was using a different version. I'm not quite sure but did you try if it works with assmbly binding like [here](http://stackoverflow.com/questions/2460542/using-different-versions-of-the-same-assembly-in-the-same-folder)? – KCT Nov 11 '14 at 07:58
  • Interesting, but where do you put the configuration? Since I don't control the parent application I don't have access to its config, just to my dll files... – sfaust Nov 11 '14 at 16:47
  • p.s. I upvoted this answer because I think it's helpful but I'm not sure it's the final answer to this question... If no one else chimes in with a better answer in the next few days I'll go ahead and mark it... – sfaust Nov 11 '14 at 16:49