Mencetak properti objek di Powershell


120

Saat bekerja di konsol interaktif jika saya mendefinisikan objek baru dan menetapkan beberapa nilai properti padanya seperti ini:

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

Kemudian ketika saya mengetik nama variabel saya ke dalam jendela interaktif Powershell memberi saya ringkasan properti dan nilai objek:

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

Saya pada dasarnya ingin melakukan ini tetapi dari dalam fungsi dalam skrip. Fungsi ini membuat objek dan menetapkan beberapa nilai properti dan saya ingin mencetak ringkasan nilai objek ke jendela Powershell sebelum kembali. Saya mencoba menggunakan Write-Host dalam fungsi:

Write-Host $obj

Tapi ini hanya menampilkan tipe objek bukan ringkasan:

System.Object

Bagaimana saya bisa membuat fungsi saya menampilkan ringkasan nilai properti objek ke jendela Powershell?

Jawaban:


187

Coba ini:

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

atau

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

4
Saya harus meneruskan -Forceparameter agar berfungsi, misalnyaWrite-Host ($obj | Format-List -Force | Out-String)
Bart Verkoeijen

1
Ugh! Ini masih ditampilkan secara horizontal di layar .... jika ada output yang keluar dari buffer Anda, itu hanya menempatkan .... Saya punya cinta benci dengan POSH
Kolob Canyon

Menggunakan $objs = @();dan $objs = $objs + $obj; saya dapat menggunakan ConvertTo-Html: $ cols = $ objs | ConvertTo-Html -Fragment -Nama Properti, Jenis Data, Default, Identitas, InPrimaryKey, IsForeignKey, Deskripsi;
Kiquenet

33

Solusi saya untuk masalah ini adalah dengan menggunakan blok sub-ekspresi $ () .

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"

Memberikan:

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

16

Untuk mencetak properti dan nilai objek di Powershell. Contoh di bawah ini bekerja dengan baik untuk saya.

$ pool = Dapatkan-Item "IIS: \ AppPools.NET v4.5"

$ pool | Dapatkan-Anggota

   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 * # Anda dapat menghilangkan -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
Varian terakhir ini bekerja paling baik untuk saya - bahkan dapat mempersingkatnya menjadi $x | select *, bagus untuk interaktif.
digandakan

Saya tidak berpikir ini berfungsi jika ingin memasukkannya ke dalam skrip. Jika demikian, saya pikir Anda harus melakukan sesuatu tambahan dari apa yang dinyatakan untuk benar-benar mencetaknya ke konsol (yaitu: Write-Output <something-something>)
Fractal

11

Kiat # 1

Jangan pernah menggunakan Write-Host.

Kiat # 12

Cara yang benar untuk mengeluarkan informasi dari cmdlet atau fungsi PowerShell adalah dengan membuat objek yang berisi data Anda, lalu menulis objek tersebut ke pipa dengan menggunakan Write-Output.

-Don Jones: Master PowerShell

Idealnya skrip Anda akan membuat objek Anda ( $obj = New-Object -TypeName psobject -Property @{'SomeProperty'='Test'}) lalu lakukan a Write-Output $objects. Anda akan menyalurkan output ke Format-Table.

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

Mereka harus benar-benar memanggil PowerShell PowerObjectandPipingShell.


4
Terima kasih Bob, saya telah menerima jawaban mjolinor karena saya merasa ini menjawab pertanyaan secara lebih langsung, namun saya belajar banyak dari tautan yang Anda berikan dan setuju bahwa dalam banyak kasus, Host Tulis tidak sesuai. Terima kasih!
Yohanes

1
Teknik yang sama akan berhasil, dan mungkin lebih cocok digunakan dengan Write-Verbose atau Write-Debug.
mjolinor

4
Saya tahu, saya terlambat bertahun-tahun, tetapi saya tidak setuju dengan Never use Write-Host.pernyataan. Anda tidak dapat menggunakan fungsi Write-Output di dalam yang mengembalikan data, karena akan "mencemari" fungsi ini. Contoh sederhana. Tebak fungsi ReturnText apa yang akan dihasilkan? Inilah mengapa saya selalu menggunakan fungsi dalam host-Write. function ReturnText () {Write-Output "Some random message" return "What I want to return"}
Denis Molodtsov

