Сначала я займусь $PSCmdlet.ShouldContinue
. По сути, это способ запроса самостоятельно независимо от настроек подтверждения.
$PSCmdlet.ShouldProcess
с другой стороны, не всегда подсказывает. Он учитывает ConfirmImpact
(который вы установили на High
) и автоматическую переменную $ConfirmPreference
, которая по умолчанию High
. Допустимые значения: None
, Low
, Medium
и High
и предназначены для указания степени воздействия изменения, поэтому, когда значение $ConfirmPreference
равно или меньше значения команды ConfirmImpact
значение, тогда ShouldProcess
подскажет.
Я знаю, что это не ваш прямой вопрос, но фон важен для ответа на то, что вы должны делать.
Прямой вопрос: "где хранится ответ?" имеет скучный ответ: он хранится во внутренней переменной в классе, который определяет ShouldProcess
метод .
Так что, нет, вы, к сожалению, не можете этого понять.
Но это возвращает нас к .ShouldContinue
, который может взять эти ссылки и сохранить эти значения для вас, поэтому, когда вы хотите получить значения и хотите иметь возможность принимать решения с ними, вы должны использовать .ShouldContinue
.
Но вы действительно должны использовать оба. Потому что они делают разные вещи.
.ShouldProcess
не только отвечает за запросы подтверждения, но и отвечает за обработку -WhatIf
/ $WhatIfPreference
; когда вы произносите команду SupportsShouldProcess
, вы также говорите, что она поддерживает -WhatIf
. Если вы не используете .ShouldProcess
, вы попадете в ситуацию с командами, которые кажутся безопасными, но на самом деле принимают меры в любом случае.
Таким образом, шаблон чего-то подобного будет охватывать ваши базы:
if ($PSCmdet.ShouldProcess('thing', 'do')) {
if ($PSCmdlet.ShouldContinue('prompt')) {
# do it
}
}
Проблема с этим восходит к вашему подтверждению влияния и предпочтений. Если они совпадают, или если пользователь вызвал вашу команду с -Confirm
, вам будет предложено дважды: один раз в .ShouldProcess
и затем снова в .ShouldContinue
.
К сожалению, это отстой.
Я написал вещь, которая, кажется, работает вокруг этого. Сначала он основан на функции, которая позволяет вам запускать произвольный блок сценариев с подтверждением, так что вы все равно можете запустить .ShouldProcess
, подавляя его приглашение.
Затем он также пытается вычислить, нужна ли подсказка или нет, и затем выборочно вызвать .ShouldContinue
. Я не демонстрировал сохранение или сброс настроек переменных yesToAll и noToAll, потому что вы уже знаете, как это сделать.
Это в основном для демонстрации шаблона, который можно использовать для соответствия стандартной семантике приглашения подтверждения, с возможностью обнаружения, поддержкой параметров -Confirm
, $ConfirmPreference
и ConfirmImpact
, при сохранении поддержки -Verbose
и -WhatIf
.
function Test-Should {
[CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')]
param()
Begin {
$local:ShouldConfirm = $ConfirmPreference -ne [System.Management.Automation.ConfirmImpact]::None -and
$ConfirmPreference -le [System.Management.Automation.ConfirmImpact]::High # hard coded :(
function Invoke-CommandWithConfirmation {
[CmdletBinding(SupportsShouldProcess)]
param(
[Parameter(Mandatory)]
[ScriptBlock]
$ScriptBlock
)
Invoke-Command -NoNewScope -ScriptBlock $ScriptBlock
}
}
Process {
if (Invoke-CommandWithConfirmation -ScriptBlock { $PSCmdlet.ShouldProcess('target', 'action') } -Confirm:$false ) {
if (-not $local:ShouldConfirm -or $PSCmdlet.ShouldContinue('query', 'caption')) {
'Hi' | Write-Host
'Hello' | Write-Verbose
}
}
}
}
Вызовы:
Test-Should
Test-Should -Confirm
Test-Should -Confirm:$false
Test-Should -Verbose
Test-Should -Verbose -WhatIf
Test-Should -WhatIf -Confirm
Test-Should -WhatIf -Confirm:$false
И так далее, с разными значениями $ConfirmPreference
и разными значениями для команды ConfirmImpact
.
Единственное, что раздражает, - это значение, которое я пометил как жестко запрограммированное: оно должно совпадать с тем, которое вы указали в качестве подтверждения для этой команды.
Оказывается, это задница в заднице - программно получить это значение , но, возможно, вы могли бы каким-то образом это обработать.