Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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;
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top