Jak sprawdzić, czy obiekt ma określoną właściwość?

93

Jak sprawdzić, czy obiekt ma określoną właściwość?

Doceniam, że mogę ...

$members = Get-Member -InputObject $myobject 

a następnie foreachza pomocą $members, ale czy istnieje funkcja do sprawdzenia, czy obiekt ma określoną właściwość?

Dodatkowe informacje: Problem polega na tym, że importuję dwa różne rodzaje plików CSV, jeden z dwiema kolumnami, a drugi z trzema. Nie mogłem sprawić, by czek działał z „Property”, tylko z „NoteProperty” ... niezależnie od różnicy

if ( ($member.MemberType -eq "NoteProperty" ) -and ($member.Name -eq $propertyName) ) 
SteveC
źródło
6
($object.property -ne $null)?
arco444
2
Czy to ma znaczenie, czy właściwość istnieje, ale ma $nullwartość
Matt
1
@ arco444 nope - aby odnieść sukces, musi istnieć właściwość. - Jeśli masz dane dynamiczne (np. Z żądania internetowego), w których niektóre wiersze nawet nie określają tej właściwości, to sprawdzenie zakończy się niepowodzeniem. :(
BrainSlugs83

Odpowiedzi:

104

Lubię to?

 [bool]($myObject.PSobject.Properties.name -match "myPropertyNameToTest")
CB.
źródło
16
Ta odpowiedź działa tylko w przypadku programu PowerShell w wersji 3 lub nowszej. Poniższe powinno działać nawet z PowerShell v2 i nowszymi: [bool] ($ file.psobject.Properties | gdzie {$ _. Name -eq "myPropertyNameToTest"})
Patrick
33
$myObject.PSobject.Properties.Name -contains "myPropertyNameToTest"jest lepiej. Nie musisz się martwić o możliwe dopasowanie wzorców, a wtedy nie będziesz też musiał rzucać na Boolean.
Bacon Bits
2
A jeśli obiekt ma tę właściwość ThisisMyPropertyi chciałbyś sprawdzić MyProperty? Wszystkie rozwiązania w tej odpowiedzi spowodują fałszywie pozytywny wynik.
Zoltán Tamási,
3
@KolobCanyon To nie będzie działać w trybie ścisłym.
user2864740
1
Ten kod da fałszywie dodatni wynik, jeśli na przykład testowanie pod kątem „Count” ma właściwość o nazwie „ThingCount”.
dan-gph
72

Możesz użyć Get-Member

if(Get-Member -inputobject $var -name "Property" -Membertype Properties){
#Property exists
}
Paweł
źródło
12
Najlepsza odpowiedź IMHO. Działa to z obiektami .NET, które nie mają elementu PSobject. Możemy również usunąć opcję -Membertype, jeśli nie obchodzi nas, jaki typ elementu członkowskiego zawiera obiekt - tylko nazwę elementu członkowskiego. Bardzo przydatne w przypadku obiektów Invoke-RestMethod lub ConvertFrom-Json!
Mister_Tom,
2
Krótka składnia bez sprawdzania typu if($var | Get-Member Property){ }if($var | gm Property){ }
:,
To moim zdaniem najlepsza odpowiedź.
Kiran Hegde
25

To jest zwięzłe i czytelne:

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

Możemy umieścić to w funkcji:

function HasProperty($object, $propertyName)
{
    $propertyName -in $object.PSobject.Properties.Name
}
dan-gph
źródło
Uwielbiam tę odpowiedź, ale wydaje się, że nie działa w niektórych przypadkach, w których działa odpowiedź CB.
edwin
Lub, gdzie „succinct” = „niepotrzebne śmieci wprowadzone przez tryb ścisły bez dobrego awaryjnego przypadku użycia” (tj. Bez ?.odpowiednika): | To również zakończy się niepowodzeniem w przypadku niektórych odmian $MyObject, w szczególności $ null. Tak nie było w przypadku zerowania łańcuchowego poza trybem ścisłym.
user2864740
5

Używałem następującego, które zwraca wartość właściwości, tak jak byłoby to dostępne za pośrednictwem$thing.$prop , gdyby „właściwość” miała istnieć i nie zgłaszać losowego wyjątku. Jeśli właściwość „nie istnieje” (lub ma wartość null), to $nulljest zwracana: to podejście działa w / jest przydatne w trybie ścisłym , ponieważ, no cóż, Gonna Catch 'em All.

Uważam, że to podejście jest przydatne, ponieważ pozwala obiektom niestandardowym PS, zwykłym obiektom .NET, tabelom PS HashTables i kolekcjom .NET, takim jak Dictionary, być traktowane jako „odpowiedniki pisane kaczką” , co moim zdaniem dobrze pasuje do programu PowerShell.

Oczywiście nie spełnia to ścisłej definicji „ma właściwość”… do której to pytanie można wyraźnie ograniczyć. Jeśli zaakceptujesz szerszą definicję „właściwości” przyjętą w tym miejscu, metoda może zostać w trywialny sposób zmodyfikowana, aby zwracała wartość logiczną.

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

Przykłady:

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"

I takie zachowanie może nie [zawsze] być pożądane… tj. nie można odróżnić od x.Counti x["Count"].

user2864740
źródło
3

U mnie MyProperty" -in $MyObject.PSobject.Properties.Namejednak nie działało

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

Pracuje

sebke CCU
źródło
2

Jeśli używasz StrictMode i psobject może być pusty, wyświetli się błąd.

Do wszystkich celów wystarczy:

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

Rzeczywiste podobne do sprawdzania javascript:

foreach($member in $members)
{
    if($member.PropertyName)
    {
        Write $member.PropertyName
    }
    else
    {
        Write "Nope!"
    }
}
YtramX
źródło
1
Może to nie zadziałać, jeśli właściwość faktycznie ma wartość $ null.
Tola Odejayi
8
To się nie powiedzie, jeśli PowerShell jest w trybie ścisłym.
Ian Kemp
@IanKemp Co to jest tryb ścisły? Podobnie jak zasady wykonywania?
Kolob Canyon
1
@KolobCanyon docs.microsoft.com/en-za/powershell/module/ ... - w zasadzie jest to odpowiednik PS w JavaScript use strict.
Ian Kemp
1
To również nie zadziała, jeśli właściwość istnieje i jest ustawiona na $ false.
1

Aby wyjaśnić, biorąc pod uwagę następujący przedmiot

$Object

Z następującymi właściwościami

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

Oto prawda

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

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

Zatem wcześniejsze odpowiedzi, które jawnie sprawdzają właściwość według nazwy, są najbardziej poprawnym sposobem sprawdzenia, czy ta właściwość nie istnieje.

John Mello
źródło
1

Po prostu sprawdź null.

($myObject.MyProperty -ne $null)

Jeśli nie ustawiłeś PowerShell na StrictMode , działa to nawet jeśli właściwość nie istnieje:

$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
źródło
2
O ile widzę, działa to, jeśli właściwość istnieje i ma wartość $ null, ale nie, jeśli właściwość nie istnieje - próba uzyskania do niej dostępu w celu sprawdzenia wartości null zgłasza wyjątek.
Peter
@Peter Czy możesz podać przykład sprawdzania wartości null rzucającej wyjątek, gdy właściwość nie istnieje. Dodałem przykład, w którym nieruchomość nie istnieje i nie ma wyjątku.
Shaun Luttin
2
Uruchom to: 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}a pojawi się błąd Właściwość „StartDate” nie może zostać znaleziona w tym obiekcie. Muszę jednak zakwalifikować mój komentarz - nie otrzymasz go, jeśli nie jest ustawiony tryb Strictmode. Zawsze mam to ustawione, więc nigdy nie zdawałem sobie sprawy, dopóki nie przetestowałem tego! Mimo to myślę, że większość ludzi używa (lub powinna używać) „Set-Strictmode”.
Peter
2
Prawdopodobnie najlepiej, jeśli zakwalifikujesz swoją odpowiedź, a ja usunę mój głos przeciw? Każdy się czegoś nauczył, o co chodzi :-)
Peter
0

