Как выгрузить сборки из GAC?

Я пытаюсь запустить автоматические тесты на определенном продукте. Тест состоит из установки продукта в разные места на жестком диске, затем выполнения над ним некоторых операций и закрытия приложения.

Код, запускающий процесс, выглядит так:

using (Process process = new Process())
            {
                process.StartInfo.FileName = "C:\mylocation\myapp.exe";
                process.Start();
            }

При непрерывном выполнении тестов при изменении места установки приложения я получаю исключение из приведенного выше кода, в котором говорится:

Ограничение API: сборка file: /// C: \ alternate_location \ myapp.exe уже загружена из другого места. Его нельзя загрузить из нового места в том же домене приложения.

Из-за этого тесты нельзя запускать непрерывно.

Что можно сделать, чтобы это преодолеть? Есть ли способ выгрузить сборки из GAC?

Могу ли я что-нибудь сделать в своем тестовом приложении, чтобы преодолеть это, ИЛИ нужно ли что-то изменить в тестируемом приложении?


person Poulo    schedule 09.11.2009    source источник
comment
Кстати, вы не «загружаете» материал в GAC, вы «регистрируете» или «добавляете». Следовательно, вы не «выгружаете», вы «удаляете» (отсюда и путаница в ответе Конамимана)   -  person Ruben Bartelink    schedule 09.11.2009
comment
В порядке. Спасибо за исправление.   -  person Poulo    schedule 09.11.2009
comment
Какую среду тестирования вы используете?   -  person serialhobbyist    schedule 09.11.2009
comment
Фреймворк для тестирования - это то, что я разрабатываю.   -  person Poulo    schedule 09.11.2009


Ответы (3)


Вы не можете выгружать сборки из домена приложения после загрузки. Но вы можете создать новый домен приложения (класс AppDomain) , загрузите в него сборки, используйте их, а затем выгрузите домен. См. Здесь: Хороший пример использования AppDomain

person Konamiman    schedule 09.11.2009
comment
Это не имеет ничего общего с доменами приложений. Она имеет в виду GAC - person Ruben Bartelink; 09.11.2009
comment
Не могли бы пользователи +1, пожалуйста, объясните уместность ответа? (Я удалю свои комментарии и / или -1, если есть веская причина ...) - person Ruben Bartelink; 09.11.2009
comment
Перечитайте вопрос, он имеет прямое отношение к доменам приложений и имеет мало общего с GAC. К сожалению, слишком поздно, чтобы отменить мой -1 ... Кто-нибудь может добавить +1, чтобы отменить, пожалуйста: P - person Ruben Bartelink; 09.11.2009
comment
Вы можете поставить +1 на любой из моих ответов на другие вопросы в качестве компенсации, хотя я не знаю, считается ли это законным / этичным в SO :-) - person Konamiman; 09.11.2009
comment
Итак, вы предлагаете, чтобы я запускал каждый тестовый пример в отдельном домене приложения или что-то в этом роде? - person Poulo; 09.11.2009
comment
@Konamiman: Канкассирование приведет к дисквалификации: P Я уверен, что Карма разберутся с вами за потерю очков - меня больше беспокоило то, что ваш ответ, который у меня должен был быть +1, занял свое законное место в порядке голосования! (Сейчас же прочь, чтобы найти что-нибудь свое до +1!) - person Ruben Bartelink; 09.11.2009
comment
@Poulo: По крайней мере, стоит попробовать. - person Konamiman; 09.11.2009
comment
@Poulo: Вы до сих пор не сказали, какой у вас тестовый стенд / фреймворк. Суть в том, что вы не сможете загрузить одну и ту же сборку в один домен приложения, поэтому вам нужно обойти этот факт, либо явно создавая отдельные, либо, возможно, выполняя каждый тест в отдельном процессе и т. Д. зависит от того, что вы делаете - поэтому вам нужно объяснять больше, если вам нужен точный ответ - person Ruben Bartelink; 09.11.2009

Добавление чего-либо в GAC не является неотъемлемой частью определения компонента - обычно это выполняется установщиком и т. Д.

Инструмент gacutil можно использовать для удаления вашего инструмента из GAC. В версии 1.1 он находился в директории Framework. В более новых версиях он находится в SDK, например C:\Program Files (x86)\Microsoft Visual Studio 8\SDK\v2.0\Bin

