Разработка powershell в C # - блокировка импорта-модулей dll [дублировать]

Другое возможное решение: создать объект, содержащий имена групп и индексы.

  var regex = new RegExp ("(. *) (. *)");  var regexGroups = {FirstName: 1, LastName: 2};   

Затем используйте объектные ключи для ссылки на группы:

  var m = regex.exec («John Smith»);  var f = m [regexGroups.FirstName];   

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

29
задан Eric Schoonover 26 August 2009 в 23:55
поделиться

10 ответов

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

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

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

6
ответ дан Jesse MacNett 17 August 2018 в 08:47
поделиться

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

3
ответ дан Johann Strydom 17 August 2018 в 08:47
поделиться
  • 1
    к сожалению, я думаю, что это то, что я тоже могу сделать – David Faivre 14 October 2011 в 23:47

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

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

После выхода вы вернетесь к экземпляру 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.

21
ответ дан jpmc26 17 August 2018 в 08:47
поделиться
  • 1
    Несколько лет спустя поздно, но похожая проблема заключается в том, чтобы выполнить работу в фоновом задании . Рабочие задания Powershell выполняются как отдельные процессы. Вы по-прежнему не можете читать ввод пользователя, но он немного более гибкий, чем создание нового экземпляра Powershell. – JamesQMurphy 1 July 2014 в 21:07
  • 2
    @JamesQMurphy Фоновые задания выглядят так, как будто они предназначены для асинхронных операций. Если это то, что вам нужно в любом случае, это звучит как отличный вариант, но если вы этого не сделаете, это создает дополнительную сложность, когда вы можете просто запустить процесс в очереди. Есть ли другие преимущества, которые я не вижу? – jpmc26 1 July 2014 в 21:32
  • 3
    Два преимущества, о которых я могу думать: во-первых, вы передаете блок сценария в задание, что позволяет сохранить ваш скрипт в одном исходном файле. И, во-вторых, вы можете передавать (сериализуемые) объекты как параметры для задания, а не только текстовые параметры. Это аналогичное обходное решение для вас, поэтому я не публиковал его как отдельный ответ. – JamesQMurphy 3 July 2014 в 04:57

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

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

Во-вторых, в тех случаях, когда я знаю, что хочу загрузить модуль, сделайте некоторую работу и убедитесь, что модуль выгружен впоследствии я использую второй экземпляр 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» из любого окна PowerShell

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

3
ответ дан Kory Gill 17 August 2018 в 08:47
поделиться

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

17
ответ дан Mischa 17 August 2018 в 08:47
поделиться

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

0
ответ дан Sleeper Smith 17 August 2018 в 08:47
поделиться

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


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

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

5
ответ дан STW 17 August 2018 в 08:47
поделиться
  • 1
    Я ожидал, что это может быть так, но я не думаю, что вы можете загрузить взаимодействие с модулями PSH таким образом. Так что реальный ответ, скорее всего, того, чего я пытаюсь достичь, невозможен. – Eric Schoonover 26 August 2009 в 23:57
  • 2
    Можно загрузить & amp; выгружать DLL и заменять DLL с помощью функции теневой копии AppDomain. [Д0] codeproject.com/Articles/633140/… – John Baughman 5 February 2014 в 17:31

Модули PS являются сборками .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.

0
ответ дан terry 17 August 2018 в 08:47
поделиться

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

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

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

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

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
2
ответ дан UNdedss 17 August 2018 в 08:47
поделиться
0
ответ дан Andreas Dietrich 6 September 2018 в 06:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: