Sto provando a caricare la mia dll plugin in AppDomain separato, ma il metodo Load() non riesce con FileNotFoundException. Inoltre, sembra che l'impostazione della proprietà PrivateBinPath di AppDomainSetup non abbia alcun effetto, perché nel registro vedo "Initial PrivatePath = NULL". Tutti i plugin hanno un nome sicuro. Normalmente ogni plugin è memorizzato in [percorso di avvio dell'applicazione] \ postplugins \ [plugindir]. Se inserisco sottodirectory di plug-in sotto [Percorso avvio applicazione] directory, tutto funziona. Ho anche provato a modificare manualmente la proprietà AppBase ma non cambia.
ecco il codice:AppDomain.Load() non riesce con FileNotFoundException
public void LoadPostPlugins(IPluginsHost host, string pluginsDir)
{
_Host = host;
var privatePath = "";
var paths = new List<string>();
//build PrivateBinPath
var dirs = new DirectoryInfo(pluginsDir).GetDirectories();
foreach (var d in dirs)
{
privatePath += d.FullName;
privatePath += ";";
}
if (privatePath.Length > 1) privatePath = privatePath.Substring(0, privatePath.Length - 1);
//create new domain
var appDomainSetup = new AppDomainSetup { PrivateBinPath = privatePath };
Evidence evidence = AppDomain.CurrentDomain.Evidence;
var sandbox = AppDomain.CreateDomain("sandbox_" + Guid.NewGuid(), evidence, appDomainSetup);
try
{
foreach (var d in dirs)
{
var files = d.GetFiles("*.dll");
foreach (var f in files)
{
try
{
//try to load dll - here I get FileNotFoundException
var ass = sandbox.Load(AssemblyName.GetAssemblyName(f.FullName));
var f1 = f;
paths.AddRange(from type in ass.GetTypes()
select type.GetInterface("PluginsCore.IPostPlugin")
into iface
where iface != null
select f1.FullName);
}
catch (FileNotFoundException ex)
{
Debug.WriteLine(ex);
}
}
}
}
finally
{
AppDomain.Unload(sandbox);
}
foreach (var plugin in from p in paths
select Assembly.LoadFrom(p)
into ass
select
ass.GetTypes().FirstOrDefault(t => t.GetInterface("PluginsCore.IPostPlugin") != null)
into type
where type != null
select (IPostPlugin)Activator.CreateInstance(type))
{
plugin.Init(host);
plugin.GotPostsPartial += plugin_GotPostsPartial;
plugin.GotPostsFull += plugin_GotPostsFull;
plugin.PostPerformed += plugin_PostPerformed;
_PostPlugins.Add(plugin);
}
}
E qui è il log:
'FBTest.vshost.exe' (Managed (v4.0.30319)): Loaded 'D:\VS2010Projects\PNotes - NET\pnfacebook\FBTest\bin\Debug\postplugins\pnfacebook\pnfacebook.dll', Symbols loaded.
A first chance exception of type 'System.IO.FileNotFoundException' occurred in FBTest.exe
System.IO.FileNotFoundException: Could not load file or assembly 'pnfacebook, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9e2a2192d22aadc7' or one of its dependencies. The system cannot find the file specified.
File name: 'pnfacebook, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9e2a2192d22aadc7'
at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean forIntrospection)
at System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
at System.Reflection.Assembly.Load(String assemblyString)
at System.UnitySerializationHolder.GetRealObject(StreamingContext context)
at System.AppDomain.Load(AssemblyName assemblyRef)
at PNotes.NET.PNPlugins.LoadPostPlugins(IPluginsHost host, String pluginsDir) in D:\VS2010Projects\PNotes - NET\pnfacebook\FBTest\PNPlugins.cs:line 71
=== Pre-bind state information ===
LOG: User = ANDREYHP\Andrey
LOG: DisplayName = pnfacebook, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9e2a2192d22aadc7
(Fully-specified)
LOG: Appbase = file:///D:/VS2010Projects/PNotes - NET/pnfacebook/FBTest/bin/Debug/
LOG: Initial PrivatePath = NULL
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
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: pnfacebook, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9e2a2192d22aadc7
LOG: Attempting download of new URL file:///D:/VS2010Projects/PNotes - NET/pnfacebook/FBTest/bin/Debug/pnfacebook.DLL.
LOG: Attempting download of new URL file:///D:/VS2010Projects/PNotes - NET/pnfacebook/FBTest/bin/Debug/pnfacebook/pnfacebook.DLL.
LOG: Attempting download of new URL file:///D:/VS2010Projects/PNotes - NET/pnfacebook/FBTest/bin/Debug/pnfacebook.EXE.
LOG: Attempting download of new URL file:///D:/VS2010Projects/PNotes - NET/pnfacebook/FBTest/bin/Debug/pnfacebook/pnfacebook.EXE.
James, grazie mille! Finalmente vedo la spiegazione chiara sull'uso di MarshalByRefObject. Purtroppo non ho abbastanza reputazione per contrassegnare una risposta come utile (è necessario almeno 15) :( – dedpichto
Nessun problema! Felice ha aiutato :) –
Quando provo questo, anche se ho reso il metodo LoadPlugins generico, ottengo un SerializationException. Qualche suggerimento sul perché possa essere? Posso vedere che l'assembly è stato caricato nel dominio dell'app sandbox. –