Wie können Sie testen, ob ein Objekt eine bestimmte Eigenschaft hat?

90

Wie können Sie testen, ob ein Objekt eine bestimmte Eigenschaft hat?

Schätzen Sie, dass ich tun kann ...

$members = Get-Member -InputObject $myobject 

und dann foreachdurch die $members, aber gibt es eine Funktion, um zu testen, ob das Objekt eine bestimmte Eigenschaft hat?

Zusätzliche Informationen: Das Problem ist, dass ich zwei verschiedene Arten von CSV-Dateien importiere, eine mit zwei Spalten, die andere mit drei. Ich konnte den Scheck nicht mit "Property" arbeiten lassen, nur mit "NoteProperty" ... was auch immer der Unterschied ist

if ( ($member.MemberType -eq "NoteProperty" ) -and ($member.Name -eq $propertyName) ) 
SteveC
quelle
6
($object.property -ne $null)?
Arco444
2
Ist es wichtig, ob das Eigentum existiert, aber einen $nullWert hat
Matt
@ arco444 nein - dafür muss die Eigenschaft vorhanden sein, damit sie erfolgreich ist. - Wenn Sie dynamische Daten haben (z. B. aus einer Webanforderung), in denen einige Zeilen diese Eigenschaft nicht einmal angeben, schlägt diese Prüfung fehl. :(
BrainSlugs83

Antworten:

96

So was?

 [bool]($myObject.PSobject.Properties.name -match "myPropertyNameToTest")
CB.
quelle
16
Diese Antwort funktioniert nur für PowerShell v3 oder höher. Folgendes sollte auch mit PowerShell v2 und höher funktionieren: [bool] ($ file.psobject.Properties | where {$ _. Name -eq "myPropertyNameToTest"})
AstralisSomnium
31
$myObject.PSobject.Properties.Name -contains "myPropertyNameToTest"ist besser. Sie müssen sich keine Gedanken über einen möglichen Mustervergleich machen, und Sie müssen dann auch nicht in Boolean umwandeln.
Bacon Bits
2
Was ist, wenn das Objekt die Eigenschaft hat ThisisMyPropertyund Sie danach suchen möchten MyProperty? Alle Lösungen in dieser Antwort führen zu einem falsch positiven Ergebnis.
Zoltán Tamási
3
@KolobCanyon Das funktioniert im Strict-Modus nicht.
user2864740
1
Dieser Code gibt ein falsches Positiv aus, wenn Sie beispielsweise auf "Count" getestet haben und das Objekt eine Eigenschaft namens "ThingCount" hatte.
Dan-Gph
66

Sie können verwenden Get-Member

if(Get-Member -inputobject $var -name "Property" -Membertype Properties){
#Property exists
}
Paul
quelle
12
Beste Antwort IMHO. Dies funktioniert mit .NET-Objekten, die kein PSobject-Mitglied haben. Wir können auch die Option -Membertype entfernen, wenn es uns egal ist, welchen Elementtyp das Objekt enthält - nur den Mitgliedsnamen. Sehr nützlich bei Invoke-RestMethod- oder ConvertFrom-Json-Objekten!
Mister_Tom
1
Kurze Syntax ohne Überprüfung des Typs : if($var | Get-Member Property){ }, noch kürzer, aber weniger lesbar:if($var | gm Property){ }
zett42
24

Dies ist kurz und lesbar:

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

Wir können es in eine Funktion setzen:

function HasProperty($object, $propertyName)
{
    $propertyName -in $object.PSobject.Properties.Name
}
dan-gph
quelle
Ich liebe diese Antwort, aber sie scheint in einigen Fällen nicht zu funktionieren, in denen die Antwort von CB dies tut.
Edwin
Oder wobei "prägnant" = "unnötiger Müll, der über den strengen Modus ohne einen guten Fallback-Anwendungsfall eingeführt wurde" (dh kein ?.Äquivalent): | Dies wird auch für bestimmte Variationen von $MyObject, insbesondere $ null, fehlschlagen . Dies war bei der Nullverkettung außerhalb des Strict Mode nicht der Fall.
user2864740
5

Ich habe Folgendes verwendet, das den Eigenschaftswert zurückgibt, über den zugegriffen werden würde$thing.$prop , wenn die "Eigenschaft" existieren und keine zufällige Ausnahme auslösen würde. Wenn die Eigenschaft "nicht existiert" (oder einen Nullwert hat), $nullwird sie zurückgegeben: Dieser Ansatz funktioniert im strengen Modus , da er alle abfangen wird.

Ich finde diesen Ansatz nützlich, da damit benutzerdefinierte PS-Objekte, normale .NET-Objekte, PS HashTables und .NET-Sammlungen wie Dictionary als "Enten-Typ-Äquivalent" behandelt werden können , was meiner Meinung nach ziemlich gut zu PowerShell passt.

Dies entspricht natürlich nicht der strengen Definition von "hat eine Eigenschaft", auf die diese Frage ausdrücklich beschränkt sein kann. Wenn die hier angenommene größere Definition von "Eigenschaft" akzeptiert wird, kann die Methode trivial geändert werden, um einen Booleschen Wert zurückzugeben.

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

Beispiele:

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"

Und dieses Verhalten ist möglicherweise nicht [immer] erwünscht. es ist nicht möglich zwischen x.Countund zu unterscheiden x["Count"].

user2864740
quelle
2

Wenn Sie StrictMode verwenden und das psobject möglicherweise leer ist, wird ein Fehler angezeigt.

Für alle Zwecke reicht dies aus:

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

Wirklich ähnlich wie bei einer Javascript-Prüfung:

foreach($member in $members)
{
    if($member.PropertyName)
    {
        Write $member.PropertyName
    }
    else
    {
        Write "Nope!"
    }
}
YtramX
quelle
1
Dies funktioniert möglicherweise nicht, wenn die Eigenschaft tatsächlich den Wert $ null hat.
Tola Odejayi
8
Dies schlägt fehl, wenn sich PowerShell im strengen Modus befindet.
Ian Kemp
@IanKemp Was ist der strikte Modus? Wie die Ausführungsrichtlinie?
Kolob Canyon
1
@KolobCanyon docs.microsoft.com/en-za/powershell/module/… - im Wesentlichen ist es das PS-Äquivalent zu JavaScript use strict.
Ian Kemp
1
Dies funktioniert auch nicht, wenn die Eigenschaft vorhanden ist und auf $ false gesetzt ist.
1

Nur um das folgende Objekt zu verdeutlichen

$Object

Mit den folgenden Eigenschaften

type        : message
user        : john.doe@company.com
text        : 
ts          : 11/21/2016 8:59:30 PM

Folgendes ist wahr

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

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

Die früheren Antworten, die explizit nach der Eigenschaft nach Namen suchen, sind daher die korrekteste Methode, um zu überprüfen, ob diese Eigenschaft nicht vorhanden ist.

John Mello
quelle
1

Einfach gegen Null prüfen.

($myObject.MyProperty -ne $null)

Wenn Sie PowerShell nicht auf StrictMode festgelegt haben , funktioniert dies auch dann, wenn die Eigenschaft nicht vorhanden ist:

$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
quelle
2
Soweit ich sehen kann, funktioniert dies, wenn die Eigenschaft vorhanden ist und $ null ist, aber nicht, wenn die Eigenschaft nicht vorhanden ist. Wenn Sie versuchen, darauf zuzugreifen, um die Nullprüfung durchzuführen, wird eine Ausnahme ausgelöst.
Peter
@Peter Können Sie ein Beispiel für die Nullprüfung angeben, die eine Ausnahme auslöst, wenn die Eigenschaft nicht vorhanden ist? Ich habe ein Beispiel hinzugefügt, in dem eine Eigenschaft nicht vorhanden ist und es keine Ausnahme gibt.
Shaun Luttin
2
Führen 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}Sie Folgendes aus : und Sie erhalten eine Fehler- Eigenschaft 'StartDate' kann für dieses Objekt nicht gefunden werden. Allerdings muss ich meinen Kommentar qualifizieren - man bekommt es nicht , wenn StrictMode nicht gesetzt ist. Ich habe es immer eingestellt, also erst realisiert, als ich es getestet habe! Dennoch denke ich, dass die meisten Leute 'Set-Strictmode' verwenden (oder verwenden sollten).
Peter
2
Wahrscheinlich am besten, wenn Sie Ihre Antwort qualifizieren und ich meine Ablehnung entfernen werde? Jeder hat etwas gelernt, worum es geht :-)
Peter
1

