Выполнение, а затем удаление DLL в C#

Я создаю самообновляющееся приложение, где у меня есть большая часть кода в отдельной DLL. Это командная строка и в конечном итоге будет запущена на Mono. Я просто пытаюсь заставить этот код работать в C# на окнах в командной строке.

Как я могу создать приложение AC#, которое я могу удалить поддерживающую DLL во время его работы?

AppDomain domain = AppDomain.CreateDomain("MyDomain");
ObjectHandle instance = domain.CreateInstance( "VersionUpdater.Core", "VersionUpdater.Core.VersionInfo");
object unwrap = instance.Unwrap();
Console.WriteLine(((ICommand)unwrap).Run());
AppDomain.Unload(domain);
Console.ReadLine();

на ReadLine VersionUpdater.Core.dll по-прежнему заблокирован от удаления

Интерфейс ICommand находится в VersionUpdater.Common.dll, на который ссылаются как приложение командной строки, так и VersionUpdater.Core.dll

4 ответа

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

Если вы ищете способ выполнить обновление, я бы предпочел заглушку exe, которая порождает настоящий AppDomain. Затем, когда этот stub exe обнаруживает, что должно быть применено обновление, он закрывает другой домен приложения и затем выполняет магию обновления.

РЕДАКТИРОВАТЬ: средство обновления не может делить библиотеки DLL с тем, что он обновляет, в противном случае он заблокирует эти библиотеки DLL и, следовательно, предотвратит их удаление. Я подозреваю, что именно поэтому вы все еще получаете исключение. Средство обновления должно быть автономным и не зависеть от всего, что использует другой домен приложений, и наоборот.

Вы всегда можете использовать MOVEFILE_DELAY_UNTIL_REBOOT удалить при перезагрузке. Скорее всего, это наименее хаккейный способ делать подобные вещи, хаккей я обычно вижу такие вещи, как; загрузка новых DLL или внедрение в explorer.exe, даже исправление системной библиотеки DLL для загрузки в другой процесс и т. д.

MoveFileEx от MSDN;

lpNewFileName [in, необязательно] Новое имя файла или каталога на локальном компьютере.

При перемещении файла место назначения может находиться в другой файловой системе или томе. Если пункт назначения находится на другом диске, необходимо установить MOVEFILE_COPY_ALLOWED флаг в dwFlags.

При перемещении каталога адресат должен находиться на том же диске.

Если dwFlags указывает MOVEFILE_DELAY_UNTIL_REBOOT и lpNewFileName имеет значение NULL, MoveFileEx регистрирует файл lpExistingFileName, который будет удален при перезапуске системы. Если lpExistingFileName ссылается на каталог, система удаляет каталог при перезапуске, только если каталог пуст.

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

Приложение запустится, поищите обновления. Если он обнаружит обновление, он загрузит копию нового приложения во временное хранилище, а затем запустит его (System.Diagnostics.Process.Start()), используя параметр командной строки, который говорит "вы обновляетесь". Тогда оригинальный exe выходит.

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

Запускается только что запущенный exe из исходного места установки приложения - видит временный файл и удаляет его. Затем возобновляется нормальное исполнение.

Unwrap загрузит сборку типа объекта в домен приложения, который ее вызывает. Одним из способов решения этой проблемы является создание типа в вашей "базовой" сборке, который вызывает command.run, а затем загрузка его в новый домен приложения. Таким образом, вам никогда не придется вызывать развертку для объекта из типа в другой сборке, и вы можете удалить сборку на диске.

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