AppDomain dependencies across directories
I am creating a plugin system and I am creating one AppDomain per plugin. Each plugin has its own directory with its main assemblies and references. The main assemblies will be loaded by my plugin loader, in addition to my interface assemblies (so the plugin can interact with the application).
Creating the AppDomain:
this.appDomain = AppDomain.CreateDomain("AppDomain", null, new AppDomainSetup {
ApplicationBase = pluginPath,
PrivateBinPath = pluginPath,
});
Loading the assemblies:
this.appDomain.Load(myInterfaceAssembly.GetName(true));
var assemblies = new List<Assembly>();
foreach (var assemblyName in this.assemblyNames) {
assemblies.Add(this.appDomain.Load(assemblyName));
}
The format of assemblyName
is the assembly's filename without ".dll".
The problem is that AppDomain.Load(assemblyName)
throws an exception:
Could not load file or assembly '[[assemblyName]], Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
All of the dependencies of [[assemblyName]]
are:
- Inside the directory
pluginPath
, - The
myInterfaceAssembly
which is already loaded, or - In the GAC (e.g. mscorelib).
Clearly I'm not doing something right. I have tried:
- Creating an object using
this.appDomain.CreateInstanceAndUnwrap
inheriting from MarshalByRefObject with aLoadAssembly
method to load the assembly. I get an exception saying that the current assembly (containing the proxy class) could not be loaded (file not found, as above), even if I manually callthis.appDomain.Load(Assembly.GetExecutingAssembly().GetName(true))
. - Attaching an
AssemblyResolve
handler tothis.appDomain
. I'm met with the same exception as in (1), and manually loading doesn't help. - Recursively loading assemblies by loading their dependencies into
this.appDomain
first. This doesn't work, but I doubt my code is correct:
private static void LoadAssemblyInto(AssemblyName assemblyName, AppDomain appDomain) {
var assembly = Assembly.Load(assemblyName);
foreach (var referenceName in assembly.GetReferencedAssemblies()) {
if (!referenceName.FullName.StartsWith("MyProject")) {
continue;
}
var loadedAssemblies = appDomain.GetAssemblies();
if (loadedAssemblies.Any((asm) => asm.FullName == referenceName.FullName)) {
continue;
}
LoadAssemblyInto(referenceName, appDomain);
}
appDomain.Load(assembly.GetName(true));
}
How can I load my plugin assembly with its dependencies in that plugin's directory while also loading some assemblies in the current directory?
Note: The assemblies a plugin may (probably will) reference are already loaded in the current domain. This can be shared across domains (performance benefit? simplicity?) if required.
Fusion log:
*** Assembly Binder Log Entry (12/24/2010 @ 11:03:29 AM) *** The operation was successful. Bind result: hr = 0x0. The operation completed successfully. Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll Running under executable C:\MyProject\bin\Debug\MyProject.vshost.exe --- A detailed error log follows. === Pre-bind state information === LOG: User = Null-Laptop-PC\Null-Laptop LOG: Where-ref bind. Location = C:/MyProject/bin/Debug/MyProject.Library.DLL LOG: Appbase = file:///C:/PluginDir LOG: Initial PrivatePath = C:\PluginDir LOG: Dynamic Base = NULL LOG: Cache Base = NULL LOG: AppName = MyProject.vshost.exe Calling assembly : (Unknown). === LOG: This bind starts in LoadFrom load context. WRN: Native image will not be probed in LoadFrom context. Native image will only be probed in default load context, like with Assembly.Load(). LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.exe.Config LOG: Using host configuration file: LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config. LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/MyProject.Library.DLL. LOG: Assembly download was successful. Attempting setup of file: C:\MyProject\bin\Debug\MyProject.Library.dll LOG: Entering run-from-source setup phase. LOG: Assembly Name is: MyProject.Library, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null LOG: Re-apply policy for where-ref bind. LOG: Where-ref bind Codebase does not match what is found in default context. Keep the result in LoadFrom context. LOG: Binding succeeds. Returns assembly from C:\MyProject\bin\Debug\MyProject.Library.dll. LOG: Assembly is loaded in LoadFrom load context. *** Assembly Binder Log Entry (12/24/2010 @ 11:03:29 AM) *** The operation was successful. Bind result: hr = 0x0. The operation completed successfully. Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll Running under executable C:\MyProject\bin\Debug\MyProject.vshost.exe --- A detailed error log follows. === Pre-bind state information === LOG: User = Null-Laptop-PC\Null-Laptop LOG: Where-ref bind. Location = C:\MyProject\bin\Debug\MyProject.exe LOG: Appbase = file:///C:/MyProject/bin/Debug/ LOG: Initial PrivatePath = NULL LOG: Dynamic Base = NULL LOG: Cache Base = NULL LOG: AppName = MyProject.vshost.exe Calling assembly : (Unknown). === LOG: This bind starts in LoadFrom load context. WRN: Native image will not be probed in LoadFrom context. Native image will only be probed in default load context, like with Assembly.Load(). LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.exe.Conf开发者_如何学JAVAig LOG: Using host configuration file: LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config. LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/MyProject.exe. LOG: Assembly download was successful. Attempting setup of file: C:\MyProject\bin\Debug\MyProject.exe LOG: Entering run-from-source setup phase. LOG: Assembly Name is: MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null LOG: Re-apply policy for where-ref bind. LOG: Where-ref bind Codebase matches what is found in default context. Keep the result in default context. LOG: The post-policy assembly reference requires probing again. LOG: Switch from LoadFrom context to default context. LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.exe.Config LOG: Using host configuration file: LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config. LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind). LOG: Binding succeeds. Returns assembly from C:\MyProject\bin\Debug\MyProject.exe. LOG: Assembly is loaded in default load context. LOG: Where-ref bind Codebase matches what is found in default context. Keep the result in default context. *** Assembly Binder Log Entry (12/24/2010 @ 11:03:29 AM) *** The operation was successful. Bind result: hr = 0x0. The operation completed successfully. Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll Running under executable C:\MyProject\bin\Debug\MyProject.vshost.exe --- A detailed error log follows. === Pre-bind state information === LOG: User = Null-Laptop-PC\Null-Laptop LOG: DisplayName = System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a (Fully-specified) LOG: Appbase = file:///C:/MyProject/bin/Debug/ LOG: Initial PrivatePath = NULL LOG: Dynamic Base = NULL LOG: Cache Base = NULL LOG: AppName = MyProject.vshost.exe Calling assembly : System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089. === LOG: This bind starts in default load context. LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.exe.Config LOG: Using host configuration file: LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config. LOG: Binding succeeds. Returns assembly from C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Configuration\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Configuration.dll. LOG: Assembly is loaded in default load context. *** Assembly Binder Log Entry (12/24/2010 @ 11:03:29 AM) *** The operation failed. Bind result: hr = 0x80070002. The system cannot find the file specified. Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll Running under executable C:\MyProject\bin\Debug\MyProject.vshost.exe --- A detailed error log follows. === Pre-bind state information === LOG: User = Null-Laptop-PC\Null-Laptop LOG: DisplayName = MyProject.resources, Version=1.0.0.0, Culture=en-US, PublicKeyToken=null (Fully-specified) LOG: Appbase = file:///C:/MyProject/bin/Debug/ LOG: Initial PrivatePath = NULL LOG: Dynamic Base = NULL LOG: Cache Base = NULL LOG: AppName = MyProject.vshost.exe Calling assembly : MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null. === LOG: This bind starts in default load context. LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.exe.Config LOG: Using host configuration file: LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config. LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind). LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/en-US/MyProject.resources.DLL. LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/en-US/MyProject.resources/MyProject.resources.DLL. LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/en-US/MyProject.resources.EXE. LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/en-US/MyProject.resources/MyProject.resources.EXE. LOG: All probing URLs attempted and failed. *** Assembly Binder Log Entry (12/24/2010 @ 11:03:29 AM) *** The operation failed. Bind result: hr = 0x80070002. The system cannot find the file specified. Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll Running under executable C:\MyProject\bin\Debug\MyProject.vshost.exe --- A detailed error log follows. === Pre-bind state information === LOG: User = Null-Laptop-PC\Null-Laptop LOG: DisplayName = MyProject.resources, Version=1.0.0.0, Culture=en, PublicKeyToken=null (Fully-specified) LOG: Appbase = file:///C:/MyProject/bin/Debug/ LOG: Initial PrivatePath = NULL LOG: Dynamic Base = NULL LOG: Cache Base = NULL LOG: AppName = MyProject.vshost.exe Calling assembly : MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null. === LOG: This bind starts in default load context. LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.exe.Config LOG: Using host configuration file: LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config. LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind). LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/en/MyProject.resources.DLL. LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/en/MyProject.resources/MyProject.resources.DLL. LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/en/MyProject.resources.EXE. LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/en/MyProject.resources/MyProject.resources.EXE. LOG: All probing URLs attempted and failed. *** Assembly Binder Log Entry (12/24/2010 @ 11:03:29 AM) *** The operation failed. Bind result: hr = 0x80070002. The system cannot find the file specified. Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll Running under executable C:\MyProject\bin\Debug\MyProject.vshost.exe --- A detailed error log follows. === Pre-bind state information === LOG: User = Null-Laptop-PC\Null-Laptop LOG: DisplayName = MyProject.Library, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null, processorArchitecture=MSIL (Fully-specified) LOG: Appbase = file:///C:/PluginDir LOG: Initial PrivatePath = C:\PluginDir LOG: Dynamic Base = NULL LOG: Cache Base = NULL LOG: AppName = MyProject.vshost.exe Calling assembly : (Unknown). === LOG: This bind starts in default load context. LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.exe.Config LOG: Using host configuration file: LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config. LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind). LOG: Attempting download of new URL file:///C:/PluginDir/MyProject.Library.DLL. LOG: Attempting download of new URL file:///C:/PluginDir/MyProject.Library/MyProject.Library.DLL. LOG: Attempting download of new URL file:///C:/PluginDir/MyProject.Library.EXE. LOG: Attempting download of new URL file:///C:/PluginDir/MyProject.Library/MyProject.Library.EXE. LOG: All probing URLs attempted and failed. *** Assembly Binder Log Entry (12/24/2010 @ 11:03:28 AM) *** The operation was successful. Bind result: hr = 0x0. The operation completed successfully. Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll Running under executable C:\MyProject\bin\Debug\MyProject.vshost.exe --- A detailed error log follows. === Pre-bind state information === LOG: User = Null-Laptop-PC\Null-Laptop LOG: DisplayName = MyProject (Partial) WRN: Partial binding information was supplied for an assembly: WRN: Assembly Name: MyProject | Domain ID: 1 WRN: A partial bind occurs when only part of the assembly display name is provided. WRN: This might result in the binder loading an incorrect assembly. WRN: It is recommended to provide a fully specified textual identity for the assembly, WRN: that consists of the simple name, version, culture, and public key token. WRN: See whitepaper http://go.microsoft.com/fwlink/?LinkId=109270 for more information and common solutions to this issue. LOG: Appbase = file:///C:/MyProject/bin/Debug/ LOG: Initial PrivatePath = NULL LOG: Dynamic Base = NULL LOG: Cache Base = NULL LOG: AppName = MyProject.vshost.exe Calling assembly : Microsoft.VisualStudio.HostingProcess.Utilities, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a. === LOG: This bind starts in default load context. LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.exe.Config LOG: Using host configuration file: LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config. LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind). LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/MyProject.DLL. LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/MyProject/MyProject.DLL. LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/MyProject.EXE. LOG: Assembly download was successful. Attempting setup of file: C:\MyProject\bin\Debug\MyProject.exe LOG: Entering run-from-source setup phase. LOG: Assembly Name is: MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null LOG: A partially-specified assembly bind succeeded from the application directory. Need to re-apply policy. LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.exe.Config LOG: Using host configuration file: LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config. LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind). LOG: Binding succeeds. Returns assembly from C:\MyProject\bin\Debug\MyProject.exe. LOG: Assembly is loaded in default load context. *** Assembly Binder Log Entry (12/24/2010 @ 11:03:29 AM) *** The operation was successful. Bind result: hr = 0x0. The operation completed successfully. Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll Running under executable C:\MyProject\bin\Debug\MyProject.vshost.exe --- A detailed error log follows. === Pre-bind state information === LOG: User = Null-Laptop-PC\Null-Laptop LOG: DisplayName = MyPlugin (Partial) WRN: Partial binding information was supplied for an assembly: WRN: Assembly Name: MyPlugin | Domain ID: 2 WRN: A partial bind occurs when only part of the assembly display name is provided. WRN: This might result in the binder loading an incorrect assembly. WRN: It is recommended to provide a fully specified textual identity for the assembly, WRN: that consists of the simple name, version, culture, and public key token. WRN: See whitepaper http://go.microsoft.com/fwlink/?LinkId=109270 for more information and common solutions to this issue. LOG: Appbase = file:///C:/PluginDir LOG: Initial PrivatePath = C:\PluginDir LOG: Dynamic Base = NULL LOG: Cache Base = NULL LOG: AppName = MyProject.vshost.exe Calling assembly : (Unknown). === LOG: This bind starts in default load context. LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.exe.Config LOG: Using host configuration file: LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config. LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind). LOG: Attempting download of new URL file:///C:/PluginDir/MyPlugin.DLL. LOG: Assembly download was successful. Attempting setup of file: C:\PluginDir\MyPlugin.dll LOG: Entering run-from-source setup phase. LOG: Assembly Name is: MyPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null LOG: A partially-specified assembly bind succeeded from the application directory. Need to re-apply policy. LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.exe.Config LOG: Using host configuration file: LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config. LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind). LOG: Binding succeeds. Returns assembly from C:\PluginDir\MyPlugin.dll. LOG: Assembly is loaded in default load context. *** Assembly Binder Log Entry (12/24/2010 @ 11:03:29 AM) *** The operation failed. Bind result: hr = 0x80070002. The system cannot find the file specified. Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll Running under executable C:\MyProject\bin\Debug\MyProject.vshost.exe --- A detailed error log follows. === Pre-bind state information === LOG: User = Null-Laptop-PC\Null-Laptop LOG: DisplayName = MyPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null (Fully-specified) LOG: Appbase = file:///C:/MyProject/bin/Debug/ LOG: Initial PrivatePath = NULL LOG: Dynamic Base = NULL LOG: Cache Base = NULL LOG: AppName = MyProject.vshost.exe Calling assembly : (Unknown). === LOG: This bind starts in default load context. LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.exe.Config LOG: Using host configuration file: LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config. LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind). LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/MyPlugin.DLL. LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/MyPlugin/MyPlugin.DLL. LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/MyPlugin.EXE. LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/MyPlugin/MyPlugin.EXE. LOG: All probing URLs attempted and failed. *** Assembly Binder Log Entry (12/24/2010 @ 11:03:29 AM) *** The operation was successful. Bind result: hr = 0x0. The operation completed successfully. Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll Running under executable C:\MyProject\bin\Debug\MyProject.vshost.exe --- A detailed error log follows. === Pre-bind state information === LOG: User = Null-Laptop-PC\Null-Laptop LOG: DisplayName = Microsoft.VisualStudio.HostingProcess.Utilities, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL (Fully-specified) LOG: Appbase = file:///C:/PluginDir LOG: Initial PrivatePath = C:\PluginDir LOG: Dynamic Base = NULL LOG: Cache Base = NULL LOG: AppName = MyProject.vshost.exe Calling assembly : (Unknown). === LOG: This bind starts in default load context. LOG: Download of application configuration file was attempted from file:///C:/MyProject/bin/Debug/MyProject.vshost.exe.Config. LOG: Found application configuration file (C:\MyProject\bin\Debug\MyProject.vshost.exe.Config). LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.exe.Config LOG: Using host configuration file: LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config. LOG: Post-policy reference: Microsoft.VisualStudio.HostingProcess.Utilities, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL LOG: Found assembly by looking in the GAC. LOG: Binding succeeds. Returns assembly from C:\Windows\assembly\GAC_MSIL\Microsoft.VisualStudio.HostingProcess.Utilities\10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.HostingProcess.Utilities.dll. LOG: Assembly is loaded in default load context. *** Assembly Binder Log Entry (12/24/2010 @ 11:03:29 AM) *** The operation was successful. Bind result: hr = 0x0. The operation completed successfully. Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll Running under executable C:\MyProject\bin\Debug\MyProject.vshost.exe --- A detailed error log follows. === Pre-bind state information === LOG: User = Null-Laptop-PC\Null-Laptop LOG: DisplayName = Ionic.Zip.Reduced, Version=1.9.1.5, Culture=neutral, PublicKeyToken=edbe51ad942a3f5c (Fully-specified) LOG: Appbase = file:///C:/MyProject/bin/Debug/ LOG: Initial PrivatePath = NULL LOG: Dynamic Base = NULL LOG: Cache Base = NULL LOG: AppName = MyProject.vshost.exe Calling assembly : MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null. === LOG: This bind starts in default load context. LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.exe.Config LOG: Using host configuration file: LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config. LOG: Post-policy reference: Ionic.Zip.Reduced, Version=1.9.1.5, Culture=neutral, PublicKeyToken=edbe51ad942a3f5c LOG: GAC Lookup was unsuccessful. LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/Ionic.Zip.Reduced.DLL. LOG: Assembly download was successful. Attempting setup of file: C:\MyProject\bin\Debug\Ionic.Zip.Reduced.dll LOG: Entering run-from-source setup phase. LOG: Assembly Name is: Ionic.Zip.Reduced, Version=1.9.1.5, Culture=neutral, PublicKeyToken=edbe51ad942a3f5c LOG: Binding succeeds. Returns assembly from C:\MyProject\bin\Debug\Ionic.Zip.Reduced.dll. LOG: Assembly is loaded in default load context.
I tried one of my attempted solutions again:
Creating an object using
this.appDomain.CreateInstanceAndUnwrap
inheriting from MarshalByRefObject with aLoadAssembly
method to load the assembly. I get an exception saying that the current assembly (containing the proxy class) could not be loaded (file not found, as above), even if I manually callthis.appDomain.Load(Assembly.GetExecutingAssembly().GetName(true))
.
I found out that CreateInstanceFromAndUnwrap
can accept the path to an assembly file, which makes things easy:
private T CreateOnAppDomain<T>() {
var type = typeof(T);
return (T) this.appDomain.CreateInstanceFromAndUnwrap(
type.Assembly.Location,
type.FullName
);
}
public void LoadAssemblies() {
var assemblyLoader = CreateOnAppDomain<AssemblyLoader>();
assemblyLoader.LoadAssembly(myInterfaceAssembly.GetName(true));
foreach (var assemblyName in this.assemblyNames) {
assemblyLoader.LoadAssembly(new AssemblyName(assemblyName));
}
}
class AssemblyLoader : MarshalByRefObject {
public void LoadAssembly(AssemblyName name) {
Assembly.Load(name);
}
}
This solves my AppDomain creation problems. (Now to get everything else working!)
Thanks for everyone's help; I really appreciate your inputs.
I believe that the exception is occurring when it tries to load the assembly into the main AppDomain
and not the domain you created explicitly. This is a side effect of using AppDomain.Load
which leads to the assembly being loaded into the current domain and the domain you created. Since the assembly is only in the bin path (plugin directory) of the domain you created you get the exception.
From MSDN related to AppDomain.Load:
The assembly is loaded into both domains because Assembly does not derive from MarshalByRefObject, and therefore the return value of the Load method cannot be marshaled. Instead, the common language runtime tries to load the assembly into the calling application domain.
I had a similar issue. You need to customize the method used to find the assemblies. The Console.Debug statements might need to be modified to compile but here is the general gist:
private static void SetupResolvingAdditionalThirdPartyDlls()
{
AppDomain.CurrentDomain.AssemblyResolve += ResolveAssemblies;
}
private static Assembly ResolveAssemblies(object sender, ResolveEventArgs args)
{
Assembly assembly = null;
bool foundAssembly = false;
Console.DebugFormat("Received request for the following dll {0}", args.Name);
int idx = args.Name.IndexOf(',');
if (idx > 0)
{
string partialName = args.Name.Substring(0, idx);
string dllName = partialName + ".dll";
string exeName = partialName + ".exe";
string searchDirectory = "locationOfDirectoryToSearch";
// Add other directories that you want to search here
List<string> directorySearch = new List<string>
{
CombinePath(searchDirectory, dllName),
CombinePath(searchDirectory, exeName),
// Include the other directories here to this list adding both the dll and exe.
};
foreach (string fileName in directorySearch)
{
if (File.Exists(fileName))
{
Console.DebugFormat("Found dll {0} at {1}", args.Name, fileName);
foundAssembly = true;
assembly = Assembly.LoadFrom(fileName);
break;
}
}
if (assembly == null)
{
if (!foundAssembly)
{
foreach (string fileName in directorySearch)
{
Console.DebugFormat("Could not find dll {0} in any search path used {1}", args.Name, fileName);
}
}
else
{
Console.DebugFormat("Could not load dll {0}", args.Name);
}
}
}
return assembly;
}
精彩评论