Comment tester si un objet a une propriété spécifique?

93

Comment tester si un objet a une propriété spécifique?

J'apprécie que je puisse faire ...

$members = Get-Member -InputObject $myobject 

puis foreachvia le $members, mais y a-t-il une fonction pour tester si l'objet a une propriété spécifique?

Informations supplémentaires: le problème est que j'importe deux types de fichiers CSV, l'un avec deux colonnes, l'autre avec trois. Je n'ai pas pu faire fonctionner le chèque avec "Propriété", uniquement avec "NoteProperty" ... quelle que soit la différence

if ( ($member.MemberType -eq "NoteProperty" ) -and ($member.Name -eq $propertyName) ) 
SteveC
la source
6
($object.property -ne $null)?
arco444
2
Est-ce important si la propriété existe mais a une $nullvaleur
Matt
1
@ arco444 non - cela nécessite que la propriété existe pour réussir. - Si vous avez des données dynamiques (c'est-à-dire provenant d'une requête Web) où certaines lignes ne spécifient même pas cette propriété, cette vérification échouera. :(
BrainSlugs83

Réponses:

104

Comme ça?

 [bool]($myObject.PSobject.Properties.name -match "myPropertyNameToTest")
CB.
la source
16
Cette réponse ne fonctionne que pour powerShell v3 ou supérieur. Ce qui suit devrait fonctionner même avec powerShell v2 et supérieur: [bool] ($ file.psobject.Properties | where {$ _. Name -eq "myPropertyNameToTest"})
Patrick
33
$myObject.PSobject.Properties.Name -contains "myPropertyNameToTest"est mieux. Pas besoin de s'inquiéter de la possible correspondance de modèles, et vous n'aurez pas non plus besoin de convertir en booléen.
Bacon Bits
2
Que faire si l'objet possède la propriété ThisisMyPropertyet que vous souhaitez vérifier MyProperty? Toutes les solutions de cette réponse entraîneront un faux positif.
Zoltán Tamási
3
@KolobCanyon Cela ne fonctionnera pas en mode strict.
user2864740
1
Ce code donnera un faux positif si par exemple vous testez "Count" et que l'objet avait une propriété appelée "ThingCount".
dan-gph
72

Vous pouvez utiliser Get-Member

if(Get-Member -inputobject $var -name "Property" -Membertype Properties){
#Property exists
}
Paul
la source
12
Meilleure réponse à mon humble avis. Cela fonctionne avec les objets .NET qui n'ont pas de membre PSobject. Nous pouvons également supprimer l'option -Membertype si nous ne nous soucions pas du type de membre que l'objet contient - juste le nom du membre. Très utile avec les objets Invoke-RestMethod ou ConvertFrom-Json!
Mister_Tom
2
Syntaxe courte sans vérification de type if($var | Get-Member Property){ }if($var | gm Property){ }
:,
C'est à mon avis la meilleure réponse.
Kiran Hegde
25

Ceci est succinct et lisible:

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

On peut le mettre dans une fonction:

function HasProperty($object, $propertyName)
{
    $propertyName -in $object.PSobject.Properties.Name
}
dan-gph
la source
J'adore cette réponse, mais elle semble ne pas fonctionner dans certains cas où la réponse de CB fonctionne.
edwin
Ou, où "succinct" = "indésirable inutile introduit via le mode strict sans un bon cas d'utilisation de secours" (c'est-à-dire sans ?.équivalent): | Cela échouera également pour certaines variations de $MyObject, notamment $ null. Tel n'était pas le cas avec le chaînage nul en dehors du mode strict.
user2864740
5

J'ai utilisé ce qui suit qui renvoie la valeur de la propriété, car elle serait accessible via$thing.$prop , si la "propriété" devait exister et ne pas lancer une exception aléatoire. Si la propriété "n'existe pas" (ou a une valeur nulle) alors $nullest retournée: cette approche fonctionne en / est utile pour le mode strict , car, eh bien, va les attraper tous.

Je trouve cette approche utile car elle permet aux objets personnalisés PS, aux objets .NET normaux, aux HashTables PS et aux collections .NET comme Dictionary d'être traités comme des «équivalents de type canard» , ce qui, à mon avis, convient assez bien à PowerShell.

Bien entendu, cela ne répond pas à la définition stricte de "possède une propriété" .. à laquelle cette question peut être explicitement limitée. Si vous acceptez la définition plus large de "propriété" supposée ici, la méthode peut être modifiée de manière triviale pour renvoyer un booléen.

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

Exemples:

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"

Et, ce comportement pourrait ne pas [toujours] être souhaité .. ie. il n'est pas possible de faire la distinction entre x.Countet x["Count"].

user2864740
la source
3

Pour moi MyProperty" -in $MyObject.PSobject.Properties.Namen'a pas fonctionné, cependant

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

travaux

sebke CCU
la source
2

Si vous utilisez StrictMode et que le psobject est peut-être vide, cela vous donnera une erreur.

À toutes fins, cela fera:

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

Réel similaire à une vérification javascript:

foreach($member in $members)
{
    if($member.PropertyName)
    {
        Write $member.PropertyName
    }
    else
    {
        Write "Nope!"
    }
}
YtramX
la source
1
Cela peut ne pas fonctionner si la propriété a réellement la valeur $ null.
Tola Odejayi
8
Cela échouera si PowerShell est en mode strict.
Ian Kemp
@IanKemp Qu'est-ce que le mode strict? Vous aimez la politique d'exécution?
Kolob Canyon
1
@KolobCanyon docs.microsoft.com/en-za/powershell/module/… - c'est essentiellement l'équivalent PS de JavaScript use strict.
Ian Kemp
1
Cela ne fonctionnera pas non plus si la propriété existe et est définie sur $ false.
1

Juste pour clarifier compte tenu de l'objet suivant

$Object

Avec les propriétés suivantes

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

Ce qui suit est vrai

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

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

Ainsi, les réponses précédentes qui vérifient explicitement la propriété par son nom sont le moyen le plus correct de vérifier que cette propriété n'est pas présente.

John Mello
la source
1

Vérifiez simplement la valeur nulle.

($myObject.MyProperty -ne $null)

Si vous n'avez pas défini PowerShell sur StrictMode , cela fonctionne même si la propriété n'existe pas:

$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
la source
2
Pour autant que je puisse voir, cela fonctionne si la propriété existe et est $ null, mais pas si la propriété n'existe pas - tenter d'y accéder pour faire la vérification null lève une exception.
Peter
@Peter Pouvez-vous fournir un exemple de vérification de null lançant une exception lorsque la propriété n'existe pas. J'ai ajouté un exemple dans lequel une propriété n'existe pas et il n'y a pas d'exception.
Shaun Luttin le
2
Exécutez ceci: 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}et vous obtiendrez une erreur La propriété 'StartDate' ne peut pas être trouvée sur cet objet. Cependant, je dois nuancer mon commentaire - vous ne l'obtiendrez pas si Strictmode n'est pas défini. Je l'ai toujours réglé, donc je ne m'en suis jamais rendu compte avant de l'avoir testé! Pourtant, je pense que la plupart des gens utilisent (ou devraient utiliser) 'Set-Strictmode'.
Peter
2
Probablement mieux si vous qualifiez votre réponse, et je retirerai mon vote défavorable? Tout le monde a appris quelque chose, qui est le point :-)
Peter
0

