Как да разтоваря сглобки от 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, а „регистрирате“ или „добавяте“. Следователно вие не „разтоварвате“, а „премахвате“ (оттук и объркването в отговора на Konamiman)   -  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
Това няма нищо общо с App Domains. Тя има предвид GAC - person Ruben Bartelink; 09.11.2009
comment
Може ли +1, моля, да обясни уместността на отговора? (Ще премахна коментарите си и/или -1, ако има основателна причина...) - person Ruben Bartelink; 09.11.2009
comment
Прочетете отново въпроса, има всичко общо с AppDomains и малко общо с 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: Cancassing ще дисквалифицира :P Сигурен съм, че Karma ще те оправи за загубата на точки - повече се притеснявах отговорът ти, който трябваше да означя с +1, да стигне до полагащото му се място в реда на гласуване! (Изключете сега, за да намерите нещо ваше за +1!) - person Ruben Bartelink; 09.11.2009
comment
@Poulo: Това поне би си струвало да се опита. - person Konamiman; 09.11.2009
comment
@Poulo: Все още не си казал каква е твоята тестова платформа/рамка. В крайна сметка няма да можете да заредите едно и също сглобяване в един AppDomain, така че трябва да заобиколите този факт, или чрез изрично създаване на отделни, или може би чрез изпълнение на всеки тест в отделен процес и т.н. зависи от това, което правите -- така че трябва да обясните повече, ако имате нужда от точен отговор - 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 - което може да се дължи на множество тестове, изпълнявани в един и същ [AppDomain] контекст. Отговорът на Konamiman е правилен. Трябва да разширите въпроса си, за да обясните каква рамка/механизъм използвате за изпълнение на тестовете - това ще бъде ключът към намирането на най-добрия начин за изолиране на изпълненията едно от друго по подходящ начин. Когато казвате „инсталиране“, какво имате предвид, 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, постигайки същия резултат. Точно това каза Konamiman, така че дай му +1 (но предполагам, че си бил ти)! - person Ruben Bartelink; 09.11.2009
comment
Благодаря ви Konamiman и Ruben. @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