Powershell 将哈希表值属性导出到CSV文件

Powershell 将哈希表值属性导出到CSV文件,powershell,csv,hashtable,Powershell,Csv,Hashtable,我正在运行AdfsServerHealth测试 问题是,其中一个输出值value name output是一个显示为System.Collection.Hashtable的数组,我正试图找到一种方法,以简洁的Excel格式获取它 例如,这是我导出时CSV上的一个实际值: Name Result Detail Output TestServiceAccountProperties Pass "" System.Collections.Hashtable 这不会有太大的困难,只

我正在运行AdfsServerHealth测试

问题是,其中一个输出值value name output是一个显示为System.Collection.Hashtable的数组,我正试图找到一种方法,以简洁的Excel格式获取它

例如,这是我导出时CSV上的一个实际值:

Name Result Detail Output TestServiceAccountProperties Pass "" System.Collections.Hashtable
这不会有太大的困难,只是会很烦人。之所以要获取System.collections.hashtable,是因为无法以这样的单一格式显示该属性中的所有内容,所以有办法获取大量信息。您必须创建另一个对象,并在其中放入您想要的任何信息

这个问题不会完全像你想要的那样工作,但是经过一些调整,它应该会让你达到目的

$ServerResult = Test-ADFSServerHealth
$Object = New-PSObject -Property @{
    'Name' = $ServerResult.name
    'Result' = $ServerResult.Result
    'Detail' = $ServerResult.Detail
    'Output' = ($ServerResult.Output | out-string -stream)
    'ExceptionMessage' = $ServerResult.ExceptionMessage

    }
如果您感兴趣,这里是我用来寻找这个答案的资源。 tl;博士:

上面将每个.Output哈希表的条目序列化为单行字符串,该字符串由空格分隔=对PSv4+语法组成,该语法在CSV输出中应能正常工作

由于CSV是文本格式,PowerShell通过调用要导出的对象的.ToString方法来序列化这些对象

复杂对象(如[hashtable]实例)通常只生成其完整类型名称System.Collections.hashtable for.ToString,这在CSV中不有用

我正在使用ConvertTo Csv的一个简化示例,但该示例同样适用于导出Csv:

如果Test AdfsServerHealth的所有输出对象在其.output属性中都具有相同的哈希表结构,则可以尝试通过使哈希表的条目列位于它们自己的右侧来展平哈希表,但听起来情况并非如此

因此,必须手动将哈希表转换为适合单个CSV列的文本表示形式:

可以使用“选择对象”和为您执行转换的“计算属性”来执行此操作,但需要确定在CSV文件上下文中有意义的文本表示形式

在下面的示例中,创建了由空格分隔=对组成的单行字符串PSv4+语法

[pscustomobject] @{ prop1 = 1; Output = @{ name='foo'; ID=666 } } | 
  Select-Object prop1, @{ 
    n='Output'
    e={ $_.prop2.GetEnumerator().ForEach({ '{0}={1}' -f $_.Key, $_.Value }) -join ' ' } 
  } | ConvertTo-Csv
有关创建Computed prop2属性的哈希表格式的说明,请参阅我的

上述收益率:

"prop1","prop2"
"1","ID=666 name=foo"
但是,请注意,如果哈希表中的值再次是仅序列化为其类型名的复杂对象,则必须递归地应用该方法

可选阅读:将哈希表属性展平为单个列 如果要导出到CSV文件的对象的哈希表值属性都具有相同的结构,则可以选择使每个哈希表条目都具有自己的输出列

让我们以以下示例输入为例:一个由2个自定义对象组成的集合,其.prop2值是一个具有统一密钥项集的哈希表:

$coll = [pscustomobject] @{ prop1 = 1; prop2 = @{ name='foo1'; ID=666 } },
        [pscustomobject] @{ prop1 = 2; prop2 = @{ name='foo2'; ID=667 } }
如果您预先知道感兴趣的键名称,只需使用计算属性的显式列表来创建各个列:

上述结果显示,哈希表条目变成了它们自己的列、名称和ID:

如果您事先不知道密钥名称,则需要更高级的技术:


这将产生与上一个命令相同的输出,并具有固定的计算属性列表。

我想我已经接近解决方案了。设法将代码重新写入如下内容:`$ServerResult | select Name,@{Name=OutputResult;Expression={$\输出| Out String-Stream}}}导出csv$outputfilename`结果截断字段中的一些属性:@mutukrp:您将得到一个带有Out String的多行填充控制台窗口宽度表示;实际上,将其转换为合理的单行表示法并不重要,因此最好将条目逐个转换为字符串,就像我的回答中那样,这也让您对格式有了更多的控制。顺便说一句:使用Out String-Stream实际上在这里的属性输出中创建了一个字符串数组,然后将其序列化为字符串System.Object[]并导出Csv;只需省略-Stream即可获得一个多行字符串表示形式。非常好!我之前确实尝试过$\ GetEnumerator方法,但我想我一定是做错了什么。我本想回到这里说,嘿,我以前也这么做过,但没有用的是当我注意到你的Tl;博士复制了代码,根据我的要求做了一些修改,然后粘贴了一张——瞧!!我需要什么,我需要什么。谢谢善良的陌生人:@mutukrp:很高兴它能帮上忙;我的荣幸。为了完整性,我添加了一个将哈希表展平到各个列的解决方案。
# Create a custom object whose .col2 property is a hashtable with 2 
# sample entries and convert it to CSV
PS> [pscustomobject] @{ prop1 = 1; Output = @{ name='foo'; ID=666 } } | ConvertTo-Csv

"prop1","Output"
"1","System.Collections.Hashtable"
[pscustomobject] @{ prop1 = 1; Output = @{ name='foo'; ID=666 } } | 
  Select-Object prop1, @{ 
    n='Output'
    e={ $_.prop2.GetEnumerator().ForEach({ '{0}={1}' -f $_.Key, $_.Value }) -join ' ' } 
  } | ConvertTo-Csv
"prop1","prop2"
"1","ID=666 name=foo"
$coll = [pscustomobject] @{ prop1 = 1; prop2 = @{ name='foo1'; ID=666 } },
        [pscustomobject] @{ prop1 = 2; prop2 = @{ name='foo2'; ID=667 } }
$coll | select prop1, @{ n='name'; e={ $_.prop2.name } }, @{ n='ID'; e={ $_.prop2.ID } } |
  ConvertTo-Csv
"prop1","name","ID"
"1","foo1","666"
"2","foo2","667"
# Create the list of calculated properties dynamically, from the 1st input
# object's .prop2 hashtable.
$propList = foreach ($key in $coll[0].prop2.Keys) {
  # The script block for the calculated property must be created from a 
  # *string* in this case, so we can "bake" the key name into it.
  @{ n=$key; e=[scriptblock]::Create("`$_.prop2.$key") } 
}

$coll | Select-Object (, 'prop1' + $propList) | ConvertTo-Csv