函数中 return 的 PowerShell 行为
PowerShell Behaviour for return from Function
我有一个简单的 CSV 文件。它包含 Header 和一些值。通常,如果 CSV 文件中有 2 个以上的条目,它就可以正常工作。如果只有 1 个条目(和 Header),它的行为对我来说非常意外。
function ImportServersToProcess($csv) {
begin {
[System.Collections.ArrayList] $aServers = @()
}
process {
$ImportedData = Import-CSV $csvPath -Delimiter ';' -Header 'Hostname','ServiceIP','AdminIP','IBRIP','HW','VMHW','OS','CPUs','RAM','DriveSizeC','DriveSizeD'
ForEach ($item in $ImportedData){
[System.Collections.Hashtable] $hServer = @{}
$hServer.Hostname = $($item.Hostname)
$hServer.ServiceIP = $($item.ServiceIP)
$hServer.AdminIP = $($item.AdminIP)
$hServer.IBRIP = $($item.IBRIP)
$hServer.HW = $($item.HW)
$hServer.VMHW = $($item.VMHW)
$hServer.OS = $($item.OS)
$hServer.CPUs = $($item.CPUs)
$hServer.RAM = $($item.RAM)
$hServer.DriveSizeC = $($item.DriveSizeC)
$hServer.DriveSizeD = $($item.DriveSizeD)
if ($hServer.Hostname -eq "Hostname") { continue } # Ignore 1st line/headers
$aServers.Add($hServer) | Out-Null # OutNull is used to prevent additonal add to array of unexpected object (also suprising output)
}
Write-Host "Test0 - " $aServers.Count
$aServers #| Out-Null
Write-Host "TEST1 - " $aServers.Count
}
end {
}
}
CSV 看起来像这样:
Hostname;ServiceIP;AdminIP;IBRIP;HW;VMHW;OS;CPUs;RAM;DriveSizeC;DriveSizeD
ash000126;1.1.1.191;2.2.2.223;3.3.3.223;System x;Virtual: 01_CL_01;Windows 2012 R2 ;4;16;200;300
ash000127;1.1.1.191;2.2.2.223;3.3.3.223;System x;Virtual: 01_CL_01;Windows 2012 R2 ;4;16;200;300
然后我运行脚本使用:
[System.Collections.ArrayList] $aServersToProcess = ImportServersToProcess($csvPath)
[int] $count = $($aServersToProcess.Count)
Write-Host -ForegroundColor Red "[*] There are $count servers to be checked. Starting up [*]"
屏幕上的输出是:
Test0 - 2
TEST1 - 2
[*] There are 2 servers to be checked. Starting up [*]
哪个好。 CSV 格式的 2 台服务器。 2 个计数。
现在,如果我从 CSV 中删除 1 个服务器,CSV 现在看起来像这样:
Hostname;ServiceIP;AdminIP;IBRIP;HW;VMHW;OS;CPUs;RAM;DriveSizeC;DriveSizeD
ash000126;1.1.1.191;2.2.2.223;3.3.3.223;System x;Virtual: 01_CL_01;Windows 2012 R2 ;4;16;200;300
注意没有空行等。
脚本的return是...
Test0 - 1
TEST1 - 1
[*] There are 11 servers to be checked. Starting up [*]
11从哪里来?
如果我修改脚本,在$aServers
后面加上$aServers.Count
Write-Host "Test0 - " $aServers.Count
$aServers
$aServers.Count
Write-Host "TEST1 - " $aServers.Count
输出是这样的:
Test0 - 1
TEST1 - 1
[*] There are 2 servers to be checked. Starting up [*]
11 来自 CSV 中 headers 的数量。这是一个问题,您得到的是单个 object,而 collection 在 csv 中有多个条目。
我认为这里最好的解决方案是将 $ImportedData 类型转换为一个数组,这样如果只有一个元素,它就会变成 collection,而不是 object。
$ImportedData = @(Import-CSV $csvPath -Delimiter ';' -Header 'Hostname','ServiceIP','AdminIP','IBRIP','HW','VMHW','OS','CPUs','RAM','DriveSizeC','DriveSizeD')
这是完成此任务的一种简单方法。另一种方式是:
[Collections.Generic.List[Object]]$ImportedData = Import-CSV $csvPath -Delimiter ';' -Header 'Hostname','ServiceIP','AdminIP','IBRIP','HW','VMHW','OS','CPUs','RAM','DriveSizeC','DriveSizeD'
编辑:
事实证明,问题实际上出在您的 return 中,当输出中只有一个 object 时,它被接收为单个哈希表,而不是哈希表数组。在 return 语句中使用逗号强制 return 作为 collection:
,$aServers #| Out-Null
刚刚看到有人在评论中打败了我。
我有一个简单的 CSV 文件。它包含 Header 和一些值。通常,如果 CSV 文件中有 2 个以上的条目,它就可以正常工作。如果只有 1 个条目(和 Header),它的行为对我来说非常意外。
function ImportServersToProcess($csv) {
begin {
[System.Collections.ArrayList] $aServers = @()
}
process {
$ImportedData = Import-CSV $csvPath -Delimiter ';' -Header 'Hostname','ServiceIP','AdminIP','IBRIP','HW','VMHW','OS','CPUs','RAM','DriveSizeC','DriveSizeD'
ForEach ($item in $ImportedData){
[System.Collections.Hashtable] $hServer = @{}
$hServer.Hostname = $($item.Hostname)
$hServer.ServiceIP = $($item.ServiceIP)
$hServer.AdminIP = $($item.AdminIP)
$hServer.IBRIP = $($item.IBRIP)
$hServer.HW = $($item.HW)
$hServer.VMHW = $($item.VMHW)
$hServer.OS = $($item.OS)
$hServer.CPUs = $($item.CPUs)
$hServer.RAM = $($item.RAM)
$hServer.DriveSizeC = $($item.DriveSizeC)
$hServer.DriveSizeD = $($item.DriveSizeD)
if ($hServer.Hostname -eq "Hostname") { continue } # Ignore 1st line/headers
$aServers.Add($hServer) | Out-Null # OutNull is used to prevent additonal add to array of unexpected object (also suprising output)
}
Write-Host "Test0 - " $aServers.Count
$aServers #| Out-Null
Write-Host "TEST1 - " $aServers.Count
}
end {
}
}
CSV 看起来像这样:
Hostname;ServiceIP;AdminIP;IBRIP;HW;VMHW;OS;CPUs;RAM;DriveSizeC;DriveSizeD
ash000126;1.1.1.191;2.2.2.223;3.3.3.223;System x;Virtual: 01_CL_01;Windows 2012 R2 ;4;16;200;300
ash000127;1.1.1.191;2.2.2.223;3.3.3.223;System x;Virtual: 01_CL_01;Windows 2012 R2 ;4;16;200;300
然后我运行脚本使用:
[System.Collections.ArrayList] $aServersToProcess = ImportServersToProcess($csvPath)
[int] $count = $($aServersToProcess.Count)
Write-Host -ForegroundColor Red "[*] There are $count servers to be checked. Starting up [*]"
屏幕上的输出是:
Test0 - 2
TEST1 - 2
[*] There are 2 servers to be checked. Starting up [*]
哪个好。 CSV 格式的 2 台服务器。 2 个计数。
现在,如果我从 CSV 中删除 1 个服务器,CSV 现在看起来像这样:
Hostname;ServiceIP;AdminIP;IBRIP;HW;VMHW;OS;CPUs;RAM;DriveSizeC;DriveSizeD
ash000126;1.1.1.191;2.2.2.223;3.3.3.223;System x;Virtual: 01_CL_01;Windows 2012 R2 ;4;16;200;300
注意没有空行等。
脚本的return是...
Test0 - 1
TEST1 - 1
[*] There are 11 servers to be checked. Starting up [*]
11从哪里来?
如果我修改脚本,在$aServers
后面加上$aServers.CountWrite-Host "Test0 - " $aServers.Count
$aServers
$aServers.Count
Write-Host "TEST1 - " $aServers.Count
输出是这样的:
Test0 - 1
TEST1 - 1
[*] There are 2 servers to be checked. Starting up [*]
11 来自 CSV 中 headers 的数量。这是一个问题,您得到的是单个 object,而 collection 在 csv 中有多个条目。
我认为这里最好的解决方案是将 $ImportedData 类型转换为一个数组,这样如果只有一个元素,它就会变成 collection,而不是 object。
$ImportedData = @(Import-CSV $csvPath -Delimiter ';' -Header 'Hostname','ServiceIP','AdminIP','IBRIP','HW','VMHW','OS','CPUs','RAM','DriveSizeC','DriveSizeD')
这是完成此任务的一种简单方法。另一种方式是:
[Collections.Generic.List[Object]]$ImportedData = Import-CSV $csvPath -Delimiter ';' -Header 'Hostname','ServiceIP','AdminIP','IBRIP','HW','VMHW','OS','CPUs','RAM','DriveSizeC','DriveSizeD'
编辑: 事实证明,问题实际上出在您的 return 中,当输出中只有一个 object 时,它被接收为单个哈希表,而不是哈希表数组。在 return 语句中使用逗号强制 return 作为 collection:
,$aServers #| Out-Null
刚刚看到有人在评论中打败了我。