Bei mir hat es MyProperty" -in $MyObject.PSobject.Properties.Nameaber nicht geklappt

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

funktioniert

sebke CCU
quelle
0

Am Ende hatte ich folgende Funktion ...

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
quelle
0

Ich habe kürzlich auf Strict-Mode-Version 2.0 umgestellt und meine Null-Tests sind fehlgeschlagen.

Ich habe eine Funktion hinzugefügt:

#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
}

Jetzt codiere ich

if (exists $run main) { ...

eher, als

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

und wir sind auf dem Weg. Scheint an Objekten und Hashtabellen zu arbeiten

Als unbeabsichtigter Vorteil ist es weniger tippen.

Steve Pritchard
quelle
Für null oder leer habe ich immer verwendet: IF ([string] :: IsNullOrEmpty ($ userID)) {Schreibhost "Null oder leer"}
-1

Ich habe gerade angefangen, PowerShell mit PowerShell Core 6.0 (Beta) zu verwenden, und Folgendes funktioniert einfach:

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

oder

if (-not $members.NoteProperty) {
   # NoteProperty does not exist
}
hshib
quelle
1
Nicht mit striktem Modus auf
Casper Leon Nielsen
-1

Sie könnten überprüfen mit:

($Member.PropertyNames -contains "Name") Dadurch wird nach der Named-Eigenschaft gesucht

Tom Stryhn
quelle
-1

Zum Identifizieren, welche der Objekte in einem Array eine Eigenschaft haben

$HasProperty = $ArrayOfObjects | Where-Object {$_.MyProperty}
korkig
quelle
Schlägt im StrictMode fehl, wenn die Eigenschaft nicht vorhanden ist.
user2864740