3

When dealing with plugin assemblies in their own subdirectories, there is the well-known problem that these assemblies fail to load once they try to load their respective dependencies from their subdirectories. A solution is to load the plugins in AppDomains which had their PrivateBinPath set in their AppDomainSetup object upon initialization. However, this causes other difficulties concerning marshalling/cross-AppDomain communication, in particular if the plugins are supposed to provide some GUI.

When security aspects have a lower priority (non-critical utility application, no severe problems upon crashes caused by faulty plugins), I've had the following idea: Upon application start-up, all plugin directories should be searched for, and a new AppDomain should be created that has those directories in its bin path. Then, the whole application and its GUI run in that new AppDomain, along with all plugins.

Under the given circumstances, are there any reasons to avoid that solution? Or are there maybe any reasons why that solution isn't even feasible?

O. R. Mapper
  • 20,083
  • 9
  • 69
  • 114
  • I think that if your main UI is running in the same AppDomain as the plugin, the main UI will likely crash if the plugin crashes. Are you using the addin framework or is it "RYO"? – IAbstract Aug 05 '12 at 13:31
  • @IAbstract: Even when running in another AppDomain, don't crashes of the plugin usually make the main UI crash, too? After all, any exceptions thrown in the plugin are marshalled across AppDomain boundaries and make the main application exit unless I handle the exceptions. In my particular case, this is RYO - I've looked into the Addin Framework and read many articles about it, but they all referred to rather minimalist interfaces between core app and plugins rather than the complex and deeply-nested object hierarchies I'll need to transfer. – O. R. Mapper Aug 05 '12 at 13:46

1 Answers1

1

Taking in consideration your described scenario I don't know of any issue associated with your proposal for a second domain. However, you may also investigate the possibility of handling the assembly loading failures on the initial domain by searching yourself through the addins sub-directories and loading the assembly from there using Assembly.LoadFrom.

Example of a possible setup for this, where the FindAssemblyByName would have to be implemented to search through all the possible locations:

static void Main(string[] args)
{
    AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;

    // ...
}

static Assembly CurrentDomain_AssemblyResolve(
    object sender, 
    ResolveEventArgs e)
{
    var assemblyName = new AssemblyName(e.Name);

    string assemblyFilePath = FindAssemblyByName(assemblyName);

    if (string.IsNullOrEmpty(assemblyFilePath))
        return null;

    return Assembly.LoadFrom(assemblyFilePath);
}
João Angelo
  • 56,552
  • 12
  • 145
  • 147
  • Will this work only for managed assemblies? More specifically, when I've manually found a plugin assembly in a subdirectory, will unmanaged libraries in the same subdirectory be discovered automatically? – O. R. Mapper Aug 15 '12 at 11:57
  • The `Assembly.LoadFrom` allows further dependencies on that path to be found and loaded because the path information is maintained by the context. However, with unmanaged assemblies in the mix I'm not comfortable to give you any certainties. – João Angelo Aug 15 '12 at 12:21
  • I've read up further on this and done some tests. It seems indeed as if not only managed, but also unmanaged libraries will be found if they are in the same directory as the assembly loaded with `LoadFrom`. However, reading in the [docs](http://msdn.microsoft.com/en-us/library/1009fa28.aspx), it seems that `LoadFrom` exclusively loads assemblies into the so-called *load-from* context, whereas the *load* context would be preferrable for various reasons. On the other hand, I don't see any way to load an assembly into that *load* context from a custom location. – O. R. Mapper Aug 28 '12 at 19:23