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


38

Я хотел бы знать, как выгрузить сборку, загруженную в основной AppDomain.

У меня есть следующий код:

var assembly = Assembly.LoadFrom(FilePathHere); 

мне нужно/хочу, чтобы иметь возможность разгружать эту сборку, когда я сделал.

Благодарим за помощь.

+1

Попытка не использовать LoadFrom, это в другом контексте, чем контекст загрузки, и может вызвать проблемы. 24 сен. 082008-09-24 01:09:32

  0

Хороший вопрос, но я не вижу ни одного СРОЧНОГО ответа о том, как решить var assembly = Assembly.LoadFrom (FilePathHere); 13 июл. 122012-07-13 17:09:35

32

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

объяснение знакомства Джейсон Цандер из Why isn't there an Assembly.Unload method?

Если вы используете 3.5, вы можете использовать AddIn Framework, чтобы сделать его легче управлять/позвонить в различные AppDomains (которые вы может выгрузку, разгрузка всех сборок) , Если вы используете версии до этого, вам нужно создать новый appdomain, чтобы выгрузить его.

  0

Я думал, что это изменилось с .Net 3.5? 23 сен. 082008-09-23 19:52:46

+1

Планируется, что выгрузите сборку из домена приложения (я бы тоже их не ожидал, это очень сложно сделать, а те, кто заботится, будут использовать более безопасное и более эффективное обходное решение). Лучшее, что вы можете сделать, это легкий код gen, который упоминал Khoth. 20 мар. 092009-03-20 14:46:17


14

Вы не можете выгрузить сборку без разгрузки всего AppDomain. Here's why:

  1. Вы работаете, что код в домене приложения. Это означает, что есть потенциально вызывающие сайты и стеки вызовов с адресами в них, которые ожидают продолжения работы.

  2. Скажите, что вам удалось отслеживать все ручки и ссылки на уже запущенный код с помощью сборки. Предполагая, что вы не кодировали код, как только вы успешно освободили сборку, вы только освободили метаданные и IL. Код JIT'd по-прежнему распределяется в куче загрузчика домена приложения (методы JIT'd распределяются последовательно в буфере в том порядке, в котором они вызываются).

  3. Последний выпуск относится к коду, который был загружен совместно, иначе формально известен как «нейтральный домен» (проверьте/поделитесь с инструментом ngen). В этом режиме генерируется код для сборки из любого домена приложения (ничего не проводного).

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


4

Если вы хотите иметь временный код, который может быть выгружен впоследствии, в зависимости от ваших потребностей класс DynamicMethod может делать то, что вы хотите. Тем не менее, это не дает вам классов.


8

Вы должны загрузить свои временные сборки в другую AppDomain, а когда они не используются, вы можете выгрузить это AppDomain. Это безопасно и быстро.

+2

См. AppDomain.DoCallback, а также см. MarshalByRefObject: вы создаете «invoker» MarshalByRefObject с помощью метода, который делает то, что вы хотите, и возвращает что-то в своих изменяемых полях, вы создаете временный AppDomain и вызовите dom.DoCallback (invoker.DoSomething), чтобы сделать этот объект так, как вам хочется; то вы собираете результаты из invoker в своем приложении и выгружаете временный домен. 19 июл. 112011-07-19 15:23:27

  0

@jkff: К сожалению, если вы используете MarshalByRefObject, как в примере PingPong, Assembly.LoadFrom будет выполняться, как в главном AppDomain, поэтому выгрузка темпа AppDomain по-прежнему приведет к старой проблеме неспособности выгрузить сборку. Я думаю, вам, возможно, придется каким-то образом сериализовать нужные вам данные из Temp AppDomain без маршалинга, если вы хотите получить к нему доступ и все еще сможете разгружать сборку. 08 май. 132013-05-08 16:30:37

  0

@jkff: Возможно, вы правы, хотя ... но это не так просто, как то, что описано в примере MSDN. Вероятно, нужно использовать tempAppDomain.CreateInstanceAndUnwrap ... и может потребоваться даже использование AppDomain.GetData и SetData. (Это не будет помешать appdomain, если только цель должна быть загружена и выгружена.) 08 май. 132013-05-08 19:57:42


1

Вот хороший пример того, как компилировать и запускать DLL во время выполнения, а затем выгрузить все ресурсы: http://www.west-wind.com/presentations/dynamicCode/DynamicCode.htm


0

Я знаю, что его старый, но может кому-то помочь. Вы можете загрузить файл из потока и отпустить его. Это сработало для меня. Я нашел решение HERE.

Надеюсь, это поможет.


13

Я также знаю, что это очень старый, но может помочь кому-то, у кого есть эта проблема! Вот один из способов, который я нашел для этого! вместо использования:

var assembly = Assembly.LoadFrom(FilePathHere); 

использовать это:

var assembly = Assembly.Load(File.ReadAllBytes(FilePathHere)); 

Это фактически загружает «Contents» файла сборки, а не сам файл. Это означает, что в файле сборки нет блокировки файлов! Так что теперь он может быть скопирован, удален или обновлен без закрытия вашего приложения или попытки использовать отдельный AppDomain или Marshaling!

PROS: Очень простой в установке с 1 вкладышем кода! CONS: Невозможно использовать AppDomain, Assembly.Location или Assembly.CodeBase.

Теперь вам просто нужно уничтожить все экземпляры, созданные на сборке. Например:

assembly = null; 
  0

Под «** Can not use AppDomain **» вы подразумеваете, что вы не можете инициировать его внутри этой сборки или можете быть более конкретным ? Что относительно 'AppDomain.CurrentDomain.Load (File.ReadAllBytes (FilePathHere)),' есть ли какое-либо реальное отличие от Assembly.Load в этом конкретном сценарии? 23 окт. 162016-10-23 03:29:43


0

В качестве альтернативы, если сборка была просто загружена в первую очередь, чтобы проверить информацию о сборке, как на ОткрытыйКлюч, то лучше было бы, чтобы не загружать его, а скорее проверить информацию, сначала загрузив только AssemblyName:

AssemblyName an = AssemblyName.GetAssemblyName ("myfile.exe"); 
byte[] publicKey = an.GetPublicKey(); 
CultureInfo culture = an.CultureInfo; 
Version version = an.Version;