Objekteigenschaften in Powershell drucken

119

Wenn ich in der interaktiven Konsole ein neues Objekt definiere und ihm einige Eigenschaftswerte wie folgt zuweise:

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

Wenn ich dann den Namen meiner Variablen in das interaktive Fenster eingebe, gibt mir Powershell eine Zusammenfassung der Objekteigenschaften und -werte:

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

Ich möchte im Grunde nur dies tun, aber innerhalb einer Funktion in einem Skript. Die Funktion erstellt ein Objekt und legt einige Eigenschaftswerte fest. Ich möchte, dass eine Zusammenfassung der Objektwerte im Powershell-Fenster ausgedruckt wird, bevor sie zurückgegeben wird. Ich habe versucht, Write-Host innerhalb der Funktion zu verwenden:

Write-Host $obj

Dabei wird jedoch nur der Typ des Objekts ausgegeben, nicht die Zusammenfassung:

System.Object

Wie kann meine Funktion eine Zusammenfassung der Eigenschaftswerte des Objekts im Powershell-Fenster ausgeben?

John
quelle

Antworten:

186

Versuche dies:

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

oder

Write-Host ($obj | Format-List | Out-String)
mjolinor
quelle
4
Ich musste den -ForceParameter übergeben, damit es funktioniert, zBWrite-Host ($obj | Format-List -Force | Out-String)
Bart Verkoeijen
1
Pfui! Es wird immer noch horizontal auf dem Bildschirm angezeigt. Wenn eine Ausgabe außerhalb Ihres Puffers liegt, wird sie nur abgelegt .... Ich habe einen Liebeshass mit POSH
Kolob Canyon
Verwenden $objs = @();und $objs = $objs + $obj; ich kann verwenden ConvertTo-Html: $ cols = $ objs | ConvertTo-Html -Fragment -Property Name, Datentyp, Standard, Identität, InPrimaryKey, IsForeignKey, Beschreibung;
Kiquenet
32

Meine Lösung für dieses Problem bestand darin, den Unterausdruckblock $ () zu verwenden .

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"

Gibt:

My name is Bill
This won't work right: Thing.Name
David Peters
quelle
16

So drucken Sie die Eigenschaften und Werte des Objekts in Powershell aus Die folgenden Beispiele funktionieren gut für mich.

$ 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 * # Sie können -Property weglassen

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
...
Katzenaugen
quelle
1
Die letzte Variante davon hat bei mir am besten funktioniert - kann sogar verkürzt werden $x | select *, ideal für interaktive.
Dualed
Ich denke nicht, dass dies funktioniert, wenn ich es in ein Skript einfügen möchte. Wenn ja, denke ich, müssen Sie etwas anderes tun, als angegeben, um es tatsächlich auf der Konsole zu drucken (dh: Write-Output <something-something>)
Fractal
11

Tipp 1

Verwenden Sie niemals Write-Host.

Tipp 12

Die richtige Methode zum Ausgeben von Informationen aus einem PowerShell-Cmdlet oder einer PowerShell-Funktion besteht darin, ein Objekt zu erstellen, das Ihre Daten enthält, und dieses Objekt dann mithilfe von Write-Output in die Pipeline zu schreiben.

-Don Jones: PowerShell-Meister

Idealerweise würde Ihr Skript Ihre Objekte erstellen ( $obj = New-Object -TypeName psobject -Property @{'SomeProperty'='Test'}) und dann einfach a Write-Output $objects. Sie würden die Ausgabe an weiterleiten Format-Table.

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

Sie sollten PowerShell PowerObjectandPipingShell wirklich aufrufen.

BÖSE
quelle
4
Vielen Dank, Bob, ich habe die Antwort von mjolinor akzeptiert, da ich der Meinung bin, dass sie die Frage direkter beantwortet. Ich habe jedoch viel aus den von Ihnen angegebenen Links gelernt und bin mir einig, dass Write-Host in den meisten Fällen nicht geeignet ist. Vielen Dank!
John
1
Die gleiche Technik wird funktionieren und wäre wahrscheinlich besser für Write-Verbose oder Write-Debug geeignet.
Mjolinor
4
Ich weiß, ich bin viele Jahre zu spät, aber ich bin nicht einverstanden mit der Never use Write-Host.Aussage. Sie können Write-Output nicht in Funktionen verwenden, die Daten zurückgeben, da diese Funktion dadurch "verschmutzt" wird. Einfaches Beispiel. Ratet mal, welche ReturnText-Funktion ausgegeben wird? Deshalb benutze ich immer Write-Host innerhalb von Funktionen. Funktion ReturnText () {Write-Output "Eine zufällige Nachricht" return "Was ich zurückgeben möchte"}
Denis Molodtsov
3
@ DenisMolodtsov Ich stimme vollkommen zu. Zum Zwecke der Protokollierung von Informationen sollte Write-Output NIEMALS verwendet werden, es sei denn, die Funktion ist trivial. Sobald es mehrere Funktionsebenen gibt und Sie die Ausgabe zurückgeben müssen, MÜSSEN Sie etwas anderes verwenden, und Write-Host erfüllt die Rechnung.
RobG
2
Write-Host wird auch sofort von einer Remote-Sitzung zurückgeleitet, sodass Sie den Fortschritt sehen können. Wenn eine Remote-Sitzung einen Fehler auslöst, gehen die Write-Output-Informationen verloren.
RobG
3

