Bagaimana Anda bisa menguji apakah suatu benda memiliki properti tertentu?

93

Bagaimana Anda bisa menguji apakah suatu benda memiliki properti tertentu?

Menghargai yang bisa saya lakukan ...

$members = Get-Member -InputObject $myobject 

dan kemudian foreachmelalui $members, tetapi apakah ada fungsi untuk menguji apakah objek tersebut memiliki properti tertentu?

Info Tambahan: Masalahnya adalah saya mengimpor dua jenis file CSV yang berbeda, satu dengan dua kolom, yang lainnya dengan tiga. Saya tidak bisa mendapatkan cek untuk bekerja dengan "Properti", hanya dengan "NoteProperty" ... apa pun perbedaannya

if ( ($member.MemberType -eq "NoteProperty" ) -and ($member.Name -eq $propertyName) ) 
SteveC
sumber
6
($object.property -ne $null)?
arco444
2
Apakah penting jika propery memang ada tetapi memiliki $nullnilai
Matt
1
@ arco444 tidak - yang mengharuskan properti ada agar berhasil. - Jika Anda memiliki data dinamis (yaitu dari permintaan web) di mana beberapa baris bahkan tidak menentukan properti itu, pemeriksaan itu akan gagal. :(
BrainSlugs83

Jawaban:

104

Seperti ini?

 [bool]($myObject.PSobject.Properties.name -match "myPropertyNameToTest")
CB.
sumber
16
Jawaban ini hanya berfungsi untuk powerShell v3 atau lebih tinggi. Berikut ini akan bekerja bahkan dengan powerShell v2 dan yang lebih baru: [bool] ($ file.psobject.Properties | where {$ _. Name -eq "myPropertyNameToTest"})
Patrick
33
$myObject.PSobject.Properties.Name -contains "myPropertyNameToTest"lebih baik. Tidak perlu khawatir tentang kemungkinan pencocokan pola, dan Anda juga tidak perlu melakukan cast ke Boolean.
Bacon Bits
2
Bagaimana jika objek tersebut memiliki properti ThisisMyPropertydan Anda ingin memeriksanya MyProperty? Semua solusi dalam jawaban ini akan menghasilkan positif palsu.
Zoltán Tamási
3
@KolobCanyon Itu tidak akan berfungsi dalam Mode Ketat.
pengguna2864740
1
Kode ini akan memberikan positif palsu jika misalnya Anda di mana menguji "Count" dan objek tersebut memiliki properti yang disebut "ThingCount".
dan-gph
72

Kamu bisa memakai Get-Member

if(Get-Member -inputobject $var -name "Property" -Membertype Properties){
#Property exists
}
Paul
sumber
12
Jawaban terbaik IMHO. Ini bekerja dengan objek .NET yang tidak memiliki anggota PSobject. Kita juga dapat menghapus opsi -Membertype jika kita tidak peduli tipe anggota mana yang dikandung objek - hanya nama anggota. Sangat berguna dengan objek Invoke-RestMethod atau ConvertFrom-Json!
Mister_Tom
2
Sintaks pendek tanpa memeriksa jenis if($var | Get-Member Property){ }if($var | gm Property){ }
:,
Ini menurut saya jawaban terbaik.
Kiran Hegde
25

Ini ringkas dan mudah dibaca:

"MyProperty" -in $MyObject.PSobject.Properties.Name

Kita bisa memasukkannya ke dalam sebuah fungsi:

function HasProperty($object, $propertyName)
{
    $propertyName -in $object.PSobject.Properties.Name
}
dan-gph
sumber
Saya suka jawaban ini, tetapi tampaknya tidak berhasil dalam beberapa kasus di mana jawaban CB berfungsi.
edwin
Atau, di mana "ringkas" = "sampah yang tidak perlu dimasukkan melalui Mode Ketat tanpa kasus penggunaan cadangan yang baik" (yaitu, tidak ada ?.padanannya): | Ini juga akan gagal untuk variasi tertentu $MyObject, terutama $ null. Tidak demikian halnya dengan rantai-nol di luar Mode Ketat.
pengguna2864740
5

Saya telah menggunakan berikut ini yang mengembalikan nilai properti, karena akan diakses melalui$thing.$prop , jika "properti" akan ada dan tidak membuang pengecualian acak. Jika properti "tidak ada" (atau memiliki nilai null) maka $nulldikembalikan: fungsi pendekatan ini di / berguna untuk mode ketat , karena, yah, Gonna Catch 'em All.

Saya menemukan pendekatan ini berguna karena memungkinkan PS Custom Objects, normal .NET Objects, PS HashTables, dan koleksi .NET seperti Dictionary untuk diperlakukan sebagai "setara dengan tipe bebek" , yang menurut saya cukup cocok untuk PowerShell.

Tentu saja, ini tidak memenuhi definisi yang ketat tentang "memiliki properti" .. yang mungkin dibatasi secara eksplisit oleh pertanyaan ini. Jika menerima definisi yang lebih besar dari "properti" yang diasumsikan di sini, metode tersebut dapat dimodifikasi secara sederhana untuk mengembalikan boolean.

Function Get-PropOrNull {
    param($thing, [string]$prop)
    Try {
        $thing.$prop
    } Catch {
    }
}

Contoh:

Get-PropOrNull (Get-Date) "Date"                   # => Monday, February 05, 2018 12:00:00 AM
Get-PropOrNull (Get-Date) "flub"                   # => $null
Get-PropOrNull (@{x="HashTable"}) "x"              # => "HashTable"
Get-PropOrNull ([PSCustomObject]@{x="Custom"}) "x" # => "Custom"
$oldDict = New-Object "System.Collections.HashTable"
$oldDict["x"] = "OldDict"
Get-PropOrNull $d "x"                              # => "OldDict"

Dan, perilaku ini mungkin [selalu] tidak diinginkan .. yaitu. tidak mungkin membedakan antara x.Countdan x["Count"].

pengguna2864740
sumber
3

Namun, bagi saya MyProperty" -in $MyObject.PSobject.Properties.Nametidak berhasil

$MyObject.PSobject.Properties.Name.Contains("MyProperty")

bekerja

sebke CCU
sumber
2

Jika Anda menggunakan StrictMode dan psobject mungkin kosong, itu akan memberi Anda kesalahan.

Untuk semua tujuan ini akan dilakukan:

    if (($json.PSobject.Properties | Foreach {$_.Name}) -contains $variable)
Ádám Kovács
sumber
1

Sangat mirip dengan pemeriksaan javascript:

foreach($member in $members)
{
    if($member.PropertyName)
    {
        Write $member.PropertyName
    }
    else
    {
        Write "Nope!"
    }
}
YtramX
sumber
1
Ini mungkin tidak berfungsi jika properti sebenarnya memiliki nilai $ null.
Tola Odejayi
8
Ini akan gagal jika PowerShell dalam mode ketat.
Ian Kemp
@IanKemp Apa itu mode ketat? Suka Kebijakan Eksekusi?
Kolob Canyon
1
@KolobCanyon docs.microsoft.com/en-za/powershell/module/… - pada dasarnya ini adalah PS yang setara dengan JavaScript use strict.
Ian Kemp
1
Ini juga tidak akan berfungsi jika propertinya ada, dan disetel ke $ false.
1

Hanya untuk memperjelas diberikan objek berikut

$Object

Dengan properti berikut

type        : message
user        : [email protected]
text        : 
ts          : 11/21/2016 8:59:30 PM

Berikut ini adalah benar

$Object.text -eq $NULL
$Object.NotPresent -eq $NULL

-not $Object.text
-not $Object.NotPresent

Jadi jawaban sebelumnya yang secara eksplisit memeriksa properti berdasarkan nama adalah cara paling benar untuk memverifikasi bahwa properti itu tidak ada.

John Mello
sumber
1

Periksa saja terhadap nol.

($myObject.MyProperty -ne $null)

Jika Anda belum menyetel PowerShell ke StrictMode , ini berfungsi bahkan jika properti tidak ada:

$obj = New-Object PSObject;                                                   
Add-Member -InputObject $obj -MemberType NoteProperty -Name Foo -Value "Bar";
$obj.Foo; # Bar                                                                  
($obj.MyProperty -ne $null);  # False, no exception
Shaun Luttin
sumber
2
Sejauh yang saya bisa lihat, ini berfungsi jika properti itu ada dan $ null, tetapi tidak jika properti itu tidak ada - mencoba mengaksesnya untuk melakukan pemeriksaan null akan membuat pengecualian.
Peter
@Peter Dapatkah Anda memberikan contoh pemeriksaan null yang membuat pengecualian saat properti tidak ada. Saya telah menambahkan contoh di mana properti tidak ada dan tidak ada pengecualian.
Shaun Luttin
2
Jalankan ini: Set-Strictmode -version Latest;$obj = ConvertFrom-Json -InputObject '{"name":"test", "version":"1.1.0"}';If($obj.StartDate -ne $null){Write-Verbose -Message $obj.startDate -Verbose}dan Anda akan mendapatkan kesalahan Properti 'StartDate' tidak dapat ditemukan pada objek ini. Namun saya perlu mengkualifikasikan komentar saya - Anda tidak mengerti jika Strictmode tidak disetel. Saya selalu mengaturnya, jadi tidak pernah menyadari sampai saya mengujinya! Namun, saya pikir kebanyakan orang menggunakan (atau harus menggunakan) 'Set-Strictmode'.
Peter
2
Mungkin paling baik jika Anda memenuhi syarat untuk jawaban Anda, dan saya akan menghapus suara negatif saya? Setiap orang telah belajar sesuatu, yang intinya :-)
Peter
0