person Ruben Bartelink    schedule 09.11.2009
comment
Но я удаляю приложение после каждого теста. (в противном случае мне не разрешили бы установить еще одну его копию). Итак, не следует ли при удалении позаботиться об удалении ее также, если при установке была добавлена ​​сборка в GAC? Кроме того, я не могу воспроизвести проблему при выполнении тестов вручную. Так что это похоже на вопрос времени. Итак, вы предлагаете использовать инструмент для удаления сборки из GAC после каждого тестового примера? Это может оказаться неприемлемым для меня, потому что я запускаю тесты на машинах, на которых установлена ​​только платформа .NET. (Нет VS и SDK) Есть ли другой выход? - person Poulo; 09.11.2009
comment
Похоже, здесь много путаницы. Вы уверены, что помещаете материал в GAC? Возникающее исключение связано с попыткой дважды загрузить одну и ту же DLL из разных мест в один и тот же домен приложений, что может быть связано с тем, что несколько тестов выполняются в одном контексте [AppDomain]. Ответ Конамимана правильный. Вы должны расширить свой вопрос, чтобы объяснить, какой фреймворк / механизм вы используете для выполнения тестов - это будет ключом к выяснению наилучшего способа изолировать запуски друг от друга надлежащим образом. Когда вы говорите «установка», что вы имеете в виду, installutil? MSI? - person Ruben Bartelink; 09.11.2009
comment
Прости. Вот что происходит. У меня есть тестовое приложение, которое выполняет тесты один за другим. Тестовые примеры - это в основном методы класса. Тесты направлены на тестирование установщика продукта. Таким образом, каждый тестовый пример устанавливает продукт с помощью установщика InstallShield, а затем для проверки я запускаю приложение (которое было установлено), используя метод, описанный в вопросе. Я выполняю несколько основных операций, затем закрываю приложение и удаляю его. Следующий тестовый пример повторяет то же самое, за исключением того, что приложение устанавливается в другое место. ... продолжение - person Poulo; 09.11.2009
comment
продолжение ... В этом случае я получаю исключение. Я НЕ намеренно помещаю материал в GAC. - person Poulo; 09.11.2009
comment
@Poulo: Тогда я предлагаю удалить слово GAC из вашего вопроса. Похоже, проблема в том, что вы динамически загружаете класс .NET в свое тестовое приложение. Эта сборка остается в вашем домене приложения навсегда, и выгрузить ее невозможно. Обходной путь - либо убедиться, что вы загрузились в отдельный домен приложения [который вы затем выгружаете, когда закончите с], либо выполнить оболочку для другого EXE с достижением того же результата. Это именно то, что сказал Конамиман, так что давай +1 ему (но я предполагаю, что это был ты)! - person Ruben Bartelink; 09.11.2009
comment
Спасибо, Конамиман и Рубен. @Ruben: Ага, как вы догадались! - person Poulo; 09.11.2009

Не могли бы вы предоставить нам дополнительную информацию? Мне не удалось воспроизвести эту ошибку.

Process.Start должен создать новый процесс со своим собственным AppDomain.

На своей машине я создал проект Harness, в котором есть ссылка на проект DoNothing, которая является строго подписанной сборкой, и ссылка на проект LaodDoNothing, в которой есть ссылка на c: \ DoNothing.exe. Я вставил приведенный ниже код из Harness.Main с выводами отладки в виде встроенных комментариев. Exes с суффиксом unsigned не подписаны.

//debug outputs when Main is jitted:'Harness.vshost.exe' (Managed): Loaded 'c:\project\DoNothing\Harness\bin\Debug\DoNothing.exe', Symbols loaded.
//debug outputs when Main is jitted:'Harness.vshost.exe' (Managed): Loaded 'c:\project\DoNothing\Harness\bin\Debug\LoadDoNothing.exe', Symbols loaded.

ZaZaZa.Main();
LoadDoNothing.Program.Main();
using (Process process = new Process())
{
    process.StartInfo.FileName = @"C:\donothingunsigned.exe";
    process.Start(); //debug outputs The thread 0x17f0 has exited with code 0 (0x0).  No assemblies loads are logged to debug because this is a separate process.


}

using (Process process = new Process())
{
    process.StartInfo.FileName = @"C:\3\donothingunsigned2.exe";
    process.Start(); //Debug outputs The thread 0x1014 has exited with code 0 (0x0). No assemblies loads are logged to debug because this is a separate process.
}
AppDomain.CurrentDomain.ExecuteAssembly(@"C:\donothingunsigned.exe"); //debug outputs 'Harness.vshost.exe' (Managed): Loaded 'C:\donothingunsigned.exe'
AppDomain.CurrentDomain.ExecuteAssembly(@"C:\3\donothingunsigned2.exe"); //no debug output because the loader realizes this assembly has already been loaded and uses that.
person David Silva Smith    schedule 09.11.2009
comment
Я не совсем понял, что вы пытаетесь донести. Но я заметил, что вы запустили два разных исполняемых файла: donothingunsigned.exe и donothingunsigned2.exe. Моя проблема связана с попыткой запустить один и тот же исполняемый файл из разных мест. Это то, что дает мне исключение при обстоятельствах, которые я упомянул в вопросе, а также в последующих комментариях. - person Poulo; 09.11.2009
comment
Мне не удалось воспроизвести ошибку описанными выше способами. Процессы не разделяют домены приложений, поэтому я не понимаю, как Process.Start () может вызвать вашу ошибку. - person David Silva Smith; 25.11.2009