我试图有一个函数,可以根据我将传递参数的LatestStatus值计算作业。到目前为止我得到的是:
Function JobCountStatus {
Write-Output (Get-VBRJob | ?{$_.Info.LatestStatus -eq $args} | Measure-Object).Count
}
问题是,正如我在某处读到的,将有一个子shell(?)执行where,所以参数没有传递。
如果我将$args替换为一个特定的字符串,如"Failed"会成功的。
有办法克服这个吗?我不想为所有可能的值编写单独的函数。
我将感谢任何评论-谢谢
您可以在运行函数时将值命名为$args
是一个自动变量
JobCountStatus "Failed"
您可以使用带参数的高级函数,无论是否命名:
function JobCountStatus {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true, Position = 0)]
[System.String]
$Status
)
Process {
(Get-VBRJob | Where-Object { $_.Info.LatestStatus -eq $Status } | Measure-Object).Count
}
}
然后这样命名:
JobCountStatus -Status "Failed"
# OR
JobCountStatus "Failed"
后者与仅使用$args
具有相同的最终结果。在这里指定自己的参数的唯一可能的好处是,您可以定义状态的ValidateSet或状态值的Enum,以便您可以通过选项卡浏览它们。前者的一个示例如下:
function JobCountStatus {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true, Position = 0)]
[ValidateSet("Failed", "Running", "Successful", "Unknown")]
[System.String]
$Status
)
Process {
(Get-VBRJob | Where-Object { $_.Info.LatestStatus -eq $Status } | Measure-Object).Count
}
}
$args
是一个数组,不是单个值。在任何情况下,ScriptBlock
{}
是一个未命名的函数,$args
在它里面有它自己的含义,所以你不能在像Where-Object
这样的东西里做一些修改。您必须将$args
的元素存储为另一个变量或多个变量,以便在子ScriptBlock
中引用。对于这个函数来说,这不是一个很大的变化,但是对于一个需要更多参数的函数来说,这可能会导致大量不必要的代码,难以维护。
我更倾向于建议在大多数情况下定义命名参数,这将是一个更简单的更改,比使父$args
在子ScriptBlock
中工作:
Function JobCountStatus {
Param(
[string]$Status
)
( Get-VBRJob | Where-Object { $_.Info.LatestStatus -eq $Status } ).Count
}
我还对这个函数做了一些修改,我将在下面解释:
- 使用
Param()
通过名称强定义参数。您可以使用更简单的function JobCountStatus([string]$Status) {}
语法,但对于这种情况,使用哪种技术实际上是一个首选问题。我推荐使用Param()
作为惯例,但是您需要使用任何一种技术来获得命名参数。 - 我用
$Status
替换了$args
参考。 你对 - 你可以使用
?
,如果你想,但它被认为是省略别名和使用完整的cmdlet名称在脚本和模块的最佳实践,所以我已经取代了?
与Where-Object
。
Measure-Object
的使用是无关的,所以我已经删除了它。Where-Object
返回一个已经具有Count
属性的集合。请注意,您可以调用函数/cmdlet(对于powershell定义的cmdlet,差异是最小的)有或没有参数,因为当您不定义位置顺序时,顺序将按照声明的顺序自动确定:
# Either will work
JobCountStatus -Status Running
JobCountStatus Running
下面是一些你可能会觉得有用的文档:
<<ul>@Ash的回答给出了一些更高级的例子,说明你可以用param()
做些什么,这些例子在上面的高级函数链接中提到。您不能将高级参数属性与我在第一个要点中提到的简单函数语法一起使用。