4

I've searched the hell out of this, but I can't quite find out why I'm getting a FileNotFoundException when the file clearly exists and can be opened with File.ReadAllBytes

This is my current code:

AppDomainSetup domainInfo = new AppDomainSetup();
domainInfo.ApplicationBase = PluginDirectory;
Evidence adEvidence = AppDomain.CurrentDomain.Evidence;
AppDomain pluginDomain = AppDomain.CreateDomain("pluginDomain", adEvidence, domainInfo);

foreach (FileInfo file in files)
{
    if (m_AssemblyIgnoreList.Contains(file.Name))
        continue;

    byte[] assemblyBytes = File.ReadAllBytes(file.FullName);
    //Assembly plugin = Assembly.LoadFrom(file.FullName);

    Assembly plugin = pluginDomain.Load(assemblyBytes);

    LoadPlayerEvents(plugin);
}

AppDomain.Unload(pluginDomain);

I'm attempting to load in all .dll files from within a plugin folder, and load a bunch of attributed types and functions.

The loading of the attributed types and functions works file when I use Assembly.LoadFrom(file.FullName). However, pluginDomain.Load(assemblyBytes) causes the following exception:

FileNotFoundException: Could not load file or assembly 'Example Mod, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

Its definitely finding the file specified, since File.ReadAllBytes works perfectly, as the exception displays the full name of the assembly I'm trying to load. Thus I come to the conclusion that it cannot load a dependency.

All of the dependencies are already loaded in the CurrentDomain. Though, even when I place those dependencies right next to the .dll (this occurs during the build of said .dll anyways), the same exception is produced.

Why am I getting this exception, when the file clearly exists?

rkhb
  • 14,159
  • 7
  • 32
  • 60
Ashley
  • 121
  • 3
  • 14
  • You could run [Process Monitor](https://technet.microsoft.com/en-us/sysinternals/bb896645.aspx) to check at which locations your application searches for the dll and maybe you get an idea why it doesn't search at your desired location. – Oliver Oct 05 '15 at 06:48

1 Answers1

1

You should load the assemblies in the AssemblyResolve event handler of your current domain, like explained here

h3rb4l
  • 73
  • 6
  • I'm trying to NOT use Assembly.Load as it keeps the dll file in use until the appdomain is unloaded. I want to beable to unload the appdomain immediately after all of my plugins have been loaded and the MethodInfo variables for each method I need have been stored in a list. That way I can call those methods afterwards. – Ashley Oct 06 '15 at 06:37
  • Yes, but the dlls will be loaded to the newly created domain, so once it gets unloaded, the dlls will be released. Maybe I have wrote it wrong: by "current" domain, I meant the one you have just created. Notice, both AppDomain.Load and the event handler are static, thus called but the newly created domain. Solution from the example should work for your purpose. Tell me if you need a code sample for it. – h3rb4l Oct 06 '15 at 08:31
  • I have just noticed, you wrote you want to call the methods afterwards.. It is not possible since the domain they were loaded into, got unloaded. You will need to load the dlls into some domain, to be able to use them. You can do this dynamically, by creating a separate domain and loading the necessary dll to it on demand, but I am afraid this would not be to efficient. What exactly you are trying to accomplish here? In addition, referencing both domains, by storing MethodInfo variables in the base one, will probably block unloading. You need to find a different solution for it. – h3rb4l Oct 06 '15 at 08:40