Reading Kevin Marquette's excellent article again, Powershell: Everything you wanted to know about PSCustomObject, he shows that its possible to remove a property from a [PsCustomObject]
with the following:
$SomeObject.psobject.properties.remove('SomeProperty')
I really like this as it is consistent with working with hashtables ($hash.Remove()
) and means I can avoid piping things to Select-Object
or Where-Object
.
Now I just need a Add()
method, looking around I discovered that there is a Add()
method in $SomeObject.psobject.Properties
:
void Add(System.Management.Automation.PSPropertyInfo member)
void Add(System.Management.Automation.PSPropertyInfo member, bool preValidated)
But trying to use it gives me an error:
$o.psobject.Properties.Add("bar", "bar")
# MethodException: Cannot find an overload for "Add" and the argument count: "2".
Am I doing this the wrong way??
You're going the right path but as you can see in the method's overloads, both take a PSPropertyInfo
as their first argument, and this type is an abstract
type so you would need to use any type inheriting this base class instead, if you want to add a new property to your object for example, you would be using PSNoteProperty
:
$someobject = [psobject]::new()
$someobject.PSObject.Properties.Add([psnoteproperty]::new('foo', 'bar'))
$someobject
# foo
# ---
# bar
This is essentially how Add-Member
works behind the scenes when you're looking to add a new property to the psobject
wrapper.
If you want to find out all types that could be inheriting PSPropertyInfo
you can use the ClassExplorer Module:
Find-Type -InheritsType System.Management.Automation.PSPropertyInfo
# Namespace: System.Management.Automation
#
# Access Modifiers Name
# ------ --------- ----
# public class PSAliasProperty : PSPropertyInfo
# public class PSCodeProperty : PSPropertyInfo
# public class PSProperty : PSPropertyInfo
# public class PSAdaptedProperty : PSProperty
# public class PSNoteProperty : PSPropertyInfo
# public class PSVariableProperty : PSNoteProperty
# public class PSScriptProperty : PSPropertyInfo
Or you can filter those types in your AppDomain where their .BaseType
contains PSPropertyInfo
, do note this query would return less results because it only filters 1 level up in the base type hierarchy:
[System.AppDomain]::CurrentDomain.GetAssemblies().GetTypes() |
Where-Object BaseType -EQ ([System.Management.Automation.PSPropertyInfo]) |
Where-Object IsPublic
# Namespace: System.Management.Automation
#
# Access Modifiers Name
# ------ --------- ----
# public class PSAliasProperty : PSPropertyInfo
# public class PSCodeProperty : PSPropertyInfo
# public class PSProperty : PSPropertyInfo
# public class PSNoteProperty : PSPropertyInfo
# public class PSScriptProperty : PSPropertyInfo