Comment le formatage fonctionne-t-il avec une fonction PowerShell qui renvoie un ensemble d'éléments?

Si j'écris cette petite fonction:

function Foo { Get-Process | % { $_ } } 

Et si je cours

 Foo 

Il affiche uniquement un petit sous-ensemble de propriétés:

 PS C:\Users\Administrator> foo Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName ------- ------ ----- ----- ----- ------ -- ----------- 86 10 1680 412 31 0,02 5916 alg 136 10 2772 2356 78 0,06 3684 atieclxx 123 7 1780 1040 33 0,03 668 atiesrxx ... ... 

Mais même si seulement 8 colonnes sont affichées, il y a beaucoup d'autres propriétés (tel que foo | gm s'affiche).

Ce qui provoque cette fonction ne montre que ces 8 propriétés?

J'essaie réellement de créer une fonction similaire qui renvoie des objets complexes à partir d'une bibliothèque .Net. La bibliothèque pose une hiérarchie à deux niveaux d'objets:

 function Actual { $someDotnetObject.ACollectionProperty.ASecondLevelCollection | % { $_ } } 

Cette méthode détruit les objets dans un formulaire de liste (une ligne par propriété).

Comment puis-je contrôler ce qui s'affiche, en gardant l'objet réel disponible ?

J'ai essayé ceci:

 function Actual { $someDotnetObject.ACollectionProperty.ASecondLevelCollection | % { $_ } | format-table Property1, Property2 } 

Il montre dans une console le tableau attendu:

 Property1 Property2 --------- --------- ValA ValD ValB ValE ValC ValF 

Mais j'ai perdu mes objets. Running Get-Member sur le résultat montre:

  TypeName: Microsoft.PowerShell.Commands.Internal.Format.FormatStartData Name MemberType Definition ---- ---------- ---------- Equals Method bool Equals(System.Object obj) GetHashCode Method int GetHashCode() GetType Method type GetType() ToString Method string ToString() autosizeInfo Property Microsoft.PowerShell.Commands.Internal.Format.AutosizeInfo autosizeInfo {get;set;} ClassId2e4f51ef21dd47e99d3c952918aff9cd Property System.String ClassId2e4f51ef21dd47e99d3c952918aff9cd {get;} groupingEntry Property Microsoft.PowerShell.Commands.Internal.Format.GroupingEntry groupingEntry {get;set;} pageFooterEntry Property Microsoft.PowerShell.Commands.Internal.Format.PageFooterEntry pageFooterEntry {get;set;} pageHeaderEntry Property Microsoft.PowerShell.Commands.Internal.Format.PageHeaderEntry pageHeaderEntry {get;set;} shapeInfo Property Microsoft.PowerShell.Commands.Internal.Format.ShapeInfo shapeInfo {get;set;} TypeName: Microsoft.PowerShell.Commands.Internal.Format.GroupStartData Name MemberType Definition ---- ---------- ---------- Equals Method bool Equals(System.Object obj) GetHashCode Method int GetHashCode() GetType Method type GetType() ToString Method string ToString() ClassId2e4f51ef21dd47e99d3c952918aff9cd Property System.String ClassId2e4f51ef21dd47e99d3c952918aff9cd {get;} groupingEntry Property Microsoft.PowerShell.Commands.Internal.Format.GroupingEntry groupingEntry {get;set;} shapeInfo Property Microsoft.PowerShell.Commands.Internal.Format.ShapeInfo shapeInfo {get;set;} 

Au lieu de montrer les membres de l'objet enfant au 2ème niveau. Dans ce cas, je ne peux pas faire passer le résultat aux fonctions en attente de ce type d'argument.

Comment Powershell est censé gérer un tel scénario?

Cela est effectivement contrôlé par des fichiers de format. De powershell help about_Format.ps1xml :

Les fichiers Format.ps1xml dans Windows PowerShell définissent l'affichage par défaut des objets dans Windows PowerShell. Vous pouvez créer vos propres fichiers Format.ps1xml pour modifier l'affichage des objets ou définir des affichages par défaut pour les nouveaux types d'objets que vous créez dans Windows PowerShell.

Lorsque Windows PowerShell affiche un objet, il utilise les données dans des fichiers de mise en forme structurée pour déterminer l'affichage par défaut de l'objet. Les données dans les fichiers de mise en forme détermine si l'objet est rendu dans une table ou dans une liste, et il détermine quelles propriétés sont affichées par défaut.

Le formatage affecte uniquement l'affichage. Cela n'affecte pas les propriétés de l'objet transmises par la canalisation ni la façon dont elles sont transmises.

Selon votre exemple, get-process renvoie System.Diagnostics.Process , lequel (format de sortie) est défini dans DotNetTypes.format.ps1xml :

  <Name>process</Name> <ViewSelectedBy> <TypeName>System.Diagnostics.Process</TypeName> </ViewSelectedBy> <TableControl> <TableHeaders> <TableColumnHeader> <Label>Handles</Label> <Width>7</Width> <Alignment>right</Alignment> </TableColumnHeader> <TableColumnHeader> <Label>NPM(K)</Label> <Width>7</Width> <Alignment>right</Alignment> </TableColumnHeader> (output omitted) 

Essayez quelque chose comme ceci:

 ... | ForEach-Object { Write-Host $_.Something $_ } 

Le $_ à l'intérieur du bloc de code passe l'objet.