在PowerShell中导出为CSV时的列排序 - 控制从哈希表创建的自定义对象的属性枚举顺序

Sve*_*kke 12 csv powershell formatting pscustomobject export-to-csv

我正在写一个脚本Powershell,导出所有securitygroups和他们membersActive Directory.现在我想格式化输出.csv.

代码:

$Groups = Get-ADGroup -Properties * -Filter * -SearchBase "OU=SERVICES,DC=XXXXXX,DC=XXXXX" 

$Table = @()

$Record = @{
    "Group Name" = ""
    "Name" = ""
    "Username" = ""
}

Foreach($G In $Groups)
{
    $Arrayofmembers = Get-ADGroupMember -identity $G -recursive | select name,samaccountname
    Foreach ($Member in $Arrayofmembers) 
    {
        $Record."Group Name" = $G.Name
        $Record."Name" = $Member.name
        $Record."UserName" = $Member.samaccountname
        $objRecord = New-Object PSObject -property $Record
        $Table += $objrecord
    }
}

$Table | export-csv "C:\temp\SecurityGroups.csv" -NoTypeInformation
Run Code Online (Sandbox Code Playgroud)

结果:

"Username","Name","Group Name"
"aman","Ani Manoukian","Commercial"
"adan","Aurelia Danneels","Commercial"
"kdeb","Kathleen De Backer","Commercial"
"TVGR","Thijs Van Grimbergen","Commercial"
"SVDE","Sofie Van den Eynde","Commercial"
Run Code Online (Sandbox Code Playgroud)

现在我希望输出格式为:

"Group Name","Name","Username" 代替 "Username","Name","Group Name"

有人可以帮我吗?

提前致谢.

mkl*_*nt0 32

gvee的有用答案是一个实用的解决方案,可确保列以所需顺序显示,因为将属性名称传递给Select-Object的顺序是将属性添加到结果[pscustomobject]实例的顺序.

它是,但是,低效率的,因为所期望的列顺序可以在时间能够确保$Record定义,而无需有效地复制了结果对象的附加的流水线阶段:

定义$Record有序哈希表如下(需要PSv3 +):

$Record = [ordered] @{
    "Group Name" = ""
    "Name" = ""
    "Username" = ""
}
Run Code Online (Sandbox Code Playgroud)

这可以保证[pscustomobject]稍后由New-Object PSObject -property $Record调用创建的实例包含的属性与定义键的顺序相同$Record.

两个旁边:
*New-Object PSObject -property $Record可以简化为[pscustomobject] $Record
*使用[System.Collections.ArrayList]添加元素的实例更有效地处理增量大型数组,.Add()而不是使用PowerShell的内置数组+=,每次都会创建数组的副本.


补充资料:

问题的根源是常规哈希表(foreach实例)以有效的随机顺序枚举其键(顺序是实现细节),并且当您$Table = foreach ...从哈希表创建时,该不可预测的键排序反映在结果的排序中对象的属性.

相比之下,在PSv3 +中,您可以通过将关键字放在哈希表文字之前来创建有序哈希表,这会产生一个实例,其键的排序基于它们的添加顺序.从有序散列表 创建实例然后在结果对象的属性中保留该键排序.[hashtable][pscustomobject]
[ordered]

需要注意的是PowerShell的(至少PSv5.1的,但据推测,因为PSv3)提供了一个用于创建一个方便的快捷[System.Collections.Specialized.OrderedDictionary]使用一个Hashtable的实例 ; 例如:

PS> [pscustomobject] @{ a = 1; b = 2; c = 3 } # key order is PRESERVED

a b c
- - -
1 2 3
Run Code Online (Sandbox Code Playgroud)

需要注意的关键定义顺序如何保存下来,即使[pscustomobject]没有被指定.
换句话说:当你施放一个哈希表的文字直接[pscustomobject],[ordered]隐含的,所以上面的等价于:

[pscustomobject] [ordered] @{ a = 1; b = 2; c = 3 }  # [ordered] is optional
Run Code Online (Sandbox Code Playgroud)

警告:这种隐性订货适用于当一个哈希表的文字直接转换为[pscustomobject],所以关键/属性顺序并不保存在以下变化:

New-Object PSCustomObject -Property @{ a = 1; b = 2; c = 3 } # !! order NOT preserved

$ht = @{ a = 1; b = 2; c = 3 }; [pscustomobject] $ht # !! order NOT preserved

[pscustomobject] (@{ a = 1; b = 2; c = 3 }) # !! order NOT preserved, due to (...)
Run Code Online (Sandbox Code Playgroud)

因此,在不直接转换哈希表文字时[ordered],请明确定义它[pscustomboject].

  • 这是一个很棒的**答案! (4认同)

gve*_*vee 20

这应该工作......

$Table |
  Select-Object "Group Name", "Name", "Username" |
  Export-Csv "C:\temp\SecurityGroups.csv" -NoTypeInformation
Run Code Online (Sandbox Code Playgroud)

  • 当您无法控制集合的创建(或不想)时,此答案也适用 (2认同)