Einige allgemeine Hinweise.


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

Letzteres zeigt alle nicht intrinsischen, nicht vom Compiler generierten Eigenschaften an. Ersteres scheint nicht (immer) alle Eigenschaftstypen anzuzeigen (in meinen Tests scheint es jedoch CodeProperty MemberTypekonsistent zu sein - hier keine Garantien).


Einige Schalter, die Sie für Get-Member beachten sollten

  • Get-Membererhält standardmäßig keine statischen Mitglieder. Sie können sie auch nicht (direkt) mit den nicht statischen Mitgliedern zusammenbringen. Das heißt, bei Verwendung des Schalters werden nur statische Elemente zurückgegeben:

    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)
    ...
  • Verwenden Sie die -Force.

    Der Get-MemberBefehl verwendet den Force- Parameter, um die intrinsischen Elemente und vom Compiler generierten Elemente der Objekte zur Anzeige hinzuzufügen. Get-MemberRuft diese Mitglieder ab, versteckt sie jedoch standardmäßig.

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

Verwenden ConvertTo-Json für Tiefe und lesbare "Serialisierung"

Ich mache nicht notwendig empfehlen Speicher Objekte mit JSON (Verwendung Export-Clixmlstatt). Sie können jedoch eine mehr oder weniger lesbare Ausgabe erhalten ConvertTo-Json, mit der Sie auch die Tiefe angeben können.

Beachten Sie, dass keine Angabe Depthimpliziert-Depth 2

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

Und wenn Sie nicht vorhaben, es zu lesen, können Sie -Compresses (dh Leerzeichen entfernen)

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

Verwenden -InputObjectSie, wenn Sie können (und bereit sind)

99,9% der Zeit bei Verwendung von PowerShell: Entweder spielt die Leistung keine Rolle, oder Sie interessieren sich nicht für die Leistung. jedoch sollte es , dass das Rohr zu vermeiden zu beachten , wenn Sie es nicht brauchen kann einigen Aufwand sparen und etwas Geschwindigkeit hinzufügen (Rohrleitungen, in der Regel nicht super-effizient ist).

Das heißt, wenn Sie nur ein einziges $objHandy zum Drucken haben (und nicht zu faul sind wie ich, um es manchmal abzutippen -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

Vorsichtsmaßnahme für Get-Member -InputObject: Wenn $ obj eine Sammlung ist (z. B. System.Object[]), erhalten Sie am Ende Informationen über das Sammlungsobjekt selbst:

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

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

Wenn Sie möchten , Get-Memberfür jeden TypeNamein der Sammlung (für jede NB TypeName, nicht für jedes Objekt - eine Sammlung von N - Objekten mit all gleich TypeNamewird 1 Tabelle druckt nur für das TypeName, nicht N - Tabellen für jedes Objekt) ...... Bleib einfach bei der direkten Verrohrung.

YenForYang
quelle
1

Das Folgende hat wirklich gut für mich funktioniert. Ich habe alle oben genannten Antworten zusammengefügt und über das Anzeigen von Objekteigenschaften im folgenden Link gelesen und die folgende kurze Lektüre zum Drucken von Objekten gefunden

Fügen Sie einer Datei mit dem Namen print_object.ps1 den folgenden Text hinzu:

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

Öffnen Sie die Powershell-Eingabeaufforderung, wechseln Sie in das Verzeichnis, in dem diese Datei vorhanden ist, und geben Sie Folgendes ein:

powershell -ExecutionPolicy ByPass -File is_port_in_use.ps1 -Elevated

Ersetzen Sie einfach 'System.DateTime' durch das Objekt, das Sie drucken möchten. Wenn das Objekt null ist, wird nichts ausgedruckt.

Fraktal
quelle
0
# Json to object
$obj = $obj | ConvertFrom-Json
Write-host $obj.PropertyName
Ramanujam Allam
quelle