我正在运行Test-AdfsServerHealth(Ref.)

问题是,输出值(值名称Output)之一是一个显示为System.Collection.Hashtable的数组,我正在尝试寻找一种以整洁的Excel格式获取此值的方法。

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

Name    Result  Detail  Output
TestServiceAccountProperties    Pass    "" System.Collections.Hashtable

But PowerShell displays:

Name             : TestServiceAccountProperties
Result           : Pass
Detail           :
Output           : {AdfsServiceAccount, AdfsServiceAccountDisabled, AdfsServiceAccountLockedOut,
                   AdfsServiceAccountPwdExpired...}
ExceptionMessage :

The actual command I'm running is:

$ServerResult = Test-AdfsServerHealth

最佳答案

tl;博士:

Test-AdfsServerHealth |
  Select-Object Name, Result, Detail, @{
    n='Output'
    e={ $_.prop2.GetEnumerator().ForEach({ '{0}={1}' -f $_.Key, $_.Value }) -join ' ' }
  } | ExportTo-Csv out.csv

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

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

复杂对象(例如[hashtable]实例)通常仅产生其完整类型名称(System.Collections.Hashtable)作为.ToString(),这在CSV中不起作用。

一个简化的示例(我正在使用ConvertTo-Csv,但是该示例类似地适用于Export-Csv):
# 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"

如果Test-AdfsServerHealth的所有输出对象的.Output属性都具有相同的哈希表结构,则可以尝试使哈希表的条目列保持其自身的权利,从而使哈希表扁平化,但这听起来并非如此。

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

您可以使用Select-Object和一个为您执行转换的计算属性来执行此操作,但是您需要确定在CSV文件的上下文中有意义的文本表示形式。

在以下示例中,创建了由空格分隔的<key>=<value>对组成的单行字符串(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

有关创建计算的prop2属性的哈希表格式的说明,请参阅我的this answer

以上 yield :
"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 } }

如果您事先知道(感兴趣的)键名,则可以简单地使用使用显式的计算属性列表来创建各个列:
$coll | select prop1, @{ n='name'; e={ $_.prop2.name } }, @{ n='ID'; e={ $_.prop2.ID } } |
  ConvertTo-Csv

上面的代码产生了以下内容,表明哈希表条目变成了自己的列nameID:
"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

这将产生与前一条命令相同的输出,并带有固定的已计算属性列表。

关于powershell - 将哈希表值的属性导出到CSV文件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49276451/

10-12 16:51