Impression des propriétés des objets dans Powershell

121

Lorsque je travaille dans la console interactive, si je définis un nouvel objet et que je lui assigne des valeurs de propriété 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 essentiellement faire 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 d'objet dans la fenêtre Powershell avant de revenir. J'ai essayé d'utiliser Write-Host dans la fonction:

Write-Host $obj

Mais cela affiche simplement le type de l'objet et non le résumé:

System.Object

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

John
la source

Réponses:

188

Essaye ça:

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

ou

Write-Host ($obj | Format-List | Out-String)
mjolinor
la source
4
J'ai dû passer le -Forceparamètre pour le faire fonctionner, par exempleWrite-Host ($obj | Format-List -Force | Out-String)
Bart Verkoeijen
1
Pouah! Il s'affiche toujours horizontalement sur l'écran .... si une sortie sort de votre tampon, elle le met simplement .... J'ai une haine d'amour avec POSH
Kolob Canyon
En utilisant $objs = @();et $objs = $objs + $obj; je peux utiliser ConvertTo-Html: $ cols = $ objs | ConvertTo-Html -Fragment -Property Name, DataType, Default, Identity, InPrimaryKey, IsForeignKey, Description;
Kiquenet
33

Ma solution à ce problème était d'utiliser le bloc de sous-expression $ () .

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
David Peters
la source
16

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

$ pool = Get-Item "IIS: \ 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
...
yeux de chat
la source
1
La dernière variante de cela a fonctionné le mieux pour moi - peut même la raccourcir $x | select *, idéale pour l'interactivité.
doublé
Je ne pense pas que cela fonctionne si vous voulez le mettre dans un script. Si c'est le cas, je pense que vous devez faire quelque chose de plus que ce qui est indiqué afin de l'imprimer sur la console (par exemple: Write-Output <something-something>)
Fractal
11

Astuce n ° 1

N'utilisez jamais Write-Host.

Astuce n ° 12

La manière correcte de générer des informations à partir d'une applet de commande ou d'une fonction PowerShell consiste à créer un objet qui contient vos données, puis à écrire cet objet dans le pipeline à l'aide de Write-Output.

-Don Jones: Maître PowerShell

Idéalement, votre script créerait vos objets ( $obj = New-Object -TypeName psobject -Property @{'SomeProperty'='Test'}) puis ferait simplement un Write-Output $objects. Vous dirigeriez la sortie vers Format-Table.

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

Ils devraient vraiment appeler PowerShell PowerObjectandPipingShell.

MAL
la source
4
Merci Bob, j'ai accepté la réponse de mjolinor car je pense qu'elle répond plus directement à la question, mais j'ai beaucoup appris des liens que vous avez fournis et je suis d'accord que dans la plupart des cas, Write-Host ne convient pas. Merci!
John
1
La même technique fonctionnera, et serait probablement plus appropriée utilisée avec Write-Verbose ou Write-Debug.
mjolinor
4
Je sais, j'ai de nombreuses années de retard, mais je ne suis pas d'accord sur la Never use Write-Host.déclaration. Vous ne pouvez pas utiliser Write-Output à l'intérieur des fonctions qui renvoient des données, car cela "polluera" cette fonction. Exemple simple. Devinez quelle fonction ReturnText sortira? C'est pourquoi j'utilise toujours les fonctions Write-host à l'intérieur. function ReturnText () {Write-Output "Some random message" return "What I want to return"}
Denis Molodtsov
3
@DenisMolodtsov Je suis entièrement d'accord. Dans le but de consigner les informations, l'écriture-sortie ne doit JAMAIS être utilisée à moins que la fonction ne soit triviale. Une fois qu'il y a plusieurs niveaux de fonction et que vous devez retourner la sortie, vous DEVEZ utiliser autre chose, et Write-Host répond à la facture.
RobG
2
Write-Host sera également immédiatement renvoyé d'une session à distance, ce qui vous permettra de voir la progression, et si une session à distance génère une erreur, les informations de sortie d'écriture sont perdues.
RobG
3

Quelques remarques générales.


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

Ce dernier affichera toutes les propriétés non intrinsèques et non générées par le compilateur. Le premier ne pas semble (toujours) montrer tous les types de propriété (dans mes tests, il ne semble montrer la CodeProperty MemberTypeconstante bien - aucune garantie ici).


Quelques commutateurs à connaître pour Get-Member

  • Get-Membern'obtient pas de membres statiques par défaut. Vous ne pouvez pas non plus (directement) les obtenir avec les membres non statiques. Autrement dit, l'utilisation du commutateur entraîne uniquement le retour des 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.

    La Get-Membercommande utilise le paramètre Force pour ajouter les membres intrinsèques et les membres générés par le compilateur des objets à l'affichage. Get-Memberobtient ces membres, mais il les masque 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,...
    ...

Utilisation ConvertTo-Json pour une "sérialisation" détaillée et lisible

Je ne recommande pas nécessairement d'enregistrer des objets en utilisant JSON (à utiliser à la Export-Clixmlplace). Cependant, vous pouvez obtenir une sortie plus ou moins lisible deConvertTo-Json , ce qui vous permet également de spécifier la profondeur.

Notez que ne pas spécifier Depthimplique-Depth 2

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

Et si vous ne prévoyez pas de le lire, vous pouvez le -Compressfaire (c'est-à-dire supprimer les espaces)

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

Utilisation -InputObject si vous pouvez (et êtes prêt)

99,9% du temps lors de l'utilisation de PowerShell: soit les performances n'ont pas d'importance, soit vous ne vous souciez pas des performances. toutefois , il convient de noter qu'éviter le tuyau lorsque vous n'en avez pas besoin peut économiser des frais généraux et ajouter de la vitesse (la tuyauterie, en général, n'est pas super efficace).

Autrement dit, si vous n'avez qu'un seul $objoutil pratique pour l'impression (et que vous n'êtes pas trop paresseux comme moi parfois pour taper -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 une collection (par exemple System.Object[]), vous finissez par obtenir des informations sur l'objet de 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-Memberpour chacun TypeNamedans la collection (NB pour chacun TypeName, pas pour chaque objet - une collection de N objets avec tous les mêmes TypeNamen'imprimera qu'une table pour cela TypeName, pas N tables pour chaque objet) ...... il suffit de le coller directement.

YenForYang
la source
1

Le ci-dessous a vraiment bien fonctionné pour moi. J'ai corrigé toutes les réponses ci-dessus et j'ai lu sur l'affichage des propriétés des objets dans le lien suivant et j'ai trouvé la brève lecture ci-dessous sur l'impression d'objets

ajoutez le texte suivant à un fichier nommé print_object.ps1:

$date = New-Object System.DateTime
Write-Output $date | Get-Member
Write-Output $date | Select-Object -Property *

ouvrez l'invite de commande PowerShell, accédez au répertoire dans lequel ce fichier existe et tapez ce qui suit:

powershell -ExecutionPolicy ByPass -File is_port_in_use.ps1 -Elevated

Remplacez simplement «System.DateTime» par l'objet que vous vouliez imprimer. Si l'objet est nul, rien ne s'imprimera.

Fractale
la source
0
# Json to object
$obj = $obj | ConvertFrom-Json
Write-host $obj.PropertyName
Ramanujam Allam
la source