Skończyło się na następującej funkcji ...

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
źródło
0

Niedawno przełączyłem się na ustawienie trybu ścisłego w wersji 2.0 i moje testy zerowe zakończyły się niepowodzeniem.

Dodałem funkcję:

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

Teraz koduję

if (exists $run main) { ...

zamiast

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

i jesteśmy w drodze. Wydaje się, że działa na obiektach i tablicach skrótów

Niezamierzona korzyść to mniej pisania.

Steve Pritchard
źródło
Dla wartości null lub pustej zawsze używałem: IF ([string] :: IsNullOrEmpty ($ userID)) {write-host "Null or empty"}
0

Chciałem tylko coś dodać do dyskusji, ponieważ spędziłem godziny na debugowaniu kodu, który działał gdzie indziej.

Odpowiedz przez CB. sprawdza się dobrze przy dopasowywaniu zmiennej do nazw właściwości (jako ciągi znaków). Problem zaczął się, gdy zmienna pasowała do części nazwy właściwości.

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

Później użyłem go do odniesienia się do właściwości obiektu, ale ponieważ pasował tylko do części innej właściwości, więc rzeczywista właściwość o tej dokładnej nazwie nie istniała, operacja zwróciła wartość „null”.

Dopiero później skorzystałem z rozwiązania zaproponowanego przez dan-gph , które jest bardzo zgrabne:

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

Zapewniło to, że te dwie wartości były identyczne . Wiedziałem, gdzie szukać, ale i tak trudno było zrozumieć, że problem polega na tym, że kilka nazw łączy ciągi znaków z 2 znakami. prefiks, ale poza tym to samo.

Byron
źródło
-1

Właśnie zacząłem używać PowerShell z PowerShell Core 6.0 (beta) i po prostu działa:

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

lub

if (-not $members.NoteProperty) {
   # NoteProperty does not exist
}
hshib
źródło
1
Nie z włączonym trybem ścisłym
Casper Leon Nielsen
-1

Możesz sprawdzić:

($Member.PropertyNames -contains "Name") spowoduje to sprawdzenie właściwości Named

Tom Stryhn
źródło
-1

Do określenia, które obiekty w tablicy mają właściwość

$HasProperty = $ArrayOfObjects | Where-Object {$_.MyProperty}
korkowy
źródło
Błąd w StrictMode, gdy właściwość nie istnieje.
user2864740