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

[玩转系统] 如何创建 PowerShell 函数

作者:精品下载站 日期:2024-12-14 06:32:24 浏览:14 分类:玩电脑

如何创建 PowerShell 函数


当您需要多次重用脚本的一部分或需要运行仅具有不同值的相同代码时,您应该创建一个 PowerShell 函数。

PowerShell 函数不仅允许您轻松重用脚本的一部分,还为脚本提供结构。当事情无法正常工作时,这将使您的脚本更具可读性并且更易于调试。

在本文中,我们将了解如何创建 PowerShell 函数、使用参数、返回值,当然还有如何使用它们。

创建 PowerShell 函数

要创建函数,您需要为函数指定一个名称,后跟大括号。在这些括号内,您可以放置调用函数时要执行的脚本。

如何命名函数实际上非常重要。在 PowerShell 中,您需要使用批准的动词之一,后跟单数名词。两者都是用帕斯卡大小写编写的,其中每个单词的第一个字母大写。例如Add-UsersToGroup

要查看所有已批准动词的列表,您可以在 PowerShell 中运行 cmdlet Get-Verb,或查看 Microsoft 的文档。

例如,要创建一个向控制台(主机)写入内容的简单函数,我们可以创建以下函数:

function Write-SomethingToHost {
    Write-Host 'show something on screen'
}

使用参数

参数允许您将变量或对象传递给 PowerShell 函数,然后您可以在函数内部使用它们。如果您要创建一个小函数,则可以通过在函数名称后面的括号中添加变量来声明参数。

甚至可以通过这种方式声明多个参数,用逗号分隔它们。但这种方法其实并不推荐使用:

function Show-Something($test)
{
    Write-Host "show something on screen $test"
}

Show-Something -test "test"

在函数中使用参数的更好方法是使用参数块。参数块不仅更易于阅读,而且可以让您更好地控制参数。

在下面的示例中,我们在参数块中定义了要在函数中使用的两个变量:

function Show-Something{

    param(
        $number,
        $color
    )
    Write-Host "show number $number on the screen" -ForegroundColor $color
}

Show-Something -number 42 -color "green"

现在可以正常工作了,但是上面的例子有问题。如果您不指定颜色,那么脚本将抛出错误。此外,当您指定不存在的颜色时,您也会收到错误。

我们可以通过验证参数输入来防止这种情况。第一步是输入输入内容。这意味着我们将告诉我们期望参数的数据类型。使用的一些常见数据类型是:

  • [string] - 单引号或双引号中的简单字符串

  • [string[]] - 字符串数组(接受多个值)

  • [int] - 不带小数的整数

  • [float] - 带小数的浮点数

  • [bool] - 对或错

  • [array] - 值的集合

  • [hashtable] - 键值对的集合

  • [datetime] - 日期时间值

  • [对象] - .NET 对象

因此,对于上面的示例,我们期望两个变量都是字符串:

function Show-Something{

    param(
        [int]$number,
        [string]$color
    )
    Write-Host "show number $number on the screen" -ForegroundColor $color
}

Show-Something -number 42 -color "green"

验证参数

但仅靠打字并不总是足够的。如果我们查看颜色变量,该参数现在接受您向其抛出的每个字符串。唯一的问题是您可以使用的颜色有限。

因此,我们需要验证赋予一组可能值的字符串。为此,我们可以使用参数验证。在这种情况下,我们将针对一组值进行验证,如下所示:

[ValidateSet("Green", "Red", "Yellow", "Blue")]
[string]$color

但验证参数的其他常见选项是:

  • [ValidateRange(1, 100)] - 验证数字范围

  • [ValidateLength(1, 10)] - 验证字符串参数的长度

  • [ValidatePattern(“[A-Za-z]+”)] - 根据正则表达式模式验证值

  • [ValidateNotNullOrEmpty()] - 确保参数不为 null 或为空

  • [ValidateScript({ $_ -gt 0 })] - 使用自定义脚本块验证参数

因此,对于我们的示例函数,我们可以使用以下两个验证:

