我正在尝试创建一个脚本,该脚本接受来自我无法控制的许多不同第三方来源的各种形式的计算机列表。这些不同的源有时将计算机作为简单的字符串数组返回,有时作为Powershell对象,有时作为哈希。我希望我的脚本能够获取这些类型的列表并获取计算机名称,并将其放入数组中。然后执行实际处理。
以下是我尝试创建的脚本中可能提供的一些数据示例。
@('system-01','system-02') | \\path\share\mycommand.ps1
@(@{"ComputerName" = "system-01";OtherKey = 'foo'},
@{"ComputerName" = "system-02";OtherKey = 'foo'}) | \\path\share\mycommand.ps1
@([PSCustomObject]@{
ComputerName = 'system-01'
OtherProperties = 'foo'
},
[PSCustomObject]@{
ComputerName = 'system-02'
OtherProperties = 'foo'
}) | \\path\share\mycommand.ps1
我的脚本目前看起来像。
[CmdletBinding()]
param(
[Parameter(Mandatory=$True,
ValueFromPipeline=$True,
ParameterSetName="ComputerHash")]
[hashtable]$ComputerHash,
[Parameter(Mandatory=$True,
ValueFromPipeline=$True,
ParameterSetName="ComputerArray")]
[String[]]$ComputerName,
[Parameter(Mandatory=$True,
ValueFromPipeline=$True,
ParameterSetName="ComputerObject")]
[Object[]]$ComputerObjects
)
BEGIN
{
# create an empty array to build up a list of the computers
$computers=@()
}
PROCESS
{
# get all the computers from the pipeline
switch ($PsCmdlet.ParameterSetName)
{
"ComputerArray" { $computers+=$ComputerName; break}
"ComputerHash" { $computers+=$ComputerHash.ComputerName; break}
"ComputerObject"{ $computers+=$ComputerObjects.ComputerName; break}
}
}
END
{
$computers | % {
# do the stuff
"Do something on $_"
}
}
很遗憾,我目前收到Parameter set cannot be resolved ...
错误。如何使我的脚本基本上接受任何类型的管道输入,然后做正确的事情?我应该使用一些更简单的方法吗?
答案 0 :(得分:4)
你可以做的,而不是制作不同的参数集,只是在你得到信息后处理它。如下所示:
[CmdletBinding()]
param(
[Parameter(Mandatory=$True,
ValueFromPipeline=$True)]
$ComputerList
)
BEGIN
{
# create an empty array to build up a list of the computers
$computers=Switch($ComputerList.GetType()){
{$_.Name -eq 'Hashtable'}{$ComputerList.ComputerName;Continue}
{$ComputerList -is [Array] -and $ComputerList[0] -is [String]}{$ComputerList;Continue}
{$ComputerList -is [Array] -and $ComputerList[0] -is [Object]}{$ComputerList.ComputerName}
}
}
PROCESS
{
}
END
{
$computers | % {
# do the stuff
"Do something on $_"
}
}
或者甚至更容易:
BEGIN{$Computers=If($ComputerList[0] -is [String]){$ComputerList}Else{$ComputerList.ComputerName}}
编辑:正如所指出的,我们没有在BEGIN或END块中获取管道数据,所以我的想法有效,但我的脚本没有。相反,我们必须像Zoredache所说的那样在PROCESS块中做一些事情。他已经发布了他的代码,我确信它的功能非常好,但我想我会发布一个修改过的版本,所以我的答案不会继续出错,因为,好吧,我不喜欢错误的答案在那里。
Function Test-Function1{
[CmdletBinding()]
param(
[Parameter(Mandatory=$True,
ValueFromPipeline=$True)]
$ComputerList
)
BEGIN
{
}
PROCESS
{
[string[]]$computers+=Switch($ComputerList){
{$_ -is [Hashtable]}{$_.ComputerName;Continue}
{$_ -is [String]}{$_;Continue}
{$_ -is [Object]}{$_|Select -Expand Computer*}
}
}
END
{
$computers | % {
# do the stuff
"Do something on $_"
}
}
}
然后当我将数据传输到它时:
@{'ComputerName'='Server1','Server2'}|Test-Function1
[pscustomobject]@{'Computer'='Server1'},[pscustomobject]@{'ComputerName'='Server2'}|Test-Function1
'Server1','Server2'|Test-Function1
他们都回应了预期的输出:
Do something on Server1
Do something on Server2
答案 1 :(得分:1)
[CmdletBinding()]
param(
[Parameter(Mandatory=$True,
ValueFromPipeline=$True)]
$PipelineItem
)
BEGIN
{
$ComputerList=@()
}
PROCESS
{
$ComputerList+=
Switch($PipelineItem.GetType()) {
{$_.Name -eq 'String'}
{$PipelineItem}
{$_.Name -eq 'Hashtable'}
{$PipelineItem.ComputerName}
{$_.Name -eq 'PSCustomObject' -and (Get-Member -MemberType Properties -Name "Computer" -InputObject $PipelineItem)}
{$PipelineItem.Computer}
{$_.Name -eq 'PSCustomObject' -and (Get-Member -MemberType Properties -Name "ComputerName" -InputObject $PipelineItem)}
{$PipelineItem.ComputerName}
}
}
END
{
$ComputerList | % {
# do the stuff
"Do something on $_"
}
}