When PowerShell pipes a collection or array, it unwraps the object and passes the individual items in the collection/array. This is normally a very useful behavior, but if you pipe to function like Get-Member and Call-Method, you do not always get
what you want. Let me show how it works -
# Construct an array
$array=1,2,3
# Pass the array down the pipeline
# Gettype will be called 3 times for each integer
# in the array
$array | cm gettype
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Int32 System.ValueType
True True Int32 System.ValueType
True True Int32 System.ValueType
# Wrap array with the array operator. This changes
# nothing as the array operator only creates an array
# if there is none
@($array) | cm gettype
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Int32 System.ValueType
True True Int32 System.ValueType
True True Int32 System.ValueType
# Pass an array with the first argument being our
# array - this works
,$array | cm gettype
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
# Use the updated Call-Method and use the InputObject
# argument - like the one found on Get-Member
cm gettype -InputObject $array
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
## This is the updated Call-Method function
function Call-Method($method,$InputObject) {
begin {
if ($inputObject) {
$m=$inputObject.$method
$m.invoke($args)
}
}
process {
if ($_) {
$m=$_.$method
$m.invoke($args)
}
}
}
new-alias -force cm Call-Method
1 comment:
Very cool.
I would change the call-method to this.
function cm($method, $InputObject)
{
begin {
function doit($target) {
$m=$target.$method
$m.invoke($args)
}
}
process { if ($_) { doit($_) } }
end { if($InputObject) { doit($InputObject) } }
}
Post a Comment