function Show-Something{

    param(
        [ValidateRange(1, 100)]
        [int]$number,
        [ValidateSet("Green", "Red", "Yellow", "Blue")]
        [string]$color
    )
    Write-Host "show number $number on the screen" -ForegroundColor $color
}

Show-Something -number 42 -color "green"

强制参数

PowerShell 函数中参数的另一个常见问题是空值。有时您的脚本确实需要一个值才能执行脚本。在这些情况下,您可以通过添加 [Parameter(Mandatory=$true)] 来强制该参数。

例如,如果您不提供数字,下面的函数将不起作用。为了防止这种情况,我们可以强制该参数:

function Get-Square {
    param(
        [Parameter(Mandatory=$true)] 
        [int]$number
    )

    $Number * $Number
}

如果您想为参数定义默认值,那么您也不能将其强制执行。您可以向其添加 [ValidateNotNullOrEmpty()] 验证属性,但在我看来,这是毫无意义的,因为参数总是会回退到默认值。

返回结果

在 PowerShell 中,return 关键字用于退出函数并向函数调用者返回一个值。但是,可以选择在 PowerShell 函数中使用 return。如果不使用 return 关键字,则函数将返回最后一个表达式的值。

在下面的示例中,不需要使用 return 关键字。最后一个表达式 $InputString.ToUpper() 的结果由函数自动返回:

function ConvertTo-Uppercase {
    param (
        [Parameter(Mandatory=$true)]
        [string]$InputString
    )

    $InputString.ToUpper()
}

ConvertTo-Uppercase -InputString "hello world"

但是,return 可以显式地用于提前退出函数或返回特定值,而不管最后一个表达式如何。

当函数中遇到return时,该函数立即存在。函数中的其余代码将不会被执行。当满足特定条件时这可能很有用,例如:

function Test-Return {
    param (
        [Parameter(Mandatory=$true)]
        [int]$number
    )
    if ($number -gt 5) {
        Write-Output "Number is greater than 5"
        return "Exiting function early"
    }
    # This code will not be executed if $number is greater then 5
    Write-Output "This line will not be printed"
}

Test-Return -number 42

[玩转系统] 如何创建 PowerShell 函数

通话功能

要在 PowerShell 中调用函数,您需要记住,您需要先声明该函数,然后才能调用它。因此,您的函数位于脚本的顶部,并在其下方调用它们。

调用函数时,您只需键入函数名称。如果函数有参数,则只需键入参数名称,后跟要分配给它的变量或值。

对于参数,不需要使用参数名称,但最佳实践是也使用名称。这将使您的代码更易于阅读。

function Show-Something{

    param(
        [ValidateScript({ $_ -gt 0 })]
        [int]$number,
        [ValidateSet("Green", "Red", "Yellow", "Blue")]
        [string]$color
    )
    Write-Host "show number $number on the screen" -ForegroundColor $color
}

# This will work, but is not recommended
Show-Something 42 "blue"

# Use the parameter names instead
Show-Something -number 42 -color "Blue"

高级PowerShell功能

到目前为止,我们已经了解了如何创建基本的 PowerShell 函数。除了基本功能外,PowerShell 中还有高级功能。高级函数的原理是一样的,不同的是高级函数会自动分配一些常用参数,如 VerboseDebug ErrorAction 等等。

要将函数变成高级函数,只需在函数中添加[CmdletBinding()]即可。

function ConvertTo-Uppercase {
    [CmdletBinding()]  # < This makes it an advanced function
    param (
        [Parameter(Mandatory=$true)]
        [string]$InputString
    )

    $InputString.ToUpper()
}

值得高兴的是,当您将函数转变为高级函数时,您还需要包含 param 块。即使你没有任何参数。

启用高级功能后,您现在可以在函数中使用诸如 Write-Verbose 之类的功能。

function ConvertTo-Uppercase {
    [CmdletBinding()]  # < This makes it an advanced function
    param (
        [Parameter(Mandatory=$true)]
        [string]$InputString
    )
    Write-Verbose "Converting string $InputString to uppercase"
    $InputString.ToUpper()
}

现在,我们可以使用或不使用 -Verbose 来调用函数,以显示函数中发生的情况:

[玩转系统] 如何创建 PowerShell 函数

