Колонное упорядочение при экспорте в CSV в PowerShell - управление порядком перечисления свойств пользовательских объектов, созданных из hashtables

Я пишу script в Powershell, который экспортирует все securitygroups и их members из Active 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

Результат:

"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"

Теперь я хочу, чтобы результат форматировался как:

"Group Name","Name","Username" вместо "Username","Name","Group Name"

Кто-нибудь может мне помочь?

Спасибо заранее.

Ответ 1

Это должно работать...

$Table |
  Select-Object "Group Name", "Name", "Username" |
  Export-Csv "C:\temp\SecurityGroups.csv" -NoTypeInformation

Ответ 2

gvee Полезный ответ - это прагматичное решение, которое гарантирует, что столбцы отображаются в нужном порядке, поскольку порядок, в котором вы передаете имена свойств в Select-Object, является порядком, в котором свойства добавляются в результирующие экземпляры [pscustomobject].

Это, однако, неэффективно, потому что желаемый порядок столбцов может быть обеспечен во время определения $Record, без необходимости дополнительной стадии конвейера, которая эффективно дублирует объекты результата:

Определите $Record как упорядоченную хеш-таблицу следующим образом (требуется PSv3+):

$Record = [ordered] @{
    "Group Name" = ""
    "Name" = ""
    "Username" = ""
}

Это гарантирует, что экземпляры [pscustomobject], созданные позднее вызовами New-Object PSObject -property $Record, содержат свойства в том же порядке, в котором ключи были определены в $Record.

Two asides:
* [TG48] could be simplified to [TG49]
* Building up a large array incrementally is more efficiently handled with a [TG410] instance to which you add elements with [TG411] rather than using PowerShell built-in arrays with [TG412], which creates a copy of the array every time. Even better is to et PowerShell create the array for you, simply by capturing the output from your [TG413] loop in a variable ([TG414] - see this answer)


Дополнительная информация:

Источником проблемы является то, что обычные хеш-таблицы (экземпляры [hashtable]) нумеруют свои ключи в фактически случайном порядке (порядок является реализацией), а когда вы создаете [pscustomobject] из хеш-таблицы, что непредсказуемое упорядочение ключей отражается в упорядочении результирующих свойств объекта.

Напротив, в PSv3+ вы можете создать упорядоченную хеш-таблицу, поместив ключевое слово [ordered] перед литералом хеш-таблицы, в результате чего [System.Collections.Specialized.OrderedDictionary] экземпляр, ключи которого упорядочены в соответствии с порядком их добавления.
Создание экземпляра [pscustomobject] из упорядоченной хеш-таблицы затем сохраняет порядок ключей в результирующих свойствах объекта.

Обратите внимание, что PowerShell v3+ предлагает удобный ярлык для создания экземпляра [pscustomobject] из хеш-таблицы с использованием преобразования; например.:

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

a b c
- - -
1 2 3

Обратите внимание, как был сохранен порядок определения ключа, хотя [ordered] не был указан.
Другими словами: Когда вы приводите литерал хеш-таблицы непосредственно к [pscustomobject], [ordered] подразумевается, поэтому приведенное выше эквивалентно:

[pscustomobject] [ordered] @{ a = 1; b = 2; c = 3 }  # [ordered] is optional

Предупреждение. Это неявное упорядочение применяется только в том случае, если литерал хеш-таблицы напрямую приводится к [pscustomboject], поэтому порядок ключа/свойства не сохраняется в следующих вариантах:

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 (...)

Поэтому, если не приводить литерал хеш-таблицы непосредственно к [pscustomobject], определите его с помощью [ordered] явно.