#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
, чтобы создать новый сеанс и закрыть старый.