If you have encountered the error Method invocation failed because [System.Management.Automation.PSCustomObject] does not contain a method named 'ForEach', you are not alone. This is a common point of confusion when experimenting with PowerShell's intrinsic methods on custom objects.

Why PSCustomObject Fails with .ForEach()

PowerShell 4.0 introduced intrinsic methods like .ForEach() and .Where(). These methods provide a high-performance, fluent syntax for iterating over items without routing data through the pipeline.

While intrinsic methods are automatically attached to collection types and most standard scalar (single value) types, [pscustomobject] is a special exception.

Because a PSCustomObject relies on dynamic member resolution to handle custom properties and methods, the PowerShell engine does not inject the intrinsic collection methods into it. When you execute $myObject.ForEach('singleValue'), PowerShell attempts to look up a literal method named ForEach on the object, fails to find it, and throws an error.

Which PowerShell Objects Support .ForEach()?

The .ForEach() intrinsic method is available on:

  • Arrays and Collections: Any object implementing ICollection or IEnumerable, such as standard arrays (@()), [System.Collections.Generic.List[T]], or ArrayList.
  • Standard Primitive/Scalar Types: Primitive types like [int], [string], or [datetime] automatically get boxed into a collection context when calling intrinsic methods (e.g., (42).ForEach({ $_ * 2 }) works).

How to Fix the Error

Solution 1: Wrap the Object in an Array

If you want to use the .ForEach() method on a single PSCustomObject, force PowerShell to treat it as an array by wrapping it in the array subexpression operator @():

$myObject = [pscustomobject]@{
    singleValue = 'Hello'
    arrayValue  = @(0..10)
}

# Force array context
@($myObject).ForEach('singleValue')

Solution 2: Call .ForEach() Directly on the Property

If you want to iterate over an array stored inside a property of your custom object, invoke .ForEach() on that property directly:

# arrayValue is an array, so .ForEach() works directly on it
$myObject.arrayValue.ForEach({ $_ * 2 })

Solution 3: Use the Pipeline or standard foreach loop

Alternatively, use the standard pipeline operator ForEach-Object or a standard foreach loop, both of which accept PSCustomObject without issue:

# Pipeline approach
$myObject | ForEach-Object { $_.singleValue }

# Direct property access
$myObject.singleValue

Summary

A PSCustomObject does not natively contain the intrinsic .ForEach() method due to how custom member resolution works in PowerShell. To resolve the issue, either wrap the object in an array using @($myObject).ForEach(...) or access the property directly.