AppDomain Выполнить сборку

Я пытаюсь загрузить сборку (dll) в домен приложений и вызвать точку входа. (по сути, загрузка пакета в среду Azure). Я следил за этой статьей SO ( Как создать домен приложения и запустить в нем свое приложение?) и думаю, что я делаю это правильно, но у меня есть некоторые проблемы.

Я использовал несколько статей здесь, чтобы получить меня, насколько я, но я продолжаю сталкиваться с FileNotFoundException как описано в Невозможно загрузить исполняющуюся сборку в новый 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 учебный класс.

Я думаю, что делаю это правильно, но запомните первый абзац, так что, если я совершенно не в своей базе, я не против делать вещи по-другому.

ОБНОВИТЬ:

Я изменил код, чтобы принудительно загрузить сборки в новый домен приложения, и у меня все еще есть проблемы.

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 загружаются в новый домен приложения.

public class BootstrapProxy : MarshalByRefObject
{
    public void Main()
    {
        Console.WriteLine("Magic happened.");
    }
}

ОБНОВЛЕНИЕ 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 не идеален, так как есть несколько общих ссылок, и я могу столкнуться с конфликтами версий и другими проблемами.

1 ответ

Просто предположение, но проблема здесь:

var otherType = typeof(BootstrapProxy);

Делая это, вы загружаете эту сборку в вызывающий домен приложения. Из-за инициализации он пытается загрузить сборку, отсутствующую в пути поиска вызывающего домена. KABOOM!

Чтобы решить это:

Ссылаться на otherType по его полному имени и передаче имени сборки в виде строки. (Я думаю, что вы можете сойти с рук, просто используя FQN типа)

Также. Вы не должны действительно обращаться AssemblyResolve для сборок вне домена приложения.

Другие вопросы по тегам