3
@Denisolodtsov Saya setuju sepenuhnya. Untuk tujuan pencatatan informasi, Write-Output TIDAK PERNAH digunakan kecuali jika Fungsi tersebut sepele. Begitu ada beberapa level fungsi dan Anda perlu mengembalikan output, Anda HARUS menggunakan sesuatu yang lain, dan Write-Host memenuhi tagihannya.
RobG

2
Write-Host juga akan segera disalurkan kembali dari sesi jarak jauh yang memungkinkan Anda untuk melihat kemajuan, dan jika sesi jarak jauh menimbulkan kesalahan, informasi Write-Output hilang.
RobG

3

Beberapa catatan umum.


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

Yang terakhir akan menampilkan semua properti non-intrinsik, non-kompilator. Mantan tidak tidak muncul untuk (selalu) menunjukkan semua jenis properti (di tes saya, itu tidak muncul untuk menunjukkan CodeProperty MemberTypesecara konsisten meskipun - tidak ada jaminan di sini).


Beberapa sakelar yang harus diperhatikan untuk Get-Member

  • Get-Membertidak tidak mendapatkan anggota statis secara default. Anda juga tidak bisa (secara langsung) membawanya bersama dengan anggota non-statis. Artinya, menggunakan sakelar menyebabkan hanya anggota statis yang dikembalikan:

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

    The Get-Memberperintah menggunakan Angkatan parameter untuk menambahkan anggota intrinsik dan anggota compiler yang dihasilkan dari objek untuk layar. Get-Membermendapatkan anggota ini, tetapi menyembunyikannya secara default.

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

Gunakan ConvertTo-Jsonuntuk "serialisasi" yang mendalam dan dapat dibaca

Saya tidak perlu merekomendasikan menyimpan objek menggunakan JSON (gunakan Export-Clixmlsebagai gantinya). Namun, Anda bisa mendapatkan lebih banyak atau lebih sedikit keluaran yang dapat dibaca ConvertTo-Json, yang juga memungkinkan Anda menentukan kedalaman.

Perhatikan bahwa tidak menentukan Depthberarti-Depth 2

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

Dan jika Anda tidak berencana untuk membacanya, Anda dapat -Compressmembacanya (yaitu menghapus spasi)

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

Gunakan -InputObjectjika Anda bisa (dan mau)

99,9% dari waktu saat menggunakan PowerShell: entah kinerjanya tidak penting, atau Anda tidak peduli dengan kinerjanya. Namun , perlu dicatat bahwa menghindari pipa saat Anda tidak membutuhkannya dapat menghemat overhead dan menambah kecepatan (pemipaan, secara umum, tidak super efisien).

Artinya, jika yang Anda miliki hanyalah satu yang $objberguna untuk dicetak (dan terkadang tidak terlalu malas seperti saya untuk mengetik -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

Peringatan untuk Get-Member -InputObject: Jika $ obj adalah sebuah koleksi (mis. System.Object[]), Anda akhirnya mendapatkan informasi tentang objek koleksi itu sendiri:

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

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

Jika Anda ingin Get-Memberuntuk setiap TypeNamedalam koleksi (NB untuk masing-masing TypeName, bukan untuk setiap objek - kumpulan N objek dengan semua yang sama TypeNamehanya akan mencetak 1 tabel untuk itu TypeName, bukan N tabel untuk setiap objek) ...... cukup tetap dengan menyalurkannya secara langsung.


1

Di bawah ini bekerja sangat baik untuk saya. Saya menambal semua jawaban di atas ditambah membaca tentang menampilkan properti objek di tautan berikut dan menghasilkan bacaan singkat di bawah ini tentang mencetak objek

tambahkan teks berikut ke file bernama print_object.ps1:

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

buka command prompt PowerShell, buka direktori tempat file itu ada dan ketik yang berikut ini:

powershell -ExecutionPolicy ByPass -File is_port_in_use.ps1 -Elevated

Cukup gantikan 'System.DateTime' dengan objek apa pun yang ingin Anda cetak. Jika objeknya null, tidak ada yang akan dicetak.


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.