[玩转系统] 您想了解的有关 ShouldProcess 的所有信息
作者:精品下载站 日期:2024-12-14 03:04:03 浏览:13 分类:玩电脑
您想了解的有关 ShouldProcess 的所有信息
PowerShell 函数具有多项功能,可以极大地改善用户与其交互的方式。经常被忽视的一个重要功能是 -WhatIf
和 -Confirm
支持,并且可以轻松添加到您的函数中。在本文中,我们将深入探讨如何实现此功能。
笔记
本文的原始版本出现在@KevinMarquette 撰写的博客上。 PowerShell 团队感谢 Kevin 与我们分享这些内容。请查看他的博客:PowerShellExplained.com。
这是一个简单的功能,您可以在函数中启用它,为需要它的用户提供安全网。没有什么比第一次运行一个你知道可能很危险的命令更可怕的了。使用 -WhatIf
运行它的选项可以产生很大的不同。
CommonParameters
在我们考虑实现这些通用参数之前,我想快速了解一下它们的使用方式。
使用-WhatIf
当命令支持 -WhatIf
参数时,您可以查看该命令将执行的操作,而不用进行更改。这是测试命令影响的好方法,尤其是在执行破坏性操作之前。
PS C:\temp> Get-ChildItem
Directory: C:\temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 4/19/2021 8:59 AM 0 importantfile.txt
-a---- 4/19/2021 8:58 AM 0 myfile1.txt
-a---- 4/19/2021 8:59 AM 0 myfile2.txt
PS C:\temp> Remove-Item -Path .\myfile1.txt -WhatIf
What if: Performing the operation "Remove File" on target "C:\Temp\myfile1.txt".
如果该命令正确实现了 ShouldProcess
,它应该向您显示它会进行的所有更改。以下是使用通配符删除多个文件的示例。
PS C:\temp> Remove-Item -Path * -WhatIf
What if: Performing the operation "Remove File" on target "C:\Temp\myfile1.txt".
What if: Performing the operation "Remove File" on target "C:\Temp\myfile2.txt".
What if: Performing the operation "Remove File" on target "C:\Temp\importantfile.txt".
使用-确认
支持 -WhatIf
的命令也支持 -Confirm
。这使您有机会在执行操作之前确认该操作。
PS C:\temp> Remove-Item .\myfile1.txt -Confirm
Confirm
Are you sure you want to perform this action?
Performing the operation "Remove File" on target "C:\Temp\myfile1.txt".
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"):
在这种情况下,您有多个选项可以让您继续、跳过更改或停止脚本。帮助提示对每个选项进行了如下描述。
Y - Continue with only the next step of the operation.
A - Continue with all the steps of the operation.
N - Skip this operation and proceed with the next operation.
L - Skip this operation and all subsequent operations.
S - Pause the current pipeline and return to the command prompt. Type "exit" to resume the pipeline.
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"):
本土化
此提示已在 PowerShell 中本地化,因此语言会根据操作系统的语言而变化。这是 PowerShell 为您管理的另一件事。
开关参数
让我们快速了解一下将值传递给 switch 参数的方法。我指出这一点的主要原因是您经常希望将参数值传递给您调用的函数。
第一种方法是特定的参数语法,可用于所有参数,但您通常会看到它用于开关参数。您指定一个冒号将值附加到参数。
Remove-Item -Path:* -WhatIf:$true
您可以对变量执行相同的操作。
$DoWhatIf = $true
Remove-Item -Path * -WhatIf:$DoWhatIf
第二种方法是使用哈希表来展开值。
$RemoveSplat = @{
Path = '*'
WhatIf = $true
}
Remove-Item @RemoveSplat
如果您不熟悉哈希表或 splatting,我有另一篇文章涵盖了您想了解的有关哈希表的所有内容。
支持应处理
启用 -WhatIf
和 -Confirm
支持的第一步是在函数的 CmdletBinding
中指定 SupportsShouldProcess
。
function Test-ShouldProcess {
[CmdletBinding(SupportsShouldProcess)]
param()
Remove-Item .\myfile1.txt
}
通过以这种方式指定 SupportsShouldProcess
,我们现在可以使用 -WhatIf
(或 -Confirm
)调用我们的函数。
PS> Test-ShouldProcess -WhatIf
What if: Performing the operation "Remove File" on target "C:\Temp\myfile1.txt".
请注意,我没有创建名为 -WhatIf
的参数。指定 SupportsShouldProcess
会自动为我们创建它。当我们在Test-ShouldProcess
上指定-WhatIf
参数时,我们调用的一些东西也会执行-WhatIf
处理。
信任但要验证
相信您调用的所有内容都继承 -WhatIf
值存在一些危险。对于其余示例,我将假设它不起作用,并且在调用其他命令时非常明确。我建议您也这样做。
function Test-ShouldProcess {
[CmdletBinding(SupportsShouldProcess)]
param()
Remove-Item .\myfile1.txt -WhatIf:$WhatIfPreference
}
一旦你对游戏中的所有部分有了更好的理解,我将在稍后重新讨论这些细微差别。
$PSCmdlet.ShouldProcess
允许您实现 SupportsShouldProcess
的方法是 $PSCmdlet.ShouldProcess
。您可以调用 $PSCmdlet.ShouldProcess(...)
来查看是否应该处理某些逻辑,然后 PowerShell 会处理其余的事情。让我们从一个例子开始:
function Test-ShouldProcess {
[CmdletBinding(SupportsShouldProcess)]
param()
$file = Get-ChildItem './myfile1.txt'
if($PSCmdlet.ShouldProcess($file.Name)){
$file.Delete()
}
}
对 $PSCmdlet.ShouldProcess($file.name)
的调用会检查 -WhatIf
(和 -Confirm
参数),然后进行相应处理。 -WhatIf
导致 ShouldProcess
输出更改的描述并返回 $false
:
PS> Test-ShouldProcess -WhatIf
What if: Performing the operation "Test-ShouldProcess" on target "myfile1.txt".
使用 -Confirm
的调用会暂停脚本并提示用户选择继续。如果用户选择 Y
,则返回 $true
。
PS> Test-ShouldProcess -Confirm
Confirm
Are you sure you want to perform this action?
Performing the operation "Test-ShouldProcess" on target "myfile1.txt".
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"):
$PSCmdlet.ShouldProcess
的一个很棒的功能是它兼作详细输出。在实现 ShouldProcess
时,我经常依赖于此。
PS> Test-ShouldProcess -Verbose
VERBOSE: Performing the operation "Test-ShouldProcess" on target "myfile1.txt".
重载
$PSCmdlet.ShouldProcess
有一些不同的重载,具有不同的参数用于自定义消息传递。我们已经在上面的示例中看到了第一个。让我们仔细看看它。
function Test-ShouldProcess {
[CmdletBinding(SupportsShouldProcess)]
param()
if($PSCmdlet.ShouldProcess('TARGET')){
# ...
}
}
这会生成包含函数名称和目标(参数值)的输出。
What if: Performing the operation "Test-ShouldProcess" on target "TARGET".
指定第二个参数作为操作使用操作值而不是消息中的函数名称。
## $PSCmdlet.ShouldProcess('TARGET','OPERATION')
What if: Performing the operation "OPERATION" on target "TARGET".
下一个选项是指定三个参数以完全自定义消息。当使用三个参数时,第一个参数是整个消息。后两个参数仍然在 -Confirm
消息输出中使用。
## $PSCmdlet.ShouldProcess('MESSAGE','TARGET','OPERATION')
What if: MESSAGE
快速参数参考
以防万一您来到这里只是为了弄清楚应该使用哪些参数,这里有一个快速参考,显示参数如何在不同的 -WhatIf
场景中更改消息。
## $PSCmdlet.ShouldProcess('TARGET')
What if: Performing the operation "FUNCTION_NAME" on target "TARGET".
## $PSCmdlet.ShouldProcess('TARGET','OPERATION')
What if: Performing the operation "OPERATION" on target "TARGET".
## $PSCmdlet.ShouldProcess('MESSAGE','TARGET','OPERATION')
What if: MESSAGE
我倾向于使用带有两个参数的那个。
应处理原因
我们有第四个重载,它比其他重载更先进。它允许您获取执行 ShouldProcess
的原因。我只是为了完整性才在此处添加此内容,因为我们只需检查 $WhatIfPreference
是否为 $true
即可。
$reason = ''
if($PSCmdlet.ShouldProcess('MESSAGE','TARGET','OPERATION',[ref]$reason)){
Write-Output "Some Action"
}
$reason
我们必须使用 [ref]
将 $reason
变量作为引用变量传递到第四个参数。 ShouldProcess
使用值 None
或 WhatIf
填充 $reason
。我并没有说这很有用,我也没有理由使用它。
放置在哪里
您可以使用 ShouldProcess
来使脚本更安全。因此,当您的脚本进行更改时,您可以使用它。我喜欢将 $PSCmdlet.ShouldProcess
调用放置在尽可能靠近更改的地方。
## general logic and variable work
if ($PSCmdlet.ShouldProcess('TARGET','OPERATION')){
# Change goes here
}
如果我正在处理一组项目,我会为每个项目调用它。因此该调用被放置在 foreach 循环内。
foreach ($node in $collection){
# general logic and variable work
if ($PSCmdlet.ShouldProcess($node,'OPERATION')){
# Change goes here
}
}
我将 ShouldProcess
紧密地放在更改周围的原因是,我希望在指定 -WhatIf
时执行尽可能多的代码。我希望尽可能运行设置和验证,以便用户可以看到这些错误。
我也喜欢在我的 Pester 测试中使用它来验证我的项目。如果我有一段难以在 pester 中模拟的逻辑,我通常可以将其包装在 ShouldProcess
中,并在测试中使用 -WhatIf
调用它。测试一些代码总比不测试任何代码要好。
$WhatIfPreference
我们的第一个偏好变量是$WhatIfPreference
。默认情况下这是$false
。如果您将其设置为 $true
,则您的函数将像您指定 -WhatIf
一样执行。如果您在会话中设置此项,则所有命令都会执行 -WhatIf
执行。
当您使用 -WhatIf
调用函数时,$WhatIfPreference
的值会在函数作用域内设置为 $true
。
ConfirmImpact
我的大多数示例都是针对 -WhatIf
的,但到目前为止,所有内容都可以使用 -Confirm
来提示用户。您可以将函数的 ConfirmImpact
设置为高,它会提示用户,就像使用 -Confirm
调用它一样。
function Test-ShouldProcess {
[CmdletBinding(
SupportsShouldProcess,
ConfirmImpact = 'High'
)]
param()
if ($PSCmdlet.ShouldProcess('TARGET')){
Write-Output "Some Action"
}
}
由于高
影响,对Test-ShouldProcess
的调用正在执行-Confirm
操作。
PS> Test-ShouldProcess
Confirm
Are you sure you want to perform this action?
Performing the operation "Test-ShouldProcess" on target "TARGET".
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): y
Some Action
明显的问题是,现在在其他脚本中使用而不提示用户变得更加困难。在这种情况下,我们可以将 $false
传递给 -Confirm
来抑制提示。
PS> Test-ShouldProcess -Confirm:$false
Some Action
我将在后面的部分中介绍如何添加 -Force
支持。
$ConfirmPreference
$ConfirmPreference
是一个自动变量,用于控制 ConfirmImpact
何时要求您确认执行。以下是 $ConfirmPreference
和 ConfirmImpact
的可能值。
High
Medium
Low
None
使用这些值,您可以为每个功能指定不同的影响级别。如果您将 $ConfirmPreference
设置为高于 ConfirmImpact
的值,则系统不会提示您确认执行。
默认情况下,$ConfirmPreference
设置为 High
,ConfirmImpact
设置为 Medium
。如果您希望函数自动提示用户,请将 ConfirmImpact
设置为 High
。否则,如果其具有破坏性,则将其设置为中
;如果该命令始终在生产中安全运行,则将其设置为低
。如果您将其设置为none
,即使指定了-Confirm
,它也不会提示(但它仍然为您提供-WhatIf
支持)。
使用 -Confirm
调用函数时,$ConfirmPreference
的值在函数范围内设置为 Low
。
抑制嵌套的确认提示
$ConfirmPreference
可以由您调用的函数获取。这可以创建这样的场景:您添加确认提示,并且您调用的函数也会提示用户。
我倾向于做的是在我已经处理了提示时在调用的命令上指定 -Confirm:$false
。
function Test-ShouldProcess {
[CmdletBinding(SupportsShouldProcess)]
param()
$file = Get-ChildItem './myfile1.txt'
if($PSCmdlet.ShouldProcess($file.Name)){
Remove-Item -Path $file.FullName -Confirm:$false
}
}
这让我们回到了之前的警告:何时不将 -WhatIf
传递给函数以及何时将 -Confirm
传递给函数存在细微差别。我保证稍后会再讨论这个问题。
$PSCmdlet.ShouldContinue
如果您需要比 ShouldProcess
提供的更多控制,您可以使用 ShouldContinue
直接触发提示。 ShouldContinue
忽略 $ConfirmPreference
、ConfirmImpact
、-Confirm
、$WhatIfPreference
和 -WhatIf
因为每次执行都会提示。
乍一看,很容易混淆 ShouldProcess
和 ShouldContinue
。我倾向于记住使用 ShouldProcess
,因为该参数在 CmdletBinding
中称为 SupportsShouldProcess
。几乎在所有场景中您都应该使用 ShouldProcess
。这就是为什么我首先介绍该方法的原因。
让我们看一下 ShouldContinue
的实际应用。
function Test-ShouldContinue {
[CmdletBinding()]
param()
if($PSCmdlet.ShouldContinue('TARGET','OPERATION')){
Write-Output "Some Action"
}
}
这为我们提供了更简单的提示和更少的选项。
Test-ShouldContinue
Second
TARGET
[Y] Yes [N] No [S] Suspend [?] Help (default is "Y"):
ShouldContinue
的最大问题是它要求用户以交互方式运行它,因为它总是提示用户。您应该始终构建可供其他脚本使用的工具。执行此操作的方法是实施 -Force
。稍后我会重新审视这个想法。
是的
这是由 ShouldProcess
自动处理的,但我们必须为 ShouldContinue
做更多的工作。还有第二个方法重载,我们必须通过引用传入一些值来控制逻辑。
function Test-ShouldContinue {
[CmdletBinding()]
param()
$collection = 1..5
$yesToAll = $false
$noToAll = $false
foreach($target in $collection) {
$continue = $PSCmdlet.ShouldContinue(
"TARGET_$target",
'OPERATION',
[ref]$yesToAll,
[ref]$noToAll
)
if ($continue){
Write-Output "Some Action [$target]"
}
}
}
我添加了一个 foreach
循环和一个集合来显示它的实际情况。我将 ShouldContinue
调用从 if
语句中取出,以使其更易于阅读。调用具有四个参数的方法开始变得有点难看,但我试图让它看起来尽可能干净。
执行力
ShouldProcess
和 ShouldContinue
需要以不同的方式实现-Force
。这些实现的技巧是 ShouldProcess
应始终执行,但如果指定 -Force
,则不应执行 ShouldContinue
。
应该处理-强制
如果您将 ConfirmImpact
设置为 high
,您的用户首先要尝试的就是使用 -Force
抑制它。无论如何,这是我做的第一件事。
Test-ShouldProcess -Force
Error: Test-ShouldProcess: A parameter cannot be found that matches parameter name 'force'.
如果您还记得 ConfirmImpact
部分,他们实际上需要这样调用它:
Test-ShouldProcess -Confirm:$false
并不是每个人都意识到他们需要这样做,并且 -Force
不会抑制 ShouldContinue
。因此,为了用户的理智,我们应该实现-Force
。在这里查看这个完整的示例:
function Test-ShouldProcess {
[CmdletBinding(
SupportsShouldProcess,
ConfirmImpact = 'High'
)]
param(
[Switch]$Force
)
if ($Force -and -not $Confirm){
$ConfirmPreference = 'None'
}
if ($PSCmdlet.ShouldProcess('TARGET')){
Write-Output "Some Action"
}
}
我们添加自己的 -Force
开关作为参数。在 CmdletBinding
中使用 SupportsShouldProcess
时,会自动添加 -Confirm
参数。
[CmdletBinding(
SupportsShouldProcess,
ConfirmImpact = 'High'
)]
param(
[Switch]$Force
)
这里重点关注 -Force
逻辑:
if ($Force -and -not $Confirm){
$ConfirmPreference = 'None'
}
如果用户指定-Force
,我们希望抑制确认提示,除非他们也指定-Confirm
。这允许用户强制更改但仍确认更改。然后我们在本地范围内设置$ConfirmPreference
。现在,使用 -Force
参数临时将 $ConfirmPreference
设置为 none,从而禁用确认提示。
if ($PSCmdlet.ShouldProcess('TARGET')){
Write-Output "Some Action"
}
如果有人同时指定 -Force
和 -WhatIf
,则 -WhatIf
需要优先。此方法保留了 -WhatIf
处理,因为 ShouldProcess
始终被执行。
不要使用 ShouldProcess
在 if
语句内添加对 $Force
值的检查。这是针对此特定场景的反模式,尽管我将在下一节的 ShouldContinue
中向您展示这一点。
应该继续-强制
这是使用 ShouldContinue
实现 -Force
的正确方法。
function Test-ShouldContinue {
[CmdletBinding()]
param(
[Switch]$Force
)
if($Force -or $PSCmdlet.ShouldContinue('TARGET','OPERATION')){
Write-Output "Some Action"
}
}
通过将 $Force
放置在 -or
运算符的左侧,它会首先被求值。以这种方式编写会缩短 if
语句的执行。如果$force
为$true
,则不执行ShouldContinue
。
PS> Test-ShouldContinue -Force
Some Action
在这种情况下,我们不必担心 -Confirm
或 -WhatIf
,因为 ShouldContinue
不支持它们。这就是为什么它需要以不同于 ShouldProcess
的方式进行处理。
范围问题
使用 -WhatIf
和 -Confirm
应该适用于函数内的所有内容及其调用的所有内容。他们通过在本地范围内将 $WhatIfPreference
设置为 $true
或将 $ConfirmPreference
设置为 Low
来实现此目的。功能。当您调用另一个函数时,对 ShouldProcess
的调用将使用这些值。
这实际上在大多数情况下都可以正常工作。每当您在同一范围内调用内置 cmdlet 或函数时,它都会起作用。当您从控制台调用脚本或脚本模块中的函数时,它也适用。
它不起作用的一个特定位置是当脚本或脚本模块调用另一个脚本模块中的函数时。这听起来可能不是一个大问题,但您创建或从 PSGallery 提取的大多数模块都是脚本模块。
核心问题是,当从其他脚本模块中的函数调用时,脚本模块不会继承 $WhatIfPreference
或 $ConfirmPreference
(以及其他几个)的值。
将其总结为一般规则的最佳方法是,这对于二进制模块可以正确工作,并且永远不要相信它对于脚本模块也可以工作。如果您不确定,请对其进行测试或假设它无法正常工作。
我个人认为这是非常危险的,因为它会创建这样的场景:您向多个单独正常工作的模块添加 -WhatIf
支持,但当它们相互调用时却无法正常工作。
我们确实有一个 GitHub RFC 正在努力解决这个问题。有关更多详细信息,请参阅将执行首选项传播到脚本模块范围之外。
结束时
每次我需要使用它时,我都必须查找如何使用它。我花了很长时间才区分 ShouldProcess
和 ShouldContinue
。我几乎总是需要查找要使用哪些参数。因此,如果您仍然时不时感到困惑,请不要担心。当您需要时,这篇文章就会出现。我确信我自己会经常参考它。
如果您喜欢这篇文章,请使用下面的链接在 Twitter 上与我分享您的想法。我总是喜欢听到人们从我的内容中获得价值。
猜你还喜欢
- 03-30 [玩转系统] 如何用批处理实现关机,注销,重启和锁定计算机
- 02-14 [系统故障] Win10下报错:该文件没有与之关联的应用来执行该操作
- 01-07 [系统问题] Win10--解决锁屏后会断网的问题
- 01-02 [系统技巧] Windows系统如何关闭防火墙保姆式教程,超详细
- 12-15 [玩转系统] 如何在 Windows 10 和 11 上允许多个 RDP 会话
- 12-15 [玩转系统] 查找 Exchange/Microsoft 365 中不活动(未使用)的通讯组列表
- 12-15 [玩转系统] 如何在 Windows 上安装远程服务器管理工具 (RSAT)
- 12-15 [玩转系统] 如何在 Windows 上重置组策略设置
- 12-15 [玩转系统] 如何获取计算机上的本地管理员列表?
- 12-15 [玩转系统] 在 Visual Studio Code 中连接到 MS SQL Server 数据库
- 12-15 [玩转系统] 如何降级 Windows Server 版本或许可证
- 12-15 [玩转系统] 如何允许非管理员用户在 Windows 中启动/停止服务
取消回复欢迎 你 发表评论:
- 精品推荐!
-
- 最新文章
- 热门文章
- 热评文章
[影视] 黑道中人 Alto Knights(2025)剧情 犯罪 历史 电影
[古装剧] [七侠五义][全75集][WEB-MP4/76G][国语无字][1080P][焦恩俊经典]
[实用软件] 虚拟手机号 电话 验证码 注册
[电视剧] 安眠书店/你 第五季 You Season 5 (2025) 【全10集】
[电视剧] 棋士(2025) 4K 1080P【全22集】悬疑 犯罪 王宝强 陈明昊
[软件合集] 25年6月5日 精选软件22个
[软件合集] 25年6月4日 精选软件36个
[短剧] 2025年06月04日 精选+付费短剧推荐33部
[短剧] 2025年06月03日 精选+付费短剧推荐25部
[软件合集] 25年6月3日 精选软件44个
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电视剧] 欢乐颂.5部全 (2016-2024)
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[影视] 【稀有资源】香港老片 艺坛照妖镜之96应召名册 (1996)
[剧集] 神经风云(2023)(完结).4K
[剧集] [BT] [TVB] [黑夜彩虹(2003)] [全21集] [粤语中字] [TV-RMVB]
[实用软件] 虚拟手机号 电话 验证码 注册
[资源] B站充电视频合集,包含多位重量级up主,全是大佬真金白银买来的~【99GB】
[影视] 内地绝版高清录像带 [mpg]
[书籍] 古今奇书禁书三教九流资料大合集 猎奇必备珍藏资源PDF版 1.14G
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电影] 美国队长4 4K原盘REMUX 杜比视界 内封简繁英双语字幕 49G
[电影] 死神来了(1-6)大合集!
[软件合集] 25年05月13日 精选软件16个
[精品软件] 25年05月15日 精选软件18个
[绝版资源] 南与北 第1-2季 合集 North and South (1985) /美国/豆瓣: 8.8[1080P][中文字幕]
[软件] 25年05月14日 精选软件57个
[短剧] 2025年05月14日 精选+付费短剧推荐39部
[短剧] 2025年05月15日 精选+付费短剧推荐36部
- 最新评论
-
- 热门tag