Come puoi verificare se un oggetto ha una proprietà specifica?


93

Come puoi verificare se un oggetto ha una proprietà specifica?

Apprezzo che posso fare ...

$members = Get-Member -InputObject $myobject 

e poi foreachtramite $members, ma esiste una funzione per verificare se l'oggetto ha una proprietà specifica?

Informazioni aggiuntive: il problema è che sto importando due diversi tipi di file CSV, uno con due colonne, l'altro con tre. Non sono riuscito a far funzionare l'assegno con "Property", solo con "NoteProperty" ... qualunque sia la differenza

if ( ($member.MemberType -eq "NoteProperty" ) -and ($member.Name -eq $propertyName) ) 

6
($object.property -ne $null)?
arco444

2
Ha importanza se la proprietà esiste ma ha un $nullvalore
Matt

1
@ arco444 no - che richiede che la proprietà esista per avere successo. - Se disponi di dati dinamici (ad esempio da una richiesta web) in cui alcune righe non specificano nemmeno quella proprietà, il controllo fallirà. :(
BrainSlugs83

Risposte:


103

Come questo?

 [bool]($myObject.PSobject.Properties.name -match "myPropertyNameToTest")

16
Questa risposta funziona solo per PowerShell v3 o versioni successive. Quanto segue dovrebbe funzionare anche con powerShell v2 e versioni successive: [bool] ($ file.psobject.Properties | where {$ _. Name -eq "myPropertyNameToTest"})
Patrick

33
$myObject.PSobject.Properties.Name -contains "myPropertyNameToTest"è meglio. Non c'è bisogno di preoccuparsi della possibile corrispondenza del modello e non sarà nemmeno necessario eseguire il cast su Boolean.
Bacon Bits

2
E se l'oggetto ha la proprietà ThisisMyPropertye desideri verificarne la presenza MyProperty? Tutte le soluzioni in questa risposta risulteranno in un falso positivo.
Zoltán Tamási

3
@KolobCanyon che non funzionerà in modalità rigorosa.
user2864740

1
Questo codice darà un falso positivo se, ad esempio, stai testando per "Count" e l'oggetto aveva una proprietà chiamata "ThingCount".
dan-gph

72

Puoi usare Get-Member

if(Get-Member -inputobject $var -name "Property" -Membertype Properties){
#Property exists
}

12
Migliore risposta IMHO. Funziona con oggetti .NET che non dispongono di un membro PSobject. Possiamo anche rimuovere l'opzione -Membertype se non ci interessa quale tipo di membro contiene l'oggetto - solo il nome del membro. Molto utile con gli oggetti Invoke-RestMethod o ConvertFrom-Json!
Mister_Tom

2
Sintassi breve senza controllare il tipo if($var | Get-Member Property){ }if($var | gm Property){ }
:,

Questa è secondo me la migliore risposta.
Kiran Hegde

25

Questo è succinto e leggibile:

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

Possiamo metterlo in una funzione:

function HasProperty($object, $propertyName)
{
    $propertyName -in $object.PSobject.Properties.Name
}

Adoro questa risposta, ma sembra non funzionare in alcuni casi in cui funziona la risposta di CB.
edwin

Oppure, dove "succinct" = "inutile spazzatura introdotta tramite Strict Mode senza un buon caso di utilizzo di fallback" (cioè nessun ?.equivalente): | Questo fallirà anche per alcune varianti di $MyObject, in particolare $ null. Questo non era il caso del concatenamento di valori nulli al di fuori della modalità Strict.
user2864740

5

Ho usato quanto segue che restituisce il valore della proprietà, poiché sarebbe accessibile tramite$thing.$prop , se la "proprietà" dovesse esistere e non generare un'eccezione casuale. Se la proprietà "non esiste" (o ha un valore nullo) $nullviene restituita: questo approccio funziona in / è utile per la modalità rigorosa , perché, beh, Gonna Catch 'em All.

Trovo questo approccio utile perché consente a PS Custom Objects, normali oggetti .NET, PS HashTables e .NET raccolte come Dictionary di essere trattati come "equivalenti a forma di papera" , che trovo siano abbastanza adatti per PowerShell.

Naturalmente, questo non soddisfa la definizione rigorosa di "ha una proprietà" .. a cui questa domanda può essere esplicitamente limitata. Se si accetta la definizione più ampia di "proprietà" qui assunta, il metodo può essere banalmente modificato per restituire un valore booleano.

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

Esempi:

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"

E questo comportamento potrebbe non [sempre] essere desiderato .. cioè. non è possibile distinguere tra x.Counte x["Count"].


3

Per me MyProperty" -in $MyObject.PSobject.Properties.Nameperò non ha funzionato

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

lavori


2

Se stai usando StrictMode e psobject potrebbe essere vuoto, ti darà un errore.

A tutti gli effetti questo farà:

    if (($json.PSobject.Properties | Foreach {$_.Name}) -contains $variable)

1

Reale simile a un controllo javascript:

foreach($member in $members)
{
    if($member.PropertyName)
    {
        Write $member.PropertyName
    }
    else
    {
        Write "Nope!"
    }
}

1
Ciò potrebbe non funzionare se la proprietà ha effettivamente il valore $ null.
Tola Odejayi

8
Questo fallirà se PowerShell è in modalità rigorosa.
Ian Kemp

@IanKemp Cos'è la modalità rigorosa? Ti piace la politica di esecuzione?
Kolob Canyon

1
@KolobCanyon docs.microsoft.com/en-za/powershell/module/… - essenzialmente è l'equivalente PS di JavaScript use strict.
Ian Kemp

1
Anche questo non funzionerà se la proprietà esiste ed è impostata su $ false.

1

Giusto per chiarire dato il seguente oggetto

$Object

Con le seguenti proprietà

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

Quanto segue è vero

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

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

Quindi le risposte precedenti che verificano esplicitamente la proprietà in base al nome sono il modo più corretto per verificare che quella proprietà non sia presente.


1

Controlla solo con null.

($myObject.MyProperty -ne $null)

Se non hai impostato PowerShell su StrictMode , funziona anche se la proprietà non esiste:

$obj = New-Object PSObject;                                                   
Add-Member -InputObject $obj -MemberType NoteProperty -Name Foo -Value "Bar";
$obj.Foo; # Bar                                                                  
($obj.MyProperty -ne $null);  # False, no exception

2
Per quanto posso vedere, funziona se la proprietà esiste ed è $ null, ma non se la proprietà non esiste: il tentativo di accedervi per eseguire il controllo null genera un'eccezione.
Peter,

@Peter Puoi fornire un esempio del controllo nullo che genera un'eccezione quando la proprietà non esiste. Ho aggiunto un esempio in cui una proprietà non esiste e non ci sono eccezioni.
Shaun Luttin,

2
Esegui questo: 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}e riceverai un errore Impossibile trovare la proprietà "StartDate" su questo oggetto. Tuttavia, ho bisogno di qualificare il mio commento: non lo ottieni se Strictmode non è impostato. L'ho sempre impostato, quindi non me ne sono mai reso conto fino a quando non l'ho provato! Tuttavia, penso che la maggior parte delle persone usi (o dovrebbe usare) "Set-Strictmode".
Peter,

