Powershell — Как написать сценарий обновления сеанса в powershell?

#powershell #powershell-5.1

Вопрос:

У меня есть один скрипт ps1, который управляет операциями, которые я хочу выполнить. Я использую модули с определениями классов в модулях, использующих шаблон команд.

Все хорошо и хорошо в первый раз, когда я открываю консоль сеанса powershell и запускаю сценарий.

Если я каким-либо образом изменяю класс и повторно запускаю его в той же консоли, консоль, похоже, не принимает измененный сценарий. Я должен закрыть консоль powershell и запустить сценарий заново, чтобы мои изменения сработали. В противном случае я просто получаю сценарий, который ведет себя так же, как и до того, как я внес изменения. Очевидно, что происходит какое-то кэширование.

Мне интересно, решила ли MS наконец эту проблему. Я читал много старых постов с жалобами на это.

Я попробовал следующее, и ни один из них, похоже, не работает:

Удалить-Переменную * -Действие ошибки молча продолжается; Удалить-Модуль *; $ошибка.Очистить(); Очистить-Хост

Я даже попробовал их все вместе. Все равно не помогает.

Можно ли сделать что-то еще, чтобы обеспечить загрузку последнего кода в любых поддерживающих модулях? Необходимость закрывать всю консоль и перезагружать-серьезная проблема с производительностью.

Пример того, что я делаю:6

 using module .Logger.psm1
using module .AzurePlatformParmsDefault.psm1   
using module .AzurePlatform.psm1

[Logger] $Logger = [Logger]::Create()
[AzurePlatformParms] $AzurePlatformParms = [AzurePlatformParmsDefault]::Create( $Logger )
[AzurePlatform] $AzurePlatform = [AzurePlatform]::Create( $Logger, $AzurePlatformParms )

[bool] $Result = $AzurePlatform.Execute()
 

Комментарии:

1. Я обычно использую дочерний процесс: откройте pwsh.exe изнутри pwsh.exe , затем выйдите повторный запуск повторная загрузка корневого модуля

2. Хорошо, это отвечает на часть моего вопроса о том, решила ли MS эту проблему. Ваше решение может сработать, но оно, безусловно, не является изящным решением. MS powershell-это здорово, но это настоящая боль, когда приходится так обновляться. 😀

Ответ №1:

Общепринятое мнение состоит в том, что нет способа сделать это изначально, и создание нового пространства выполнения или процесса является решением.

Вы можете сбросить переменные до значений по умолчанию и импортировать переменные среды из области пользователя/компьютера (в Windows); перед очисткой любых заданий, событий, подписчиков событий и т.д. Однако это не настоящее обновление сеанса, и классы/пользовательские типы будут сохраняться.

Чтобы ускорить рабочий процесс, вы можете использовать функцию в своем $profile , которая может автоматизировать создание нового сеанса и загрузку того, что необходимо. Такой подход может сэкономить достаточно времени, чтобы тривиально повторно использовать интерактивный сеанс. Я включу тот, который я использую в своем профиле, в качестве примера. Она довольно всеобъемлющая, но я предлагаю адаптировать ее под ваши конкретные потребности.

Пример

 function Start-NewSession {
    [CmdletBinding(DefaultParameterSetName = 'NoChange')]
    [Alias('sans')]
    param(
        [Alias('N')]
        [switch]
        $NoClose,

        [Parameter(ParameterSetName = 'Elevate')]
        [Parameter(ParameterSetName = 'NoChange')]
        [Alias('nop')]
        [switch]
        $NoProfile,

        [Parameter(ParameterSetName = 'Elevate')]
        [Parameter(ParameterSetName = 'NoChange')]
        [Alias('A')]
        [switch]
        $AddCommands,

        [Parameter(ParameterSetName = 'Elevate')]
        [Alias('E')]
        [switch]
        $Elevate,

        [Parameter(ParameterSetName = 'DeElevate')]
        [Alias('D')]
        [switch]
        $DeElevate
    )
    $PSAppPath = (Get-Process -Id $PID).Path
    $SPParams = @{
        Filepath         = $PSAppPath
        WorkingDirectory = $PWD
        ArgumentList     = ''
    }
    if ($Elevate.IsPresent) {
        $SPParams['Verb'] = 'RunAs'
    }
    elseif ($DeElevate.IsPresent) {
        $SPParams['FilePath'] = Join-Path $env:windir 'explorer.exe'
        $SPParams['ArgumentList'] = $PSAppPath
    }
    if ($NoProfile.IsPresent) {
        $SPParams['ArgumentList']  = ' -NoProfile'
    }
    if ($AddCommands.IsPresent) {
        $ExtraCmds = Read-Host -Prompt 'Post-startup commands'
        if (-not [string]::IsNullOrWhiteSpace($ExtraCmds)) {
            $SPParams['ArgumentList']  =
            ' -NoExit -Command "'   $ExtraCmds.Replace('"', '"')   '"'
        }
    }
    if ([string]::IsNullOrWhiteSpace($SPParams['ArgumentList'])) {
        $SPParams.Remove('ArgumentList')
    }
    Start-Process @SPParams
    if (-not $NoClose.IsPresent) { exit }
}
 

Это позволяет печатать sans , чтобы создать новый сеанс и закрыть старый.