当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] PowerShell高级功能

作者:精品下载站 日期:2024-12-14 08:10:02 浏览:12 分类:玩电脑

PowerShell高级功能


[玩转系统] PowerShell高级功能

PowerShell 高级功能提供将简单 PowerShell 脚本扩展为行为类似于本机 PowerShell cmdlet 的工具的功能。 PowerShell 高级功能允许常规脚本利用本机 cmdlet 可用的同一组功能。

PowerShell 高级功能建立在四个支柱之上。

  1. 码流控制
  2. 参数验证
  3. 管道绑定
  4. 保障措施

在接下来的几节中,我们将更详细地讨论这些内容。

码流控制

PowerShell引擎提供了许多流,可用于根据上下文发送不同的消息。

  1. 输出/成功
  2. 错误
  3. 警告
  4. 冗长
  5. 调试

根据上下文,我们可以利用内置的 cmdlet 写入特定的流,例如,如果我们想写入详细流,我们可以使用 Write-Verbose cmdlet 等。

然而,正如我们在图 1 中观察到的那样,仅使用正确的 cmdlet 是不够的。

[玩转系统] PowerShell高级功能

图 1:尝试使用 Verbose 流的常规函数

为了使 -Verbose 开关正常工作,我们需要更改函数并添加 CmdletBinding,如以下示例所示:

Function Do-SomethingRegular{
		[CmdletBinding()]
		param(
				[String]$Message
		)
		Write-Verbose "We are going to write the message by the User"
		Write-Output $Message
}
Do-SomethingRegular -Message "Hi Mom" -Verbose

CmdletBinding 属性公开了 PowerShell 引擎提供的许多功能。可以说 CmdletBinding 属性使我们的功能更加先进。正如我们现在在图 2 中可以观察到的,我们的函数正确写入了详细流。

[玩转系统] PowerShell高级功能

图 2:向函数添加 CmdletBinding 属性导致函数正确写入详细流

接下来,我们看一个涉及错误流的更复杂的示例。我们首先需要定义终止错误和非终止错误之间的区别:

  • 终止错误是致命错误,它将停止程序的执行。
  • 非终止错误不太严重,不会导致程序的执行停止。

如果 PowerShell 引擎遇到非终止错误,它首先检查 ErrorActionPreference 变量的值以确定是否应该继续或终止执行。默认情况下,该值设置为“继续”,这意味着如果 PowerShell 引擎遇到错误,那么它应该继续处理脚本的其余部分。

我们可以在图 3 中观察到这种行为:当 PowerShell 引擎遇到非终止错误时,它会生成一条错误消息并继续执行脚本的其余部分。

[玩转系统] PowerShell高级功能

图 3:PowerShell 引擎在遇到非终止错误后继续执行脚本

但是,如果我们想在遇到非终止错误时立即终止脚本怎么办?
解决方案是将 ErrorActionPreference 变量的值修改为“Stop”。

但是,更改此变量将影响系统上的所有其他脚本,并且这是一个全局变量。解决方案是使用 -ErrorAction 开关,如图 4 所示,并告诉 PowerShell 引擎将我们的脚本视为“ErrorActionPreference”变量被设置为停止。同样,我们使用 ErrorAction 开关的原因是我们正在使用高级功能。

[玩转系统] PowerShell高级功能

图 4:ErrorAction 开关与“Stop”选项相结合,导致 PowerShell 在遇到错误时终止执行

参数验证

函数除非可以接受参数,否则没有多大用处。帮助函数是一个不同的故事,但我们的重点是常规函数。

因此,在我们开始将提供的参数用于编程逻辑之前,参数验证是一个非常重要的过程。 PowerShell引擎提供了许多内置机制来验证参数。高级函数可以帮助我们利用此功能来验证我们的参数,而不是编写我们自己的参数验证逻辑。

在本节中,我们将讨论一些参数验证技术,但此列表绝不是详尽无遗的。

1. 必选参数

强制参数有助于根据函数的需要声明某些参数。如果该值缺失,PowerShell 引擎将提示用户输入值(如图 5 所示)。这是一个例子:

# Writing a function with a mandatory parameter
Function Do-SomethingRegular {
		[CmdletBinding]()]
		Param(
				[Parameter(Mandatory)]
				[String] $Message
		)
		Write-Output $Message
}

