此代码:
$concerningMachines = @()
foreach($aMachine in $machineRecords.GetEnumerator())
{
if($aMachine.Value.ReviewScore -gt $averageAboveAverage)
{
$machine = New-Object -TypeName PSObject
$machine | Add-Member -MemberType NoteProperty -Name MachineName -Value $aMachine.Key
$machine | Add-Member -MemberType NoteProperty -Name ManagedBy -Value $aMachine.Value.ManagedBy
$machine | Add-Member -MemberType NoteProperty -Name LastLogin -Value $aMachine.Value.LastLogin
$machine | Add-Member -MemberType NoteProperty -Name ReviewScore -Value ($aMachine.Value.ReviewScore / $averageAboveAverage * 100)
$concerningMachines += $machine
}
}
Export-Csv -InputObject $concerningMachines -Path C:\DG\ConcerningMachines.csv -NoTypeInformation
生成此 .csv 文件:
“计数”、“长度”、“LongLength”、“排名”、“SyncRoot”、“IsReadOnly”、“IsFixedSize”、“IsSynchronized” "43","43","43","1","System.Object[]","假","真","假"
...这是数组的属性,而不是数组的成员。谷歌搜索我发现的唯一建议似乎要么实现一个完全忽略 Export-Csv 的解决方案,正在处理字符串(虽然是字符集合,但解决方案不适用),或者似乎正在做我已经在做的事情,但是生成有效的 CSV 文件(如果需要,我可以找到一些链接,但它们是论坛对话,而不是明确的指南)。
如何正确地将 PSObject 数组导出到 CSV 文件中,并避免上述意外输出?
使用管道提供输入:
$concerningMachines| Export-Csv -Path C:\DG\ConcerningMachines.csv -NoTypeInformation
当您将相同的输入传递给
-InputObject
时,确实是整个数组被解释为要导出的单个对象。
此行为会影响所有 cmdlet,并且显然是按设计:
InputObject 是要处理的单个对象。当在管道中使用时,InputObject 绑定到管道中的每个元素并一次处理一个元素。如果 InputObject 作为一个集合进行处理,那么管道中的每个项目也将作为一个集合进行处理。
在某些 cmdlet 中,此行为很有用:例如,
Get-Member
允许您使用 -InputObject
来检查集合的类型 作为一个整体,而管道输入则检查 集合的每个元素。
Export-Csv
和ConvertTo-Csv
都不属于该类别,尽管Get-Help ExportCsv
目前误导性地描述了-InputObject
参数(已添加强调):
指定要导出为 CSV 字符串的对象s。 输入包含对象s的变量,或键入获取对象s的命令或表达式。您还可以通过管道将对象导出到 Export-CSV。
务实的结论是始终使用管道(除非你真的想将集合作为一个整体传递)。
有关此行为的一般讨论,请参阅GitHub 问题 #4242。
#looping the concerningMachines details to print in the excel cell
$concerningMachines | foreach { Add-Content -Path $FilePathLocation -Value $_ }