1

I have the following output from a PowerShell command and want to update the value for EmployeeID Unfiltered output

I can filter the output with $test.identifiers | where {$_.name -like "EmployeeID" } Filtered output

But if I try to update the value with

$test.identifiers | where {$_.name -like "EmployeeID" } | foreach {$_.values.value = "098324"} 

I get an error Error

How can I update this nested value?

Mister Iks
  • 165
  • 1
  • 4
  • 13

2 Answers2

3

$_.values contains an array (or collection) objects, which explains why you can get (read) the .value property, but not set (write) it (see below).

If you expect the array to have just one element, simply use [0] to access that element directly:

$test.identifiers | where {$_.name -like "EmployeeID" } | foreach {
  $_.values[0].value = '098324'
} 

If there are multiple elements, use
$_.values | foreach { $_.value = '098324' } to assign to them all, or, alternatively in PSv4+,
$_.values.ForEach('value', '098324')


In PSv3+ a feature called member-access enumeration allows you to access a property on a collection and have the property values from the individual elements returned as an array.

However, that only works for getting properties, not for setting them.

When you try to set, only the collection's own properties are considered, which explains the error you saw - an array itself has no .value property.

While this asymmetry is by design, to avoid potentially unwanted bulk modification, the error message could certainly be more helpful.


Simple reproduction of the problem:

Create an object with property one containing a single-element array with another object, with property two:

$obj = [pscustomobject] @{ one = , [pscustomobject] @{ two = 2 } }

The default output looks as follows:

PS> $obj

one
---
{@{two=2}}

The outer {...} indicate an array, as in your case, and what's inside is a hashtable-like notation that PowerShell uses to represent custom objects.

Getting the nested-inside-an-array object's two property works as intended:

PS> $obj.two
2

Trying to set it fails:

PS> $obj.two = 2.1
The property 'two' cannot be found on this object. Verify that the property exists and can be set.

To set, use .ForEach(), for instance:

PS> $obj.ForEach('two', 2.1); $obj

one
---
{@{two=2.1}}
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • 1
    Thanks! for your very extensive answer! $test.identifiers | where {$_.name -like "EmployeeID" } | foreach {$_.values.ForEach('value', '098324')} did the trick – Mister Iks Aug 24 '18 at 05:56
0

Have you tried it this way with the full object path:

$test.identifiers | where {$_.name -like "EmployeeID" } | foreach {$_.identifiers.values.value = "098324"}
NickB
  • 7
  • 3
  • I did, but no joy. Gives the error: The property 'value' cannot be found on this object. Verify that the property exists and can be set. – Mister Iks Aug 23 '18 at 19:37
  • `$_` in the `foreach` (`ForEach-Object`) script block represents the element of input collection `$test.identifiers` currently being enumerated, so using `$_.identifiers` is incorrect. – mklement0 Aug 23 '18 at 21:07