2
Probabilmente è meglio se qualifichi la tua risposta e rimuoverò il mio voto negativo? Tutti hanno imparato qualcosa, che è il punto :-)
Peter

0

Ho finito con la seguente funzione ...

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

0

Di recente sono passato alla versione 2.0 in modalità rigorosa e i miei test nulli non sono riusciti.

Ho aggiunto una funzione:

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

Ora codifico

if (exists $run main) { ...

piuttosto che

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

e siamo in viaggio. Sembra funzionare su oggetti e tabelle hash

Come vantaggio non intenzionale, è meno digitazione.


Per null o vuoto, ho sempre usato: IF ([string] :: IsNullOrEmpty ($ userID)) {write-host "Null or empty"}

0

Volevo solo aggiungere qualcosa alla discussione, perché ho passato ore a eseguire il debug di un codice che funzionava da qualche altra parte.

Risposta di CB. funziona bene per abbinare la variabile con i nomi delle proprietà (come stringhe). Il problema è iniziato quando la variabile corrisponde a una parte del nome di una proprietà.

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

Successivamente l'ho usato per fare riferimento alla proprietà di un oggetto, ma poiché corrispondeva solo a una parte di un'altra proprietà, quindi una proprietà effettiva con quel nome esatto non esisteva, l'operazione ha restituito il valore "null".

Solo successivamente ho usato la soluzione proposta da dan-gph , che è molto pulita:

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

Ciò ha garantito che i due valori fossero identici . Sapevo dove cercare, ma è stato doloroso anche solo capire che il problema è che diversi nomi corrispondono a stringhe con 2 caratteri. prefisso ma per il resto lo stesso.


-1

Ho appena iniziato a utilizzare PowerShell con PowerShell Core 6.0 (beta) e quanto segue funziona semplicemente:

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

o

if (-not $members.NoteProperty) {
   # NoteProperty does not exist
}

1
Non con modalità rigorosa attiva
Casper Leon Nielsen

-1

Potresti controllare con:

($Member.PropertyNames -contains "Name") ciò verificherà la proprietà Named


-1

Per identificare quali oggetti in un array hanno una proprietà

$HasProperty = $ArrayOfObjects | Where-Object {$_.MyProperty}

Non riesce in StrictMode quando la proprietà non esiste.
user2864740
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.