Модуль выгрузки Powershell … полностью

Я работаю над отладкой проекта Powershell. Я использую Import-Module для загрузки модуля PS из моей C # dll, и все работает нормально. Вызов Remove-Module не полностью выгружает модуль, хотя, поскольку DLL все еще заблокирована и не может быть удалена.

Есть ли способ заставить PSH полностью выгрузить модуль и выпустить DLL, чтобы я мог скопировать его и перезагрузить его снова с помощью Import-Module без перезапуска консоли PSH?

Обновить
Итак, если вы загружаете модуль в отдельный AppDomain, он все равно работает как обычный модуль? Может ли кто-нибудь представить пример?

Существует обходное решение. Откройте еще один экземпляр PowerShell:

 PS > powershell PS > [load DLL] PS > [do work] PS > exit 

После выхода вы вернетесь к экземпляру PowerShell, из которого вы сделали этот вызов (при условии, что вы powershell вызов powershell внутри и экземпляр PowerShell). Вы можете передать любой из обычных аргументов в powershell , чтобы вы могли использовать -Command или -File. Например,

 PS > powershell -Command '[load DLL]; [do work]' # Executes a command and exits PS > powershell -Command '.\myscript.ps1 param1 param2' # Executes the script and exits PS > powershell -File .\myscript.ps1 param1 param2 # Executes a script and exits. 

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

Все это было сделано из интерфейса командной строки PowerShell. Я не тестировал, что произойдет, если вы выбросите powershell в середине скрипта или если это работает в ISE. (Я подозреваю, что это работает в ISE.) Даже если это не работает внутри скрипта, это все еще полезно во время разработки.

Редактировать:

Проделали некоторые проверки. Так что это, похоже, отлично работает из скриптов и ISE, но в ISE есть оговорка. Из ISE вы не можете читать какие-либо данные от пользователя, когда находитесь внутри отдельного процесса PowerShell. Если вы попробуете, сценарий или команды перестают ждать, но окно ввода не отображается, как обычно, и, конечно же, вы не можете вводить непосредственно в окно вывода в ISE. Поэтому, если вам нужно запросить ввод в середине [do work] , запросите перед запуском нового экземпляра PowerShell и передайте его в работу как параметр. Это не проблема, если вы используете обычную командную строку PowerShell.

Нет. Поскольку PowerShell использует .NET под ним, он имеет те же требования. Вы не можете выгружать DLL из .NET AppDomain без выгрузки самого AppDomain. Поскольку пользовательский интерфейс PowerShell живет в одном AppDomain, это невозможно.

Я вижу здесь несколько полезных ответов, но вот мой, если это все еще проблема для кого-то (и это довольно лениво, что приятно).

 Enter-PSSession -localcomputername [load dlls] [execute script(s)] Exit-PSSession 

Короче говоря, создание PSSession для вашего локального компьютера создает другой сеанс powershell, включая то, что считается «загруженным», и когда вы выходите, он очищает вещи для вас.

Я считаю, что это справедливо для PowerShell: в мире .NET единственный способ разгрузить сборку – загрузить ее в другой AppDomain ; как только assembly загружается в AppDomain она остается загруженной на всю жизнь этого AppDomain .


Вот пример из streamа, который задает почти такой же вопрос и показывает пару способов создания и загрузки модуля в новый AppDomain:

http://www.eggheadcafe.com/conversation.aspx?messageid=30789124&threadid=30766269

У меня были те же проблемы, и я закончил обертку DLL, которую я хотел загрузить внутри командной строки exe, которую я тогда вызывал из скрипта. Таким образом, я вообще не загружал DLL внутри своего приложения.

В контексте разработки Cmdlet и проблем с разгрузкой вашей DLL существует два подхода, которые я использую.

Во-первых, я разрабатываю Visual Studio и настраиваю внешнюю программу (PowerShell) для загрузки моего Cmdlet. Таким образом, мой модуль загружается, когда я начинаю отладку, и выгружается, когда я прекращаю отладку.

Во-вторых, в тех случаях, когда я знаю, что хочу загрузить модуль, выполнить некоторую работу и убедиться, что модуль выгружен впоследствии, я использую второй экземпляр PowerShell. Это обсуждалось в других ответах, и мой ответ ниже показывает, как включить этот рабочий процесс, используя функцию с псевдонимом в моем профиле. Я меняю подсказку, чтобы иметь визуальное напоминание о том, что я вхожу в «рекурсивное окно PowerShell».

