3

My directory structure looks like this:

-- Host Program Base
  |- HostProgram.exe
  |- SharedLIB.dll
  |-- LoadedLibs
     |- HostedLib.dll

HostProgram.exe is attempting to load HostedLib.dll, which depends on SharedLib.dll.

Thus, SharedLib.dll's ApplicationBase for the AppDomain I am creating to load it is /Host Program Base/HostedLibs/, but it needs to be able to find SharedLib.dll.

I have tried to add .. to the PrivateBinPath for the AppDomain but according to MSDN,

Private assemblies are deployed in the same directory structure as the application. If the directories specified for PrivateBinPath are not under ApplicationBase, they are ignored.

As the PrivateBinPath is not inside the ApplicationBase, but rather is one directory up, it is not inside ApplicationBase and is being ignored. Therefore I get a AssemblyResolveException when attempting to load the DLL into the new AppDomain.

I have also attempted to set the ApplicationBase to the Host Program Base folder and add HostedLibs as a PrivateBinPath, but this causes the domain to be unable to resolve HostedLib.dll at all.

So -> how do I resolve libraries outside ApplicationBase using an AppDomainSetup?

Christian Stewart
  • 15,217
  • 20
  • 82
  • 139
  • I don't get the problem. Keep the ApplicationBase at the EXE directory, make the PrivateBinPath the subdirectory. – Hans Passant Jul 03 '13 at 00:28
  • The DLL file that has the dependency is in the subfolder "HostedLibs". Thus, the ApplicationBase MUST be "HostedLibs". @HansPassant – Christian Stewart Jul 03 '13 at 01:04
  • 1
    That's the point, I have no idea why you think that's necessary. Have you at least tried it? – Hans Passant Jul 03 '13 at 11:07
  • @HansPassant Yes I have tried it. I get an unresolved error for the HostedLib.dll when attempting to load it while the ApplicationBase is set one directory up and PrivateBinPath is set to "LoadedLibs" – Christian Stewart Jul 03 '13 at 17:09
  • This is an XY question. Y won't work, we have no idea what might cause X. Re-ask the question and document X properly. Post a code snippet and the failed bind log you get from Fuslogvw.exe – Hans Passant Jul 03 '13 at 17:29
  • @HansPassant I have no idea what a bind log is but I will look it up. I think it's clear why it cannot resolve the assembly: it is not within `ApplicationBase`. – Christian Stewart Jul 03 '13 at 17:34

2 Answers2

1

Short of reorganizing your application structure, you could use the AppDomain.AssemblyResolve event.

Basically works like this.

  1. Subscribe to the AssemblyResolve event on the AppDomain.
  2. When the event fires, you can specifically look for your SharedLib.dll or simply attempt to create a full path to the desired assembly in your root folder given the assembly name specified in the ResolveEventArgs.Name and use Assembly.LoadFrom(path).
  3. If the assembly successfully loaded from the path, return it in the AssemblyResolve handler, otherwise return null.
Jim
  • 4,910
  • 4
  • 32
  • 50
0

Implemented solution based on Jim's answer:

internal static class Program
{
    static Program()
    {
        AppDomain.CurrentDomain.AssemblyResolve += CurrentDomainOnAssemblyResolve;
    }

    private static void Main()
    {
        //Do your stuff
    }

    private static Assembly CurrentDomainOnAssemblyResolve(object sender, ResolveEventArgs args)
    {
        try
        {
            AssemblyName name = new AssemblyName(args.Name);

            string expectedFileName = name.Name + ".dll";
            string rootDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

            return LoadAssembly(rootDir, expectedFileName, "", "Dlls", "../Dlls");
        }
        catch
        {
            return null;
        }
    }

    private static Assembly LoadAssembly(string rootDir, string fileName, params string[] directories)
    {
        foreach (string directory in directories)
        {
            string path = Path.Combine(rootDir, directory, fileName);
            if (File.Exists(path))
                return Assembly.LoadFrom(path);
        }
        return null;
    }
}
Manfred Radlwimmer
  • 13,257
  • 13
  • 53
  • 62