管道输入

要在管道中使用函数,您需要声明哪些参数接受管道中的值。有两个选项,您可以使用 ValueFromPipeline (它接受最适合数据类型的值),或使用 ValueFromPipelineByPropertyName (它允许您匹配参数的名称) 。

此外,当您想在管道中使用函数时,您至少需要向函数添加一个 process 块。

因此,当您使用 ValueFromPipeLine 时,您只能通过管道将一个字符串传递到您的函数。我们以下面的函数为例:

function ConvertTo-StyledProcesses {
    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline=$true)]
        [string]$Name
    )

    process {
        Write-Host "Process name is $($Name.ToUpper())"
    }
}

如果我们通过管道将函数放在 Get-Service cmdlet 后面,并仅选择 Name 属性,那么我们可以将进程名称转换为大写:

[玩转系统] 如何创建 PowerShell 函数

但是如果我们想将状态也包含在结果中怎么办?假设我们想根据服务是否正在运行来为状态指定颜色。如果您查看下面的函数,您可能会认为这可行,但问题是,我们尚未定义服务属性应如何映射到参数。

function ConvertTo-StyledProcesses {
    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline=$true)]
        [string]$Name,

        [Parameter(ValueFromPipeline=$true)]
        [string]$Status
    )

    process {
        $color = "Green"

        if ($Status -eq "Stopped") {
            $color = "Red"
        }

        Write-Host "Process $Name is " -NoNewline
        Write-Host $Status -ForegroundColor $color
    }
}

因此,如果我们像这样运行它,那么 name 和 status 属性都将被解析为 name 和 status 参数:

[玩转系统] 如何创建 PowerShell 函数

为了解决这个问题,我们需要使用 ValueFromPipelineByPropertyName 选项。这样我们就可以自动将属性映射到正确的参数:

function ConvertTo-StyledProcesses {
    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipelineByPropertyName=$true)]
        [string]$Name,

        [Parameter(ValueFromPipelineByPropertyName=$true)]
        [string]$Status
    )

    process {
        $color = "Green"

        if ($Status -eq "Stopped") {
            $color = "Red"
        }

        Write-Host "Process $Name is " -NoNewline
        Write-Host $Status -ForegroundColor $color
    }
}

[玩转系统] 如何创建 PowerShell 函数

开始、过程、结束

除了函数内部的 process 块之外,我们还可以有 begin 和 end 块。 begin 和 end 块仅在调用函数时执行一次。它们是可选的,并且使用得不多,但在某些情况下,它可能很有用。

例如,下面的函数将根据商品的数量和商品价格计算商品的总价。它还将计算所有商品的总价:

function Get-TotalPrice {
    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline=$true)]
        [ValidateNotNull()]
        [pscustomobject]$Item
    )

    begin {
        $totalPrice = 0
    }

    process {
        $quantity = $Item.Quantity
        $unitPrice = $Item.UnitPrice

        $totalItemPrice = $quantity * $unitPrice
        $totalPrice += $totalItemPrice

        # Outputting each item's total price
        [PSCustomObject]@{
            Item = $Item.Name
            TotalPrice = $totalItemPrice
        }
    }

    end {
        Write-Output "Overall Total Price: $totalPrice"
    }
}

您可以使用以下示例运行/尝试上面的脚本:

# Define items
$item1 = [pscustomobject]@{
    Name = "Product A"
    Quantity = 3
    UnitPrice = 10
}

$item2 = [pscustomobject]@{
    Name = "Product B"
    Quantity = 2
    UnitPrice = 15
}

# Calculate total price
$item1, $item2 | Get-TotalPrice

# Result
Item      TotalPrice
----      ----------
Product A         30
Product B         30
Overall Total Price: 60

包起来

PowerShell 函数是重用脚本中的代码段并为脚本提供结构的好方法。尽量让你的函数保持较小的规模,让它们只执行一项任务。

命名函数时,请确保仅使用认可的动词,以使其他人易于理解您的函数。另外,请确保使用唯一的名称。

我希望这篇文章对您有所帮助,如果您有任何疑问,请在下面发表评论。

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

取消回复欢迎 发表评论:

关灯