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

PowershellPowershell 3.0

Powershell Problem Overview


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) ) 

Powershell Solutions


Solution 1 - Powershell

Like this?

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

Solution 2 - Powershell

You can use Get-Member

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

Solution 3 - Powershell

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
}

Solution 4 - Powershell

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

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

works

Solution 5 - Powershell

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"].

Solution 6 - Powershell

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

Solution 7 - Powershell

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)

Solution 8 - Powershell

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

Solution 9 - Powershell

Real similar to a javascript check:

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

Solution 10 - Powershell

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.

Solution 11 - Powershell

I find this method more strict and faster when checking multiple properties

$null -ne $myobject.PSObject.Properties.Item("myPropertyNameToTest")

Solution 12 - Powershell

There are a number of solutions to this question that work in strict mode, but some are better than others.

Solutions that do not appear to iterate through every property are the fastest solutions.

  1. Bernie White's solution and
  2. esskar's solution (modified)

Solutions that look as though they iterate through every property are slower.

  1. sebke CCU's solution and
  2. dan-gph's solution

The solution that appears to iterate through every property and uses a regular expression is a little slower than the previous two solutions (because compiling and executing the regular expression takes more time)

  1. CB.'s solution

The solution that uses GetMethod appears to iterate through every property, but its use of GetMethod makes it significantly slower.

  1. Paul's GetMethod solution

The following script was used to compare the previously mentioned solutions in strict mode:

# Tested in PowerShell core 7.2.0

Set-StrictMode -Version Latest

$propertyExistsMethods = New-Object System.Collections.Generic.Dictionary'[string,scriptblock]'

# Fastest
$propertyExistsMethods.Add(
 "PSObject.Properties (Bernie White's solution)",
{
  Param( [PSObject] $Object, [string] $Property )
  [bool]$Object.PSObject.Properties[$Property]
})
$propertyExistsMethods.Add(
 "PSObject.Properties.Item (esskar's solution (modified))",
{
  Param( [PSObject] $Object, [string] $Property )
  [bool]$Object.PSObject.Properties.Item($property)
})

# Not as fast
$propertyExistsMethods.Add(
 "Contains (sebke CCU's solution)",
{
  Param( [PSObject] $Object, [string] $Property )
  $Object.PSobject.Properties.Name.Contains($Property)
})
$propertyExistsMethods.Add(
 "-in (dan-gph's solution)",
{
  Param( [PSObject] $Object, [string] $Property )
  $Property -in $Object.PSobject.Properties.Name
})

# Slower than the previously mentioned solutions
$propertyExistsMethods.Add(
 "-match (CB.'s solution)",
{
  Param( [PSObject] $Object, [string] $Property )
  [bool]($Object.PSobject.Properties.name -match $Property)
})

# Slowest
$propertyExistsMethods.Add(
 "GetMember (Paul's solution)",
{
  Param( [PSObject] $Object, [string] $Property )
  Get-Member -inputobject $Object -name $Property -Membertype Properties
})

foreach ($method in $propertyExistsMethods.Keys) {
  $propertyExists = $propertyExistsMethods[$method]

  $o = @{}
  foreach ($i in 1..100000) {
    $o[$i] = "p$i"
  }

  Write-Host $method
  $measure = Measure-Command {
    foreach ($i in 1..100000) {
      # Always check for a property that does NOT exist
      & $propertyExists -Object $o -Property 'p'
    }
  }
  Write-Host $measure | % { $_.Milliseconds }
  Write-Host ''
}

The output is as follows:

PSObject.Properties (Bernie White's solution)
00:00:03.1437587

PSObject.Properties.Item (esskar's solution)
00:00:03.5833642

Contains (sebke CCU's solution)
00:00:04.4812702

-in (dan-gph's solution)
00:00:04.6507811

-match (CB.'s solution)
00:00:05.1107066

GetMember (Paul's solution)
00:00:14.5305115

Solution 13 - Powershell

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

Solution 14 - Powershell

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.

Solution 15 - Powershell

for me this work

Set-StrictMode -Version Latest
$TMP = ...

$HAS_SERVERS=($TMP | Select-Object Servers)
if (-not $HAS_SERVERS.Servers){
    echo "No servers. Abort."
} else {
    ...
}
 

Solution 16 - Powershell

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
}

Solution 17 - Powershell

You could check with:

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

Solution 18 - Powershell

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

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSteveCView Question on Stackoverflow
Solution 1 - PowershellCB.View Answer on Stackoverflow
Solution 2 - PowershellPaulView Answer on Stackoverflow
Solution 3 - Powershelldan-gphView Answer on Stackoverflow
Solution 4 - Powershellsebke CCUView Answer on Stackoverflow
Solution 5 - Powershelluser2864740View Answer on Stackoverflow
Solution 6 - PowershellShaun LuttinView Answer on Stackoverflow
Solution 7 - PowershellÁdám KovácsView Answer on Stackoverflow
Solution 8 - PowershellBernie WhiteView Answer on Stackoverflow
Solution 9 - PowershellYtramXView Answer on Stackoverflow
Solution 10 - PowershellJohn MelloView Answer on Stackoverflow
Solution 11 - PowershellesskarView Answer on Stackoverflow
Solution 12 - PowershellDave FView Answer on Stackoverflow
Solution 13 - PowershellSteveCView Answer on Stackoverflow
Solution 14 - PowershellSteve PritchardView Answer on Stackoverflow
Solution 15 - PowershellJon GreyView Answer on Stackoverflow
Solution 16 - PowershellhshibView Answer on Stackoverflow
Solution 17 - PowershellTom StryhnView Answer on Stackoverflow
Solution 18 - PowershellcorkyView Answer on Stackoverflow