как удалить плагин сборки после AppDomain.Unload (домен) - PullRequest
16 голосов
/ 08 января 2009

У меня странная проблема. Я хотел бы удалить сборку (plugin.dll на жестком диске), которая уже загружена, но сборка заблокирована операционной системой (Vista), даже если я ее выгрузил.

F.E.

AppDomainSetup setup = new AppDomainSetup();
setup.ShadowCopyFiles = "true";
AppDomain appDomain = AppDomain.CreateDomain(assemblyName + "_AppDomain", AppDomain.CurrentDomain.Evidence, setup);
IPlugin plugin = (IPlugin)appDomain.CreateInstanceFromAndUnwrap(assemblyName,                        "Plugin.MyPlugins");

Мне также нужны сведения о сборке, поскольку я не знаю, какие классы в сборке плагина реализуют интерфейс IPlugin. Должно быть возможно иметь более одного плагина в одной сборке плагина.

Assembly assembly = appDomain.Load(assemblyName);
if (assembly != null) {
   Type[] assemblyTypes = assembly.GetTypes();
   foreach (Type assemblyTyp in assemblyTypes) {
      if (typeof(IPlugin).IsAssignableFrom(assemblyTyp)) {
         IPlugin plugin = (IPlugin)Activator.CreateInstance(assemblyTyp);
         plugin.AssemblyName = assemblyNameWithEx;
         plugin.Host = this;
      }
   }
}
AppDomain.Unload(appDomain);

Как можно получить информацию о сборке из домена приложения без блокировки сборки?

С наилучшими пожеланиями

Ответы [ 5 ]

21 голосов
/ 12 января 2009

Я думаю, что у меня есть ответ! ответ от Эйвинда Скаара не будет работать, если вы хотите удалить загруженную сборку.

вместо

using (FileStream dll = File.OpenRead(path))
{
   fileContent = new byte[dll.Length];
   dll.Read(fileContent, 0, (int)dll.Length);
}
Assembly assembly = appDomain.Load(fileContent);

вы должны использовать

byte[] b = File.ReadAllBytes(assemblyName);
assembly = Assembly.Load(b);

С наилучшими пожеланиями

8 голосов
/ 19 марта 2010

Я знаю, что эта ветка совсем мертва, но сейчас я работаю над этим, и я только что получил ответ (в 1:30 утра ...)

AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
AppDomain app = AppDomain.CreateDomain("YaCsi", null, setup);
app.DoCallBack(LoaderCallback);
AppDomain.Unload(app);
File.Delete("__YaCsi_Test01.dll");

static void LoaderCallback()
{
    byte[] raw = File.ReadAllBytes("__YaCsi_Test01.dll");
    Assembly yacsi = Assembly.Load(raw);
    ((IScript)yacsi.CreateInstance("Script")).Go();
}

И это на самом деле не исключение! Надеюсь, кто-нибудь прочтет это и ответит на вопрос!

4 голосов
/ 29 февраля 2012

Смотрите эти страницы:

Установите новый AppDomain AppDomainSetup с помощью LoaderOptimization.MultiDomainHost

1017 * Е.Г. *

domainnew = AppDomain.CreateDomain(newdomain_name, null, new AppDomainSetup {
        ApplicationName = newdomain_name,
        ApplicationBase = assembly_directory,
        ConfigurationFile = ConfigurationManager.OpenExeConfiguration(assemblylocation).FilePath,
        LoaderOptimization = LoaderOptimization.MultiDomainHost,
        ShadowCopyFiles = shadowcopy ? "true" : "false",
    }
);
4 голосов
/ 11 января 2009

Если вы загружаете сборку как поток, она должна работать.

byte[] fileContent;
string path = "../../../test/bin/Debug/test.dll"; //Path to plugin assembly
using (FileStream dll = File.OpenRead(path))
{
   fileContent = new byte[dll.Length];
   dll.Read(fileContent, 0, (int)dll.Length);
}
Assembly assembly = appDomain.Load(fileContent);
File.Delete(path);
3 голосов
/ 08 января 2009

То, что мы делаем, - это наличие одной папки, которая отслеживается для сборок. При добавлении сборки приложение копирует ее во временный каталог, присваивает ему уникальное имя файла и загружает его оттуда.

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

Не думаю, что это прямо отвечает на ваш вопрос, но, вероятно, это решит вашу проблему.

...