Создайте сценарий в своем профиле, чтобы запустить PowerShell

 function Start-DebugPowerShell { PowerShell -NoProfile -NoExit -Command { function prompt { $newPrompt = "$pwd.Path [DEBUG]" Write-Host -NoNewline -ForegroundColor Yellow $newPrompt return '> ' } } } Set-Alias -Name sdp -Value Start-DebugPowerShell 

Отредактируйте настройки отладки для своего проекта Cmdlet

Запуск внешней программы :

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe

Аргументы командной строки :

-NoProfile -NoExit -Command "Import-Module .\MyCoolCmdlet.dll"

Отладка вашего модуля

Теперь из Visual Studio запустите отладчик с F5 , и у вас есть новое окно PowerShell с загруженным Cmdlet, и вы можете отлаживать его, как вам нравится.

Используйте псевдоним «sdp» из любого windows PowerShell

Так как функция Start-DebugPowerShell находится в нашем профиле, и мы дали ей псевдоним sdp , вы можете использовать его для запуска второго экземпляра PowerShell в любое время, когда оно вам нужно.

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

  1. когда модуль загружается с объекта сборки .net, мы получили загруженный модуль с именем «dynamic_code_module_FirstPowershellModule»
  2. поэтому перед импортом мы выгружаем этот модуль и создаем новый из переименованного файла

предыдущие сборки не используются в домене

скрипт должен запускаться после восстановления каждого проекта

 Get-Module -Name "*FirstPowershellModule*" | Remove-Module $ii++ $destPath = "D:\Dev\FirstPowershellModule\FirstPowershellModule\bin\Debug\FirstPowershellModule" + $ii+ ".dll" Copy-Item D:\Dev\FirstPowershellModule\FirstPowershellModule\bin\Debug\FirstPowershellModule.dll -Destination $destPath $ass = [System.Reflection.Assembly]::LoadFile($destPath) import-module -Assembly $ass 

Сделайте копию DLL и загрузите эту копию. Вы можете перезагрузить DLL.

Модули PS являются assemblyми .net, когда вы Import-Module , вы загружаете их в AppDomain хоста PowerShell (приложение). Remove-Module просто удаляет модули из текущего сеанса.

Согласно msdn, http://msdn.microsoft.com/en-us/library/ms173101(v=vs.80).aspx

Невозможно разгрузить отдельную сборку без выгрузки всех доменов приложений, которые ее содержат. Используйте метод Unload из AppDomain для разгрузки доменов приложений. Дополнительные сведения см. В разделе «Разгрузка домена приложения».

Вы можете запустить новый узел PowerShell в новом AppDomain, импортировать свой модуль на хост и выполнить задание PowerShell. Модуль такой же обычный, как и в предыдущем хосте. Единственное различие заключается в том, что он находится в хосте, запущенном в другом AppDomain.

У меня был какой-то внешний модуль ( ImportExcel ), который я хотел обновить, и это не сработало . Для этой ситуации Install-Module -Scope CurrentUser (в случае, если он находится в папке вашего модуля пользователя, в противном случае пропустил -Scope ... param).

(Как они им управляли внутри – я не знаю, но вы держите свою текущую сессию PS.)

  • Как сделать аутентифицированный веб-запрос в Powershell?
  • Где я могу найти все COM-объекты, которые могут быть созданы в Powershell?
  • Сохранить hash-таблицу в нотации объекта PowerShell (PSON)
  • Выполнение скрипта PowerShell через контекстное меню проводника по элементам, содержащим амперсанды в их именах
  • Более одного «Открыть xxxxx здесь как администратор»
  • Использование расширенных наборов параметров в функции с несколькими уникальными переключателями
  • Не удается удалить iis из Windows Server 2012 R2
  • PowerShell - Коммутаторы Start-Process и Cmdline
  • .NET Framework 4.5.2 в Windows 7 w SP1, не отображающийся в списке функций Windows
  • Как сказать PowerShell дождаться окончания каждой команды до начала следующего?
  • Почему продолжать вести себя как перерыв в Foreach-Object?
  • Давайте будем гением компьютера.