Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does invoking a Powershell script block with .Invoke() return a collection?

It seems that invoking a PowerShell script block (by invoking the .Invoke() method) always produces a collection. Specifically, a collection of type

System.Collections.ObjectModel.Collection`1[[System.Management.Automation.PSObject, System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]

Even invoking an empty script block ({}.Invoke()) returns a collection. Invoking the same script block using the call operator (&) produces the normally expected return (either a scalar or [object[]]).

This turns out to be convenient if you need a collection instead of an array, but it seems kind of counterintuitive.

Does anyone know why it behaves this way?

I knew there are two different invocations, .Invoke() and .InvokeReturnAsIs() from reading the language spec. That's were I first noticed it.

I just don't understand the reasoning behind the naming convention and the way the mechanics of it appear to work. Looking at the documentation, what I would have thought would be the default invocation method is not what is used when the script block is invoked in PowerShell. It appears that .InvokeReturnAsIs() just returns a stream of objects, and then PowerShell wraps it into an object array if there's more than one object, as scalar if there's only one object, or creates a null object if there are none, as if there's an implicit pipeline there. Using .Invoke() returns a collection, always, and PowerShell leaves it as a collection.

like image 574
mjolinor Avatar asked Jan 27 '12 03:01

mjolinor


1 Answers

Looks to be the difference between these two methods:

Invoke - Invokes the script block with the specified arguments, returning the results as PSObject objects.

InvokeReturnAsIs - Runs the script block with the specified arguments. This method returns the raw (unwrapped) result objects so that it can be more efficient.

http://msdn.microsoft.com/en-us/library/system.management.automation.scriptblock_methods(v=vs.85).aspx

Invoke

$code = {"a"}
$code.Invoke().Gettype().FullName

Output:

System.Collections.ObjectModel.Collection`1[[System.Management.Automation.PSObject, System.Management.Automation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]

InvokeReturnAsIs

$code.InvokeReturnAsIs().GetType().FullName

Output:

System.String
like image 87
Andy Arismendi Avatar answered Oct 21 '22 16:10

Andy Arismendi