[powershell] How can you test if an object has a specific property?

How can you test if an object has a specific property?

Appreciate I can do ...

$members = Get-Member -InputObject $myobject 

and then foreach through the $members, but is there a function to test if the object has a specific property?

Additional Info: The issue is I'm importing two different sorts of CSV file, one with two columns, the other with three. I couldn't get the check to work with "Property", only with "NoteProperty" ... whatever the difference is

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

This question is related to powershell powershell-3.0

The answer is


Just to clarify given the following object

$Object

With the following properties

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

The following are true

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

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

So the earlier answers that explicitly check for the property by name is the most correct way to verify that that property is not present.


I ended up with the following function ...

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

Real similar to a javascript check:

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

I just started using PowerShell with PowerShell Core 6.0 (beta) and following simply works:

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

or

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

This is succinct and readable:

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

We can put it in a function:

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

For identifying which of the objects in an array have a property

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

For me MyProperty" -in $MyObject.PSobject.Properties.Name didn't work, however

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

works


Just check against null.

($myObject.MyProperty -ne $null)

If you have not set PowerShell to StrictMode, this works even if the property does not exist:

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

I've been using the following which returns the property value, as it would be accessed via $thing.$prop, if the "property" would be to exist and not throw a random exception. If the property "doesn't exist" (or has a null value) then $null is returned: this approach functions in/is useful for strict mode, because, well, Gonna Catch 'em All.

I find this approach useful because it allows PS Custom Objects, normal .NET objects, PS HashTables, and .NET collections like Dictionary to be treated as "duck-typed equivalent", which I find is a fairly good fit for PowerShell.

Of course, this does not meet the strict definition of "has a property".. which this question may be explicitly limited to. If accepting the larger definition of "property" assumed here, the method can be trivially modified to return a boolean.

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

Examples:

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"

And, this behavior might not [always] be desired.. ie. it's not possible to distinguish between x.Count and x["Count"].


You could check with:

($Member.PropertyNames -contains "Name") this will check for the Named property


You can use Get-Member

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

If you are using StrictMode and the psobject might be empty, it will give you an error.

For all purposes this will do:

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

I recently switch to set strict-mode -version 2.0 and my null tests failed.

I added a function:

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

Now I code

if (exists $run main) { ...

rather than

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

and we are on our way. Seems to work on objects and hashtables

As an unintended benefit it is less typing.


Try this for a one liner that is strict safe.

[bool]$myobject.PSObject.Properties[$propertyName]

For example:

Set-StrictMode -Version latest;
$propertyName = 'Property1';
$myobject = [PSCustomObject]@{ Property0 = 'Value0' };

if ([bool]$myobject.PSObject.Properties[$propertyName]) {
    $value = $myobject.$propertyName;
}