Я пытаюсь загрузить сборку (dll) в AppDomain и вызвать точку входа. (по сути, загрузите пакет в среду Azure) Я следил за этой статьей SO (How do I create an application domain and run my application in it?), и я думаю, что делаю все правильно, но у меня возникают некоторые проблемы.AppDomain Execute Assembly
Я использовал несколько статей, чтобы получить меня, насколько я знаю, но я продолжаю работать в FileNotFoundException
, как описано в Unable to load executing assembly into new AppDomain, FileNotFoundException. Моя проблема в том, что решение не работает. Сборка, которую я пытаюсь выполнить, существует в другом месте. Поэтому ApplicationBase
должен быть папкой сборки, которую я пытаюсь выполнить.
var otherType = typeof(BootstrapProxy);
var domaininfo = new AppDomainSetup
{
ConfigurationFile = executingAssembly + ".config",
ApplicationBase = _root
};
Evidence adevidence = AppDomain.CurrentDomain.Evidence;
_domain = AppDomain.CreateDomain(_type.ToString(), adevidence, domaininfo);
_domain.AssemblyResolve += (sender, args) =>
{
var lookupPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if (lookupPath == null) return null;
var assemblyname = new AssemblyName(args.Name).Name;
var assemblyFileName = Path.Combine(lookupPath, assemblyname + ".dll");
var assembly = Assembly.LoadFrom(assemblyFileName);
return assembly;
};
var proxy = _domain.CreateInstanceAndUnwrap(otherType.Assembly.FullName, otherType.FullName) as BootstrapProxy;
Последняя строка бросает исключение и событие AssemblyResolve никогда не выстреливает (как определено путем размещения точки останова на var lookupPath
линии.
Я также попробовал AppDomain.CurrentDomain.AssemblyResolve
событие с тем же обработчиком как описано выше, Я тоже попытался создать тот же обработчик внутри класса BootstrapProxy
.
Я думаю, что делаю это правильно, но обратите внимание на первый абзац, поэтому, если я полностью не в базе, я не против делая вещи по-другому.
ОБНОВЛЕНИЕ:
Я изменил код, чтобы принудительно загрузить сборки в новый appdomain и все еще иметь проблемы.
var otherType = typeof(BootstrapProxy);
var domaininfo = new AppDomainSetup
{
ConfigurationFile = executingAssembly + ".config",
ApplicationBase = _root
};
Evidence adevidence = AppDomain.CurrentDomain.Evidence;
_domain = AppDomain.CreateDomain(_type.ToString(), adevidence, domaininfo);
var deps = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
foreach (var dep in deps)
{
var lookupPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if (lookupPath == null) continue;
var assemblyname = new AssemblyName(dep.Name).Name;
var assemblyFileName = Path.Combine(lookupPath, assemblyname + ".dll");
if (File.Exists(assemblyFileName))
_domain.Load(File.ReadAllBytes(assemblyFileName));
}
_domain.Load(File.ReadAllBytes(Assembly.GetExecutingAssembly().Location));
var sl = _domain.GetAssemblies().ToArray();
var proxy = _domain.CreateInstanceAndUnwrap(otherType.Assembly.FullName, otherType.FullName) as BootstrapProxy;
sl
показывает, что все библиотеки DLL, в том числе один, на который ссылается FileNotFoundException
загружаются в новом AppDomain.
public class BootstrapProxy : MarshalByRefObject
{
public void Main()
{
Console.WriteLine("Magic happened.");
}
}
UPDATE 2:
Я изменил его вокруг этого:
var deps = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
foreach (var dep in deps)
{
var lookupPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if (lookupPath == null) continue;
var assemblyname = new AssemblyName(dep.Name).Name;
var assemblyFileName = Path.Combine(lookupPath, assemblyname + ".dll");
if (File.Exists(assemblyFileName))
File.Copy(assemblyFileName, Path.Combine(_root, assemblyname + ".dll"));
}
File.Copy(Assembly.GetExecutingAssembly().Location, Path.Combine(_root, Path.GetFileName(Assembly.GetExecutingAssembly().Location)));
var otherType = typeof(BootstrapProxy);
var domaininfo = new AppDomainSetup
{
ConfigurationFile = executingAssembly + ".config",
ApplicationBase = _root
};
Evidence adevidence = AppDomain.CurrentDomain.Evidence;
_domain = AppDomain.CreateDomain(_type.ToString(), adevidence, domaininfo);
var proxy = _domain.CreateInstanceAndUnwrap(otherType.Assembly.FullName, otherType.FullName) as BootstrapProxy;
if (proxy != null)
{
proxy.Main();
}
Этот метод копирования сборки и его ссылки на ApplicationBase нового AppDomain не является идеальным, так как это несколько общих ссылок, и я мог бы привести к конфликтам версий и другим проблемам.
BootstrapProxy присутствует в текущем домене, так как он выполняется в настоящее время, не так ли? –
@ TheGreatCO: Да, и потому, что он загружается, это не приведет к сбою 'AssemblyResolve'. (Он присутствует в обеих областях, я бы догадался).Попытка строковых параметров hardcoding вместо этого как тест, и он должен работать. 'AssemblyResolve' даже не нужно. – leppie
Я обновил свой вопрос с некоторой новой информацией. –