159 votes

Impression des propriétés des objets dans Powershell

Lorsque je travaille dans la console interactive, si je définis un nouvel objet et que je lui attribue des valeurs de propriétés comme ceci :

$obj = New-Object System.String
$obj | Add-Member NoteProperty SomeProperty "Test"

Ensuite, lorsque je tape le nom de ma variable dans la fenêtre interactive, Powershell me donne un résumé des propriétés et des valeurs de l'objet :

PS C:\demo> $obj
SomeProperty                                                                                                                                                                                  
------------                                                                                                                                                                                  
Test

Je veux faire exactement cela, mais à partir d'une fonction dans un script. La fonction crée un objet et définit certaines valeurs de propriété et je veux qu'elle imprime un résumé des valeurs de l'objet dans la fenêtre Powershell avant de revenir. J'ai essayé d'utiliser Write-Host dans la fonction :

Write-Host $obj

Mais cela ne fait qu'indiquer le type d'objet et non le résumé :

System.Object

Comment puis-je faire en sorte que ma fonction produise un résumé des valeurs des propriétés de l'objet dans la fenêtre Powershell ?

255voto

mjolinor Points 23012

Essayez ça :

Write-Host ($obj | Format-Table | Out-String)

ou

Write-Host ($obj | Format-List | Out-String)

57voto

David Peters Points 311

La solution que j'ai trouvée à ce problème a été d'utiliser le Bloc de sous-expressions $() .

Add-Type -Language CSharp @"
public class Thing{
    public string Name;
}
"@;

$x = New-Object Thing

$x.Name = "Bill"

Write-Output "My name is $($x.Name)"
Write-Output "This won't work right: $x.Name"

Donne :

My name is Bill
This won't work right: Thing.Name

19voto

cateyes Points 103

Pour imprimer les propriétés et les valeurs d'un objet dans Powershell. Ci-dessous exemples fonctionnent bien pour moi.

$pool = Get-Item "II S:\AppPools.NET v4.5"

$pool | Get-Member

   TypeName: Microsoft.IIs.PowerShell.Framework.ConfigurationElement#system.applicationHost/applicationPools#add