# Calling the function
Do-SomethingRegular

[玩转系统] PowerShell高级功能

图 5:将参数声明为强制参数

2. 验证脚本

ValidateScript 可用于根据提供的参数值运行脚本。如果脚本返回$true,则参数值被接受。这是一个例子:

Function Simple-Function {
		[CmdletBinding()]
		param(
				[Parameter(Mandatory)]
				[ValidateScript({Test-Connection -ComputerName $_ -Quiet -Count 1})]
				[string]$computerName
		)
		$ErrorActionPreference
		Get-CimInstance -ClassName win32_Process -ComputerName $ComputerName
}

Simple-Function -ComputerName 'CAT'

正如我们在图 6 中所观察到的,我们使用 ValidateScript 来测试是否可以访问用户作为 ComputerName 参数提供的机器。该脚本使用 Test-Connection cmdlet-Quiet 标志来返回 true 或 false。由于我们的实验室没有名为“CAT”的计算机,因此它返回 false 并且验证脚本无法接受参数值。

[玩转系统] PowerShell高级功能

图 6:使用 ValidateScript 参数验证 PowerShell 脚本

3. 验证模式

ValidatePattern 可用于根据正则表达式验证参数值。这是一个例子:

Function Do-SomethingRegular {
[CmdletBinding()]
Param(
[Parameter(Mandatory)]
[ValidatePattern('\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(.|$)){4}\b')]
[String] $MachineName
)
Get-CimInstance -ComputerName $MachineName -ClassName win32_Process
}
Do-SomethingRegular -MachineName 127.0.01.1

[玩转系统] PowerShell高级功能

图 7:根据正则表达式验证提供的参数值

4.验证集

ValidateSet 可用于预定义可接受的参数值(如图 8 所示)。如果用户提供的值不是预定义的,则该函数将返回错误。这是一个例子:

Function Do-SomethingRegular{
		[CmdletBinding()]
		Param(
				[Parameter(Mandatory)]
				[ValidateSet('Mom','Dad')]
				[String] $Parent
		)
		Write-Output "Hello " $Parent
}

Do-SomethingRegular -Parent

[玩转系统] PowerShell高级功能

图 8:使用 ValidateSet 预定义可接受的参数值

如前所述,PowerShell 提供了许多参数验证技术,但是,本文仅介绍了其中的一些技术。有关更多详细信息,请阅读 Bruno Buyck 关于 PowerShell 和 ScriptRunner 中的参数验证概念的文章,有关完整列表,请阅读 Microsoft PowerShell 官方文档。

管道绑定

参数管道绑定是 PowerShell 中最重要的概念之一。本节将仅关注如何使参数能够接受 Pipeline 输入。有关更多详细信息,请访问我关于 PowerShell 中的参数绑定概念的另一篇文章。

PowerShell引擎“按值”或“按属性”绑定管道输入。高级功能允许我们指定哪些参数可以接受管道输入以及如何进行绑定。

让我们举一个简单的例子,我们接受管道输入byValue

Function Do-SomethingRegular{
		[CmdletBinding()]
		Param(
				[Parameter(Mandatory,valueFromPipeline)]
				[String] $name
		)
		Write-Output "You Entered $name"
}
"Sonny"|Do-SomethingRegular

图 9 显示了一个字符串对象被传递给我们的函数,并且由于该函数有一个参数接受来自管道的值,因此函数的执行没有任何错误。

[玩转系统] PowerShell高级功能

图 9:通过管道将字符串对象作为参数值传递给函数

同样,我们可以修改函数以接受管道输入byProperty:

Function Do-SomethingRegular{
		[CmdletBinding()]
		Param(
				[Parameter(Mandatory,valueFromPipelineByProperty)]
				[String] $name
		)
		Write-Output "You Entered $name"
}
$MyNewObject = [PSCustomObject]@{name = 'Sonny'; age = 21}
$MyNewObject | Do-SomethingRegular

如图 10 所示,我们创建了一个属性名称与参数名称匹配的对象。当此对象在管道中传递时,PowerShell 引擎会将该属性与参数绑定,因为它们具有匹配的名称。

[玩转系统] PowerShell高级功能

图 10:通过管道将对象的单个属性作为参数值传递给函数

