PowerShell: модули, их расположение и перезагрузка

I have a pretty straightforward PS script, that refers to a bunch of self written modules (psm1). When I run my script from PowerShell ISE I am often pulling my hair out because due to the fact that the latest version of my module is not executed (but some outdated-somewhere-stored-in-memory-version).

У меня есть google-d, и google-d, и я читал, и пытался, и теперь настало время, когда я действительно был бы признателен, чтобы понять, что, черт возьми, происходит, вместо того, чтобы постоянно заниматься этими проблемами.

Некоторый пример кода:

(скрипт настроит ПК, которые будут работать на наших машинах, настроит общие ресурсы, создаст локальных пользователей, настроит сетевые карты и тому подобное)

Я начинаю с добавления местоположения моих модулей в путь к модулю следующим образом:

# Make sure .\Modules is part of the PSModulePath environment variable
$currentPSModulePath = [Environment]::GetEnvironmentVariable("PSModulePath", "Machine")
If (-Not ($currentPSModulePath -Like '*.\Modules*'))
{
    [Environment]::SetEnvironmentVariable("PSModulePath", $currentPSModulePath + ";.\Modules", "Machine")
}
Write-Host ("Environment variable for PSModulePath = {0}" -f [Environment]::GetEnvironmentVariable("PSModulePath", "Machine"))

Затем я загружаю необходимые модули:

### Import Modules
Import-Module -DisableNameChecking ConfigureSystemPC
Import-Module -DisableNameChecking ConfigureChipPC
Import-Module -DisableNameChecking ConfigureEngravePC
Import-Module -DisableNameChecking ConfigureCInkPC
Import-Module -DisableNameChecking ConfigureIPPC
Import-Module -DisableNameChecking ConfigureNPPC

И, наконец, спрашиваю у пользователя, какой ПК нужно настроить:

### Start configuring new PC ###

Write-Host "`nChoose the PC type form the options below:`n"
Write-Host "1. System PC"
Write-Host "2. Chip PC"
Write-Host "3. Engrave PC"
Write-Host "4. CInkjet PC"
Write-Host "5. IP PC"
Write-Host "6. NP PC"
Write-Host "7. Output PC"

$pcType = Read-Host "Please enter the PC type and press [enter]"
Write-Host ("You choose option: {0}" -f $pcType)

switch ($pcType)
{
    1 { Configure-SystemPC }
    2 { Configure-ChipPC }
    3 { Configure-EngravePC }
    4 { Configure-CInkPC }
    5 { Configure-IPPC }
    6 { Configure-NPPC }
    7 { Configure-OutputPC }
}

Проблема возникает, когда я что-то меняю в своем Configure-модуле. Когда я просто добавляю (например) Write-Host "bla bla", нажимаю кнопку «Сохранить» и снова отлаживаю мой основной скрипт (сценарий, показанный выше), PowerShell запустит СТАРУЮ версию модуля.

Если я не перезагружу модуль через:

  • rmo Configure-EngravePC, а затем ipmo Configure-EngravePC
  • ipmo Configure-EngravePC -Force

точно такая же «старая» версия моего модуля будет выполнена.

Кто может указать мне, как обычно с этим бороться? И почему, почему, почему мне даже приходится перезагружать модули, когда я запускаю свой скрипт через отладчик? Зачем ему «хранить» модули, которые были запущены в другом сеансе?? Я делаю что-то неправильно?

Заранее большое спасибо, я надеюсь, что кто-нибудь может рассказать об этом, я часто застреваю ..

Я очень предпочитаю ответ с правильным объяснением (или ссылку на хорошую документацию по этой теме)


person bas    schedule 16.04.2015    source источник


Ответы (1)


Вам нужно перезапустить ISE, так как он поддерживает единую консоль AFAIK.

Теперь, чтобы сделать это без перезагрузки, вам придется либо создать новое пространство выполнения ISE (Файл> Новая вкладка PowerShell), либо отказаться от ISE (рекомендуется, так как это sux) и использовать что-то обычное, например Cmder, и войти в ISE только для обширной отладки или реализовать некоторую форму автоперезагрузки.

Плохим решением было бы заменить функцию prompt при входе в ISE (или добавить ее в свой профиль):

rename-item Function:prompt Function:old_prompt -ErrorAction ignore
function global:prompt() {
    import-module -force Configure-EngravePC
    Function:old_prompt
}

Это будет работать нормально, кроме первого приглашения после изменения, поскольку функция приглашения еще не выполнена. Вы можете оптимизировать это для перезагрузки модуля, только если файл был недавно изменен (например, за последние 10 минут).

Так как это первое приглашение может быть проблематичным, есть способы его автоматизировать :) Создайте скрипт Autohotkey, который отслеживает модуль на наличие изменений и отправляет в свою консоль, как только обнаруживает изменения. Если вы сделаете это, то даже нет необходимости в быстром изменении, так как вы можете Send ipmo -force.. с самим Autohotkey. Я ROFLMAOd, когда писал это, но это эпично и будет работать отлично, если честно, если скрипт AHK сделан правильно.

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

ИЗМЕНИТЬ

Я нашел эту штуку, которая наполовину связана, но я все еще думаю, что решение AHK - это то, что нужно.

https://stackoverflow.com/a/7341211/82660

ИЗМЕНИТЬ2

А вот скрипт Ahk, который выполняет сложную часть (я не писал проверку изменений файлов, это тривиально) :

;Find window
SetTitleMatchMode, 2
ise := WinExist("PowerShell ISE")
WinGetPos, x,y,w,h

;Click somewhere inside console to select it
x := x + 20
y := h - 100  ;you may need to tweak this number depending on windows theme etc...
WinActivate
CoordMode, Mouse ,Screen
Click %x%, %y%
SendInput {ESC}import-module -force Configure-EngravePC{ENTER}

Скрипт, вероятно, может быть намного лучше и точнее, но мой AHKfoo сейчас плохой...

person majkinetor    schedule 16.04.2015