Name                        MemberType            Definition
----                        ----------            ----------
Recycle                     CodeMethod            void Recycle()
Start                       CodeMethod            void Start()
Stop                        CodeMethod            void Stop()
applicationPoolSid          CodeProperty          Microsoft.IIs.PowerShell.Framework.CodeProperty
state                       CodeProperty          Microsoft.IIs.PowerShell.Framework.CodeProperty
ClearLocalData              Method                void ClearLocalData()
Copy                        Method                void Copy(Microsoft.IIs.PowerShell.Framework.ConfigurationElement ...
Delete                      Method                void Delete()
...

$pool | Select-Object -Property * # Vous pouvez omettre -Property

name                        : .NET v4.5
queueLength                 : 1000
autoStart                   : True
enable32BitAppOnWin64       : False
managedRuntimeVersion       : v4.0
managedRuntimeLoader        : webengine4.dll
enableConfigurationOverride : True
managedPipelineMode         : Integrated
CLRConfigFile               :
passAnonymousToken          : True
startMode                   : OnDemand
state                       : Started
applicationPoolSid          : S-1-5-82-271721585-897601226-2024613209-625570482-296978595
processModel                : Microsoft.IIs.PowerShell.Framework.ConfigurationElement
...

11voto

Mad Tom Vane Points 1146

Conseil n°1

Ne jamais utiliser Write-Host.

Conseil n°12

La façon correcte de produire des informations à partir d'une cmdlet ou d'une fonction PowerShell est de créer un objet qui contient vos données, puis d'écrire cet objet dans le pipeline en utilisant Write-Output.

-Don Jones : Maître PowerShell

Idéalement, votre script devrait créer vos objets ( $obj = New-Object -TypeName psobject -Property @{'SomeProperty'='Test'} ), il suffit de faire un Write-Output $objects . Vous devez envoyer la sortie vers Format-Table .

PS C:\> Run-MyScript.ps1 | Format-Table

Ils devraient vraiment appeler PowerShell PowerObjectandPipingShell.

7voto

YenForYang Points 128

Quelques notes générales.


$obj | Select-Object $obj | Select-Object -Property *

Ce dernier montrera todo propriétés non intrinsèques, non générées par le compilateur. La première fait no semblent (toujours) montrer todo Les types de propriétés (dans mes tests, il semble bien que l'on affiche les CodeProperty MemberType de manière cohérente, mais sans aucune garantie).


Quelques interrupteurs à connaître pour Obtenir l'adhésion

  • Get-Member hace no obtiennent des membres statiques par défaut. Vous pouvez également ne peut pas (directement) les obtenir ainsi que les membres non statiques. En d'autres termes, l'utilisation du commutateur permet de renvoyer uniquement les membres statiques :

    PS Y:\Power> $obj | Get-Member -Static
    
       TypeName: System.IsFire.TurnUpProtocol
    
    Name        MemberType Definition
    ----        ---------- ----------
    Equals      Method     static bool Equals(System.Object objA, System.Object objB)
    ...
  • Utilisez le -Force .

    El Get-Member utilise l'option Force pour ajouter les membres intrinsèques et les membres générés par le compilateur des objets à l'affichage. Get-Member obtient ces membres, mais il les cache par défaut.

    PS Y:\Power> $obj | Get-Member -Static
    
       TypeName: System.IsFire.TurnUpProtocol
    
    Name          MemberType     Definition
    ----          ----------     ----------
    ...
    pstypenames   CodeProperty   System.Collections.ObjectModel.Collection...
    psadapted     MemberSet      psadapted {AccessRightType, AccessRuleType,...
    ...

Utilisez ConvertTo-Json pour une "sérialisation" profonde et lisible

Je le fais. no Il est nécessaire de recommander de sauvegarder les objets en utilisant JSON (utiliser Export-Clixml à la place). Cependant, vous pouvez obtenir une sortie plus ou moins lisible à partir de ConvertTo-Json qui vous permet également de spécifier la profondeur.

Notez que si vous ne spécifiez pas Depth implica -Depth 2

PS Y:\Power> ConvertTo-Json $obj -Depth 1
{
    "AllowSystemOverload":  true,
    "AllowLifeToGetInTheWay":  false,
    "CantAnyMore": true,
    "LastResortOnly": true,
...

Et si vous n'avez pas l'intention de le lire, vous pouvez -Compress (c'est-à-dire en supprimant les espaces blancs)

PS Y:\Power> ConvertTo-Json $obj -Depth 420 -Compress

Utilisez -InputObject si vous le pouvez (et le voulez)

Dans 99,9 % des cas, lorsqu'on utilise PowerShell, soit les performances n'ont aucune importance, soit elles ne vous intéressent pas. Cependant Il convient de noter qu'en évitant d'utiliser le pipe lorsque vous n'en avez pas besoin, vous pouvez économiser des frais généraux et gagner en rapidité (le pipe, en général, n'est pas très efficace).

C'est-à-dire que si vous n'avez qu'un seul $obj à portée de main pour l'impression (et ne sont pas trop paresseux comme moi parfois pour taper à la machine) -InputObject ):

# select is aliased (hardcoded) to Select-Object
PS Y:\Power> select -Property * -InputObject $obj

# gm is aliased (hardcoded) to Get-Member
PS Y:\Power> gm -Force -InputObject $obj

Avertissement pour Get-Member -InputObject : Si $obj est un collection (par exemple System.Object[] ), vous finissez par obtenir des informations sur l'objet de la collection lui-même :

PS Y:\Power> gm -InputObject $obj,$obj2
   TypeName: System.Object[]

Name        MemberType            Definition
----        ----------            ----------
Count       AliasProperty         Count = Length
...

Si vous voulez Get-Member pour chaque TypeName dans la collection (N.B. pour chaque TypeName , no pour chaque objet une collection de N objets avec tous les mêmes TypeName n'imprimera qu'un seul tableau pour cette TypeName et non pas N tables pour chaque objet) ....... Contentez-vous de l'intégrer directement dans la tuyauterie.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X