让我们通过在管道中传递多个对象来使我们的示例复杂化。由于我们正在处理多个对象,因此我们需要利用输入处理方法。输入处理方法也称为 BEGINPROCESSEND 块。优秀的 PowerShell 程序员在编写高级函数时总是会使用它们。

正如我们在图 11 中所观察到的,即使有多个对象,绑定也遵循与前面的示例相同的原则:

Function Do-SomethingRegular{
		[CmdletBinding()]
		Param(
				[Parameter(Mandatory,valueFromPipelineByPropertyName)]
				[String] $name
		)
		process{
		Write-Output "You Entered $name"
		}
}

$MyNewObject1 = [PSCustomObject]@{name = 'Sonny';age = 21}
$MyNewObject2 = [PSCustomObject]@{name = 'browninfosecguy';age = 21}
$MyNewObject1,$MyNewObject2|Do-SomethingRegular

[玩转系统] PowerShell高级功能

图 11:通过管道将多个对象的一个属性作为参数值传递给函数

保障措施

PowerShell 提供了两种内置的保护机制。

  • 如果什么
  • 确认

这些保护措施由两个系统变量$WhatIfPreference$ConfirmPreference控制。这两个变量的默认值如图 12 所示。

[玩转系统] PowerShell高级功能

图12:WhatIf 和Confirm Preference 变量的默认值

如果什么

WhatIf 开关可用于查看“会发生什么”,而无需真正修改任何内容。该行为由 $WhatIfPreference 变量控制。
$WhatIfPreference 的默认值设置为 false,这就是为什么当我们执行任何 cmdlet 时,我们没有显示假设场景。为了查看 whatif 场景,我们需要显式使用 whatif 开关,如图 13 所示。

[玩转系统] PowerShell高级功能

图 13:PowerShell 中的 -WhatIf 开关示例

在函数中实现 WhatIf 功能可以通过以下方式实现:

  1. SupportsShouldProcess 参数添加到 CmdletBinding,如图 14 所示
  2. 捕获$PSCmdlet.ShouldProcess(“ ”)返回的布尔值,如果为TRUE则表示用户没有选择whatif选项
  3. 将 Whatif 逻辑置于围绕 $PSCmdlet.ShouldProcess(“ ”) 的 if 循环中

以下示例演示了这些步骤:

Function Delete-Windows{
# First we're adding the “SupportsShouldProcess” argument to CmdletBinding
		[CmdletBinding(SupportsShouldProcess)]
		param(
		)
# Then, we're capturing the Boolean value returned by “$PSCmdlet.ShouldProcess("")”, If TRUE it means user has not selected whatif option
		if($PSCmdlet.ShouldProcess("Meow")){
				Write-Host "WhatIf flag not set, delete windows"
		}
		else{
				Write-Host "WhatIf flag set, do not delete windows or real"
		}
}

[玩转系统] PowerShell高级功能

图 14:在函数中实现 WhatIf 功能

确认

Confirm 开关可用于在执行 cmdlet 之前提示用户进行确认。我们可以在我们的函数中实现相同的功能。如前所述,如果 $ConfirmPreference 变量设置为“high”,则将 ConfirmImpact 变量设置为“high”的 cmdlet 将在执行前提示用户确认。

这给我们带来了另一个概念,$ConfirmImpact变量,用于定义函数的严重性。它可以接受以下值:

  • “低的 ”
  • “中等的 ”
  • “高的 ”

我们也可以将其设置为“无”,但这只会禁用它。

为了在我们的函数中实现 confirm,我们需要将 ConfirmImpact 参数添加到 CmdletBinding 并为其初始化一个值。然后,PowerShell 引擎会将此值与 $ConfirmPreference 值进行比较,如果我们的函数的严重性相同或更高,则会提示用户确认对话框。这是一个例子

Function Delete-Windows{
		[CmdletBinding(SupportsShouldProcess, ConfirmImpact = "Medium")]
		param(
		)
		if($PSCmdlet.ShouldProcess("Meow"){
		Write-Host "Delete Windows"
		}		
}

正如我们在图 15 中可以观察到的,由于 $ConfirmPreference 设置为“高”,PowerShell 引擎没有提示用户确认对话框,因为我们的函数具有“中”

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