Reputation: 18848
I am trying to understand how to pipe |
an object and call the properties or methods on that.
Ex:
$a = Get-Item Registry::HKLM\SOFTWARE\WOW6432Node\Microsoft\Test\abc\
$a.GetSomething() //calls the method
(Get-Item Registry::HKLM\SOFTWARE\WOW6432Node\Microsoft\Test\abc\).GetSomething() //calls the method
Can I pipe the output of the Get-Item
and invoke properties/methods
on it?
Get-Item Registry::HKLM\SOFTWARE\WOW6432Node\Microsoft\Test\abc\ | call GetSomething()
Upvotes: 12
Views: 7655
Reputation: 439477
Ansgar Wiechers has provided the crucial pointer in a comment on Martin Brandl's answer:
The canonical way would be
ForEach-Object
. It can be written pretty concisely using the alias%
:... | % { $_.GetSomething() }
In PowerShell version 3 or higher, you an make the call even more concise with simplified syntax, which obviates the need for enclosing the call in { ... }
, having to explicitly refer to $_
, and needing to use parentheses ((...)
):
... | % GetSomething # short for: ... | ForEach-Object GetSomething
If the method (overload) being called has more than one parameter, pass arguments to them individually[1] - see examples below.
Examples:
Method call without arguments:
# Perform the equivalent of:
# (Get-Item Registry::HKLM\SOFTWARE\Classes\txtfile).GetValueNames()
# That is, get the names of the values defined on registry key
# HKEY_LOCAL_MACHINE\SOFTWARE\Classes\txtfile
Get-Item Registry::HKLM\SOFTWARE\Classes\.txt | % GetValueNames
# -> @('Content Type', 'PerceivedType')
Method call with one argument:
# Perform the equivalent of (Get-Date).ToString('u'); i.e.,
# get a date's universally sortable string representation.
Get-Date | % ToString u # "u" may be quoted, but doesn't need to be.
# -> '2019-04-19 08:22:22Z'
Method call with multiple arguments:
# Perform the equivalent of 'foo'.Replace('f', 'F'); i.e.,
# replace all lowercase Fs with uppercase ones.
# Note how the arguments are passed *individually*.
'foo' | % Replace f F
# -> 'Foo'
[1] You can alternatively use an array, (,
-separated arguments), but in Windows PowerShell that requires explicit use of the -ArgumentList
parameter name, which is awkward (no longer needed in PowerShell (Core) 7).
Upvotes: 3
Reputation: 27516
Foreach-object example with an argument, getting the type of a value under the key (REG_EXPAND_SZ) with the GetValueKind() method:
Get-Item HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion |
% GetValueKind DevicePath
ExpandString
Upvotes: -1
Reputation: 104
Use %
followed by the method name.
Get-Item Registry::HKLM\SOFTWARE\WOW6432Node\Microsoft\Test\abc\ | % GetSomething
You can use it on properties as well. It behaves like select -expand
. Only the value will be printed and only 1 property can be passed.
Get-Service | % GetType
Get-Service | % Name
Upvotes: -1
Reputation: 58991
The short answer is no. You can't call a method like this using Pipeline. But you can surround your Get-Item
invoke in parentheses and invoke it:
(Get-Item Registry::HKLM\SOFTWARE\WOW6432Node\Microsoft\Test\abc\).GetSomething()
If you don't want that, you could abuse the Select-Object
cmdlet:
Get-Item Registry::HKLM\SOFTWARE\WOW6432Node\Microsoft\Test\abc\ | select { $_.GetSomething() }
Upvotes: 5
Reputation: 1075
This requirement in most cases says that the task can be accomplished in a simpler way.
However, if it is really needed, you can use the MemberName
parameter of the ForEach-Object
cmdlet:
# declare something
$o = @{
One = 1
Two = 2
Three = 6
}
# do something
$o |
ForEach-Object -MemberName "GetEnumerator" |
ForEach-Object { "$($_.Key): $($_.Value)" } |
Write-Host
Upvotes: 0
Reputation: 1
A nicer method in my opinion would be to use e.g.:
Get-Item Registry::HKLM | % { $_ }
:
where %
is ForEach-Object
(which is fine to use, even if you only have 1) and $_
is each object.
Upvotes: 2
Reputation: 4250
It's not possible without writing something to make it so. That something would be pretty confusing.
Like this.
filter Invoke-Method {
param(
[String]$Method,
[Object[]]$ArgumentList
)
$_.GetType().InvokeMember(
$Method.Trim(),
([System.Reflection.BindingFlags]'InvokeMethod'),
$null,
$_,
$ArgumentList
)
}
"qwerty" | Invoke-Method Replace 'q', 'z'
Properties are easier in that there's already a command to do that:
(...).GetSomething() | Select-Object Property1, Property2
Upvotes: 1