我正在撰写支持ShouldProcess
的Powershell cmdlet。我没有固定的ConfirmImpact
价值,而是喜欢动态的'值取决于传递给cmdlet的参数的值。让我用一个例子来说明。
让我们假装我是一家网络托管服务提供商。我有很多网站,每个网站都属于以下类别之一,按重要性排序:Production
,Test
和Development
。作为托管管理的一部分,我有一个用于销毁网站的Remove-WebSite
cmdlet。以下代码说明了这一点:
Class WebSite {
[string] $Name
[string] $Category # Can be one of: Production, Test, Development
}
Function Remove-WebSite {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[WebSite] $WebSite
)
Write-Host "$($WebSite.Name) was destroyed"
}
目前,网站在未经确认的情况下销毁。虽然这很方便,但有太多的实习生错误地销毁了生产网站,所以我通过利用Powershell的ShouldProcess功能,在Remove-WebSite
cmdlet上更喜欢安全网。
因此,我将SupportsShouldProcess
和ConfirmImpact
值添加到CmdletBinding
属性中。我的cmdlet定义变为:
Function Remove-WebSite {
[CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact='High')]
Param(
[Parameter(Mandatory=$true)]
[WebSite] $WebSite
)
if ($PSCmdlet.ShouldProcess("$($WebSite.Category) site $($WebSite.Name)")) {
Write-Host "$($WebSite.Name) was destroyed"
}
}
通过此定义,现在要求任何调用Remote-Website
cmdlet的人确认他们确实要销毁该网站。现在几乎没有任何生产网站被破坏,除非网络开发者抱怨他们的自动脚本已停止工作。
我真正喜欢的是cmdlet的ConfirmImpact
值在运行时会有所不同,具体取决于网站类别的重要性 - 生成网站的High
,{{ 1}}用于测试站点,Medium
用于开发站点。以下函数定义说明了这一点:
Low
假设可能,这怎么办?
这里粘贴了完整的脚本以及一些测试代码:http://pastebin.com/kuk6HNm6
答案 0 :(得分:1)
这并不是你要求的(我认为严格来说,这是不可能的),但这可能是一种更好的方法。
单独ConfirmImpact
而不是prompt the user with $PSCmdlet.ShouldContinue()
。
根据Requesting Confirmation from Cmdlets(强调我的)中给出的指导:
对于大多数cmdlet,您不必显式指定ConfirmImpact。而是使用参数的默认设置,即Medium。如果将ConfirmImpact设置为High,则默认情况下将确认操作。 为高度破坏性操作保留此设置,例如重新格式化硬盘卷。
此外:
大多数cmdlet仅使用ShouldProcess方法请求确认。但是,某些情况可能需要额外确认。对于这些情况,通过调用ShouldContinue方法补充ShouldProcess调用。
...
如果cmdlet调用ShouldContinue方法,则cmdlet还必须提供Force开关参数。如果用户在用户调用cmdlet时指定Force,则cmdlet仍应调用ShouldProcess,但它应绕过对ShouldContinue的调用。
鉴于此指导,我建议进行以下更改:
Function Remove-WebSite {
[CmdletBinding(SupportsShouldProcess=$true)]
Param(
[Parameter(Mandatory=$true)]
[WebSite] $WebSite ,
[Switch] $Force
)
if ($PSCmdlet.ShouldProcess("$($WebSite.Category) site $($WebSite.Name)")) {
$destroy =
$Force -or
$WebSite.Category -ne 'Production' -or
$PSCmdlet.ShouldContinue("Are you sure you want to destroy $($WebSite.Name)?", "Really destroy this?")
if ($destroy) {
Write-Host "$($WebSite.Name) was destroyed"
}
}
}
答案 1 :(得分:1)
最简单的解决方案是删除$PSCmdlet.ShouldProcess
方法调用,并根据我们自己的标准有条件地调用$PSCmdlet.ShouldContinue
方法。这个问题是我们失去了-WhatIf
功能。正如briantist指出的那样,$PSCmdlet.ShouldContinue
应该与$PSCmdlet.ShouldProcess
一起使用,除非这会导致多余的确认提示,即当用户已经足够时,用户会提示两次。
通过实验,我发现通过在ConfirmImpact='None'
属性声明中设置CmdletBinding
,ShouldProcess
不再显示提示,但仍会返回$false
if {{ 1}}已指定。因此,-WhatIf
和ShouldProcess
都可以被调用,但仍然只向用户显示一个提示。然后我可以使用自己的逻辑来确定是否要调用ShouldContinue
。
这是一个完整的解决方案:
ShouldContinue