I have been working on some PowerShell code and attempting to make it as readable as possible (something PowerShell is quite nice at). While we have an Add-Member function and a Get-Member function, there is no related Set-Member function. So I went about creating one for my project. However, in the function itself (as shown below) it is requiring me to use the line:
$_.$NotePropertyName = $NotePropertyValue
to work. However, I think I should be using the line, but it doesn't work:
$InputObject.$NotePropertyName = $NotePropertyValue
Why is it reacting this way?
Function Set-Member
{
[CmdletBinding(DefaultParameterSetName='Message')]
param(
[Parameter(ParameterSetName='Message', Position=0, ValueFromPipeline=$true)] [object[]]$InputObject,
[Parameter(ParameterSetName='Message', Mandatory=$true)] [string]$NotePropertyName,
[Parameter(ParameterSetName='Message', Mandatory=$true)] [string]$NotePropertyValue
)
$strInitialValue = $InputObject.($NotePropertyName) # Get the value of the property FirstName
# for the current object in the pipe
$_.$NotePropertyName = $NotePropertyValue
}
$objTest = [PSCustomObject]@ {
FirstName = "Bob"
LastName = "White"
}
$objTest | ForEach-Object {
$_ | Set-Member -NotePropertyName "FirstName" -NotePropertyValue "Joe"
$_ # Push the object back out the pipe
}
$objTest | ForEach-Object {
$_ | Set-Member -NotePropertyName "FirstName" -NotePropertyValue "Bobby$($_.FirstName)"
$_ # Push the object back out the pipe
}
You defined the $InputObject parameter as an array of objects. You should have a for
loop in your function to iterate over the array and not treat it as a single object. Or change the type to [object]
instead of [object[]]
.
Since you use a pipeline to call the function you should use the process block of the function or you will only see the last item in the pipeline processed.
Function Set-Member
{
[CmdletBinding(DefaultParameterSetName='Message')]
param(
[Parameter(ParameterSetName='Message', Position=0, ValueFromPipeline=$true)] [object[]]$InputObject,
[Parameter(ParameterSetName='Message', Mandatory=$true)] [string]$NotePropertyName,
[Parameter(ParameterSetName='Message', Mandatory=$true)] [string]$NotePropertyValue
)
process
{
foreach ($obj in $InputObject)
{
$strInitialValue = $obj.($NotePropertyName) # Get the value of the property FirstName
# for the current object in the pipe
$obj.$NotePropertyName = $NotePropertyValue
}
}
}