2013-07-11 5 views
2

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

ответ

1

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

var otherType = typeof(BootstrapProxy); 

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

Чтобы решить эту проблему:

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

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

+0

BootstrapProxy присутствует в текущем домене, так как он выполняется в настоящее время, не так ли? –

+0

@ TheGreatCO: Да, и потому, что он загружается, это не приведет к сбою 'AssemblyResolve'. (Он присутствует в обеих областях, я бы догадался).Попытка строковых параметров hardcoding вместо этого как тест, и он должен работать. 'AssemblyResolve' даже не нужно. – leppie

+0

Я обновил свой вопрос с некоторой новой информацией. –