J'ai fini avec la fonction suivante ...

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
la source
0

Je suis récemment passé à la version 2.0 en mode strict et mes tests nuls ont échoué.

J'ai ajouté une fonction:

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

Maintenant je code

if (exists $run main) { ...

plutôt que

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

et nous sommes en route. Semble fonctionner sur des objets et des hashtables

En tant qu'avantage involontaire, c'est moins de frappe.

Steve Pritchard
la source
Pour null ou vide, j'ai toujours utilisé: IF ([string] :: IsNullOrEmpty ($ userID)) {write-host "Null or empty"}
0

Je voulais juste ajouter à la discussion, car je viens de passer des heures à déboguer un code qui fonctionnait ailleurs.

Réponse de CB. fonctionne bien pour faire correspondre la variable avec les noms des propriétés (sous forme de chaînes). Le problème a commencé lorsque la variable correspondait à une partie d'un nom de propriété.

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

Plus tard, je l'ai utilisé pour faire référence à la propriété d'un objet, mais comme il ne correspondait qu'à une partie d'une autre propriété, une propriété réelle avec ce nom exact n'existait pas, l'opération a renvoyé la valeur «null».

Ce n'est que plus tard que j'ai utilisé la solution proposée par dan-gph , qui est très soignée:

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

Cela garantissait que les deux valeurs étaient identiques . Je savais où chercher, mais c'était encore difficile de comprendre que le problème était que plusieurs noms correspondent à des chaînes avec 2 caractères. préfixe mais sinon le même.

Byron
la source
-1

Je viens de commencer à utiliser PowerShell avec PowerShell Core 6.0 (bêta) et ce qui suit fonctionne simplement:

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

ou

if (-not $members.NoteProperty) {
   # NoteProperty does not exist
}
hshib
la source
1
Pas avec strictmode activé
Casper Leon Nielsen
-1

Vous pouvez vérifier avec:

($Member.PropertyNames -contains "Name") cela vérifiera la propriété nommée

Tom Stryhn
la source
-1

Pour identifier les objets d'un tableau qui ont une propriété

$HasProperty = $ArrayOfObjects | Where-Object {$_.MyProperty}
bouché
la source
Échoue dans StrictMode lorsque la propriété n'existe pas.
user2864740