Saya berakhir dengan fungsi berikut ...

function HasNoteProperty(
    [object]$testObject,
    [string]$propertyName
)
{
    $members = Get-Member -InputObject $testObject 
    if ($members -ne $null -and $members.count -gt 0) 
    { 
        foreach($member in $members) 
        { 
            if ( ($member.MemberType -eq "NoteProperty" )  -and `
                 ($member.Name       -eq $propertyName) ) 
            { 
                return $true 
            } 
        } 
        return $false 
    } 
    else 
    { 
        return $false; 
    }
}
SteveC
sumber
0

Saya baru-baru ini beralih untuk menyetel mode-ketat -versi 2.0 dan pengujian null saya gagal.

Saya menambahkan fungsi:

#use in strict mode to validate property exists before using
function exists {
  param($obj,$prop)
  try {
    if ($null -ne $obj[$prop]) {return $true}
    return $false
  } catch {
    return $false
  }
  return $false
}

Sekarang saya membuat kode

if (exists $run main) { ...

daripada

if ($run.main -ne $null) { ...

dan kami sedang dalam perjalanan. Sepertinya bekerja pada objek dan hashtables

Sebagai manfaat yang tidak disengaja, ini adalah lebih sedikit mengetik.

Steve Pritchard
sumber
Untuk null atau kosong, saya selalu menggunakan: IF ([string] :: IsNullOrEmpty ($ userID)) {write-host "Null or empty"}
0

Saya hanya ingin menambahkan ke diskusi, karena saya hanya menghabiskan berjam-jam men-debug kode yang berfungsi di tempat lain.

Jawaban oleh CB. berfungsi dengan baik untuk mencocokkan variabel dengan nama properti (sebagai string). Masalah dimulai ketika variabel cocok dengan bagian dari nama properti.

if([bool]($allFiles.PSobject.Properties.name -match $_.Name) -ne $true){

Kemudian saya menggunakannya untuk merujuk ke properti objek, tetapi karena properti itu hanya cocok dengan sebagian dari properti lain sehingga properti sebenarnya dengan nama persis itu tidak ada, operasi mengembalikan nilai 'null'.

Baru kemudian saya menggunakan solusi yang diusulkan oleh dan-gph , yang sangat rapi:

if([bool]($_.Name -in $allFiles.PSobject.Properties.Name) -ne $true){

Ini memastikan bahwa kedua nilai itu identik . Saya tahu di mana mencarinya tetapi tetap saja menyakitkan bahkan untuk mengetahui bahwa masalahnya adalah beberapa nama yang cocok dengan 2 karakter. prefiks tetapi sebaliknya sama.

Byron
sumber
-1

Saya baru saja mulai menggunakan PowerShell dengan PowerShell Core 6.0 (beta) dan berikut ini berfungsi:

if ($members.NoteProperty) {
   # NoteProperty exist
}

atau

if (-not $members.NoteProperty) {
   # NoteProperty does not exist
}
hshib
sumber
1
Tidak dengan mode tightmode aktif
Casper Leon Nielsen
-1

Anda dapat memeriksa dengan:

($Member.PropertyNames -contains "Name") ini akan memeriksa properti Bernama

Tom Stryhn
sumber
-1

Untuk mengidentifikasi objek mana dalam array yang memiliki properti

$HasProperty = $ArrayOfObjects | Where-Object {$_.MyProperty}
periang
sumber
Gagal di StrictMode saat properti tidak ada.
pengguna2864740