web-dev-qa-db-fra.com

Ordre des colonnes lors de l'exportation vers CSV dans PowerShell - contrôle de l'ordre d'énumération des propriétés des objets personnalisés créés à partir de tables de hachage

J'écris un script dans Powershell qui exporte tous les securitygroups et leurs members de Active Directory. Maintenant, je veux formater la sortie du .csv.

Le code:

$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

Le résultat:

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

Maintenant, je veux que la sortie soit formatée en:

"Group Name","Name","Username" au lieu de "Username","Name","Group Name"

Quelqu'un peut-il m'aider s'il-vous-plaît?

Merci d'avance.

14
Svekke

Cela devrait fonctionner ...

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

réponse utile de gvee est une solution pragmatique qui garantit que les colonnes apparaissent dans l'ordre souhaité, car l'ordre dans lequel vous passez les noms de propriété à Select-Object est l'ordre dans lequel les propriétés sont ajoutées aux instances [pscustomobject] résultantes.

Il est cependant inefficace , car l'ordre des colonnes souhaité peut être assuré au moment $Record est défini, sans avoir besoin d'une étape de pipeline supplémentaire qui duplique efficacement les objets de résultat:

Définissez $Record Comme ordonné table de hachage comme suit (nécessite PSv3 + ):

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

Cela garantit que les instances [pscustomobject] Créées ultérieurement par les appels New-Object PSObject -property $Record Contiennent des propriétés dans le même ordre que les clés ont été définies dans $Record.

Deux côtés:
* New-Object PSObject -property $Record Pourrait être simplifié en [pscustomobject] $Record
* La création incrémentielle d'un grand tableau est plus efficacement gérée avec une instance de [System.Collections.ArrayList] À laquelle vous ajoutez des éléments avec .Add() plutôt que d'utiliser les tableaux intégrés de PowerShell avec +=, Qui crée à chaque fois une copie du tableau. Encore mieux, et PowerShell crée le tableau pour vous, simplement en capturant la sortie de votre boucle foreach dans une variable ($Table = foreach ... - voir cette réponse )


Information supplémentaire:

La source du problème est que les tables de hachage régulières (instances [hashtable]) Énumèrent leurs clés dans un ordre effectivement aléatoire (l'ordre est une implémentation détail), et lorsque vous créez un [pscustomobject] à partir d'une table de hachage, cet ordre de clé imprévisible se reflète dans l'ordre des propriétés de l'objet résultant.

En revanche, dans PSv3 + vous pouvez créer une ordonnée table de hachage en plaçant le mot-clé [ordered] devant un littéral de table de hachage, ce qui donne un [System.Collections.Specialized.OrderedDictionary] instance dont clés sont ordonnées en fonction de l'ordre dans lequel elles ont été ajoutées.
La création d'une instance [pscustomobject] À partir d'une table de hachage ordonnée préserve ensuite l'ordre des clés dans les propriétés de l'objet résultant.

Notez que PowerShell v3 + offre un raccourci pratique pour créer une instance [pscustomobject] À partir d'une table de hachage à l'aide d'un cast; par exemple.:

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

a b c
- - -
1 2 3

Notez comment l'ordre de définition des clés était préservé, même si [ordered] N'a pas été spécifié.
En d'autres termes: Lorsque vous transtypez un littéral de table de hachage directement en [pscustomobject], [ordered] Est = implicite, donc ce qui précède équivaut à:

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

Avertissement : cet ordre implicite seulement s'applique lorsqu'une table de hachage littérale est directly transtypé en [pscustomboject], donc l'ordre des clés/propriétés est pas conservé dans les variantes suivantes:

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

Par conséquent, lorsque vous ne convertissez pas un littéral de table de hachage directement en [pscustomobject], Définissez-le explicitement avec [ordered].

35
mklement0