Stampa delle proprietà degli oggetti in Powershell


120

Quando lavoro nella console interattiva, se definisco un nuovo oggetto e gli assegno alcuni valori di proprietà in questo modo:

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

Quindi, quando digito il nome della mia variabile nella finestra interattiva, Powershell mi fornisce un riepilogo delle proprietà e dei valori dell'oggetto:

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

Fondamentalmente voglio fare proprio questo ma dall'interno di una funzione in uno script. La funzione crea un oggetto e imposta alcuni valori di proprietà e voglio che stampi un riepilogo dei valori dell'oggetto nella finestra di Powershell prima di tornare. Ho provato a utilizzare Write-Host all'interno della funzione:

Write-Host $obj

Ma questo restituisce solo il tipo di oggetto non il riepilogo:

System.Object

Come posso fare in modo che la mia funzione restituisca un riepilogo dei valori delle proprietà dell'oggetto nella finestra di Powershell?

Risposte:


187

Prova questo:

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

o

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

4
Ho dovuto passare il -Forceparametro per farlo funzionare, ad esempioWrite-Host ($obj | Format-List -Force | Out-String)
Bart Verkoeijen

1
Ugh! Viene ancora visualizzato orizzontalmente sullo schermo ... se un output esce dal buffer, lo mette .... Ho un amore odio con POSH
Kolob Canyon,

Uso $objs = @();e $objs = $objs + $obj; posso usare ConvertTo-Html: $ cols = $ objs | ConvertTo-Html -Fragment -Nome proprietà, DataType, Default, Identity, InPrimaryKey, IsForeignKey, Description;
Kiquenet

33

La mia soluzione a questo problema è stata quella di utilizzare il blocco di sottoespressioni $ () .

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"

dà:

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

16

Per stampare le proprietà e i valori degli oggetti in Powershell. Gli esempi seguenti funzionano bene per me.

$ 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 * # È possibile omettere -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
...

1
L'ultima variante di questo ha funzionato meglio per me - può anche accorciarla a $x | select *, ottimo per interattivo.
doppiamente il

Non penso che funzioni se vuoi metterlo in una sceneggiatura. Se è così, penso che tu debba fare qualcosa in più rispetto a quanto dichiarato per stamparlo effettivamente sulla console (es .: Write-Output <qualcosa-qualcosa>)
Fractal

11

Suggerimento n. 1

Non utilizzare mai Write-Host.

Suggerimento n. 12

Il modo corretto per restituire informazioni da un cmdlet o una funzione di PowerShell è creare un oggetto che contiene i dati e quindi scrivere tale oggetto nella pipeline utilizzando Write-Output.

-Don Jones: PowerShell Master

Idealmente il tuo script creerebbe i tuoi oggetti ( $obj = New-Object -TypeName psobject -Property @{'SomeProperty'='Test'}) quindi farebbe semplicemente un file Write-Output $objects. Dovresti reindirizzare l'output a Format-Table.

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

Dovrebbero davvero chiamare PowerShell PowerObjectandPipingShell.


4
Grazie Bob, ho accettato la risposta di mjolinor in quanto ritengo che risponda alla domanda in modo più diretto, tuttavia ho imparato molto dai link che hai fornito e sono d'accordo che nella maggior parte dei casi Write-Host non è adatto. Grazie!
John

1
La stessa tecnica funzionerà e sarebbe probabilmente più adatta se usata con Write-Verbose o Write-Debug.
mjolinor

4
Lo so, sono in ritardo di molti anni, ma non sono d'accordo sulla Never use Write-Host.dichiarazione. Non è possibile utilizzare Write-Output all'interno di funzioni che restituiscono dati, perché "inquinerà" questa funzione. Semplice esempio. Indovina quale funzione ReturnText produrrà? Questo è il motivo per cui utilizzo sempre le funzioni Write-host all'interno. function ReturnText () {Write-Output "Some random message" return "What I want to return"}
Denis Molodtsov

3
@DenisMolodtsov Sono completamente d'accordo. Ai fini della registrazione delle informazioni, l'output di scrittura non dovrebbe MAI essere utilizzato a meno che la funzione non sia banale. Una volta che ci sono più livelli di funzione e devi restituire l'output, DEVI usare qualcos'altro e Write-Host soddisfa il conto.
RobG

2
Anche Write-Host verrà immediatamente reindirizzato da una sessione remota consentendo di vedere lo stato di avanzamento e se una sessione remota genera un errore, le informazioni sull'output di scrittura vengono perse.
RobG

3

Alcune note generali.


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

Quest'ultimo mostrerà tutte le proprietà non intrinseche, non generate dal compilatore. Il primo non sembra mostrare (sempre) tutti i tipi di proprietà (nei miei test, sembra mostrare CodeProperty MemberTypecoerentemente però - nessuna garanzia qui).


Alcuni interruttori di cui essere a conoscenza per Get-Member

  • Get-Membernon non avere membri statici per impostazione predefinita. Inoltre, non è possibile (direttamente) ottenerli insieme ai membri non statici. Ovvero, l'utilizzo dell'opzione causa la restituzione solo dei membri statici:

    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)
    ...
  • Usa il -Force.

    Il Get-Membercomando utilizza il parametro Force per aggiungere alla visualizzazione i membri intrinseci e i membri degli oggetti generati dal compilatore. Get-Memberottiene questi membri, ma li nasconde per impostazione predefinita.

    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,...
    ...

Uso ConvertTo-Json per una "serializzazione" approfondita e leggibile

Non è necessario consigliare di salvare gli oggetti utilizzando JSON (usa Export-Clixmlinvece). Tuttavia, è possibile ottenere un output più o meno leggibile da ConvertTo-Json, che consente anche di specificare la profondità.

Nota che non specificare Depthimplica-Depth 2

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

E se non hai intenzione di leggerlo, puoi -Compressfarlo (cioè togliere gli spazi bianchi)

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

Usa -InputObjectse puoi (e sei disposto)

Il 99,9% delle volte quando si utilizza PowerShell: o le prestazioni non contano o non ti interessano le prestazioni. Tuttavia , va notato che evitare il tubo quando non è necessario può risparmiare un po 'di overhead e aggiungere un po' di velocità (le tubazioni, in generale, non sono super efficienti).

Cioè, se tutto quello che hai è un unico a $objportata di mano per la stampa (e non sei troppo pigro come me a volte per digitare -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

Avvertenza Get-Member -InputObject: se $ obj è una raccolta (ad esempio System.Object[]), si finiscono per ottenere informazioni sull'oggetto della raccolta stesso:

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

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

Se lo desideri Get-Memberper ciascuno TypeNamenella raccolta (NB per ciascuno TypeName, non per ogni oggetto - una raccolta di N oggetti con lo stesso TypeNamestamperà solo 1 tabella per quello TypeName, non N tabelle per ogni oggetto) ... basta attaccare con tubazioni direttamente.


1

Quanto segue ha funzionato davvero bene per me. Ho messo insieme tutte le risposte precedenti e ho letto sulla visualizzazione delle proprietà degli oggetti nel seguente collegamento e ho trovato la breve lettura di seguito sulla stampa degli oggetti

aggiungere il testo seguente a un file denominato print_object.ps1:

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

apri il prompt dei comandi di PowerShell, vai alla directory in cui esiste il file e digita quanto segue:

powershell -ExecutionPolicy ByPass -File is_port_in_use.ps1 -Elevated

Basta sostituire "System.DateTime" con qualsiasi oggetto che si desidera stampare. Se l'oggetto è nullo, non verrà stampato nulla.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.