Windows Vista Forums
Vista Forums Home Join Vista Forums Windows 7 Forum Vista Tutorials Tags
Welcome to Windows Vista Forums. Our forum is dedicated to helping you find solutions with any problems, errors or issues you are experiencing with Windows Vista. The Vista forum also covers news and updates and has an extensive Windows Vista tutorial section that covers a wide range of tips and tricks.

Go Back   Vista Forums > Misc Newsgroups > PowerShell

Vista - object pipeline?

Reply
 
Old 09-06-2007   #1 (permalink)
Mike Blake-Knox


 
 

object pipeline?

I've read that one of PowerShell's features is that the pipeline passes
objects. That sounded useful so I tried to use the pipeline to pass an
array. I tested this using an array of strings as the object with a
filter to receive the array. What I found is that PowerShell doesn't
seem to pass the array but instead passes each of values separately.

Here's a tiny piece of code:

filter disp
{
$inparm = [string[]]$_
$inparm | write-debug
bp
}

[string[]]$a += "string1"
[string[]]$a += "string2"

$a |disp

The breakpoint is reached twice. The first time, $inparam is string1;
the second time it is string2. I had expected the breakpoint would be
reached once and $inparam would be the array("string1", "string2").

What am I missing?

If I change "filter" to "function" I get an error "Write-Debug : Cannot
bind argument to parameter 'Message' because it is null."

What does this mean?

Thanks

Mike


My System SpecsSystem Spec
Old 09-06-2007   #2 (permalink)
Shay Levi


 
 

Re: object pipeline?

When you cahnge "filter" to "function" the $_ is not valid anymore and equels
to $null.
You need to change $_ to $args[0].

Shay
http://scriptolog.blogspot.com


Quote:

> I've read that one of PowerShell's features is that the pipeline
> passes objects. That sounded useful so I tried to use the pipeline to
> pass an array. I tested this using an array of strings as the object
> with a filter to receive the array. What I found is that PowerShell
> doesn't seem to pass the array but instead passes each of values
> separately.
>
> Here's a tiny piece of code:
>
> filter disp
> {
> $inparm = [string[]]$_
> $inparm | write-debug
> bp
> }
> [string[]]$a += "string1"
> [string[]]$a += "string2"
> $a |disp
>
> The breakpoint is reached twice. The first time, $inparam is string1;
> the second time it is string2. I had expected the breakpoint would be
> reached once and $inparam would be the array("string1", "string2").
>
> What am I missing?
>
> If I change "filter" to "function" I get an error "Write-Debug :
> Cannot bind argument to parameter 'Message' because it is null."
>
> What does this mean?
>
> Thanks
>
> Mike
>

My System SpecsSystem Spec
Old 09-06-2007   #3 (permalink)
Brandon Shell


 
 

Re: object pipeline?

There are other subtle difference between Function and Filter...
Basically the way I understand it
- Function collects all data in the pipe and processes it'
- Filter is process as you go.

More info
get-help about_function
"Shay Levi" <no@xxxxxx> wrote in message
news:8766a94468ee8c9beece88e5d4e@xxxxxx
Quote:

> When you cahnge "filter" to "function" the $_ is not valid anymore and
> equels to $null.
> You need to change $_ to $args[0].
>
> Shay
> http://scriptolog.blogspot.com
>
>
>
Quote:

>> I've read that one of PowerShell's features is that the pipeline
>> passes objects. That sounded useful so I tried to use the pipeline to
>> pass an array. I tested this using an array of strings as the object
>> with a filter to receive the array. What I found is that PowerShell
>> doesn't seem to pass the array but instead passes each of values
>> separately.
>>
>> Here's a tiny piece of code:
>>
>> filter disp
>> {
>> $inparm = [string[]]$_
>> $inparm | write-debug
>> bp
>> }
>> [string[]]$a += "string1"
>> [string[]]$a += "string2"
>> $a |disp
>>
>> The breakpoint is reached twice. The first time, $inparam is string1;
>> the second time it is string2. I had expected the breakpoint would be
>> reached once and $inparam would be the array("string1", "string2").
>>
>> What am I missing?
>>
>> If I change "filter" to "function" I get an error "Write-Debug :
>> Cannot bind argument to parameter 'Message' because it is null."
>>
>> What does this mean?
>>
>> Thanks
>>
>> Mike
>>
>
>
My System SpecsSystem Spec
Old 09-06-2007   #4 (permalink)
Keith Hill [MVP]


 
 

Re: object pipeline?

"Mike Blake-Knox" <mikebk@xxxxxx> wrote in message
news:VA.000000ba.0ba942ed@xxxxxx
Quote:

> I've read that one of PowerShell's features is that the pipeline passes
> objects. That sounded useful so I tried to use the pipeline to pass an
> array. I tested this using an array of strings as the object with a
> filter to receive the array. What I found is that PowerShell doesn't
> seem to pass the array but instead passes each of values separately.
PowerShell unrolls (shreds) collections and sends each individual element
down the pipeline. This is what you want the vast majority of the time. It
would bite if I had to do this:

$a = 1,2,3,4,5

$a | foreach {$_} | where {$_ % 2}

What I'd really like to do is this:

$a | where {$_ % 2}

And have PowerShell send each element of my array down the pipe. Now if you
really want to pass the array or collection down the pipeline without it
being unrolled, you can do this:

,$a | foreach {$_} | where {$_ % 2}

Note the comma prepended to the array variable. In this scenario, the comma
operator will create another array with one element in it - the collection
that you don't want to have unrolled. Now when the pipe output mechanism
unrolls this new collection (which it only unrolls at the top level) the
original collection is emitted as the one and only element which is passed
down the pipe as is. BTW the following doesn't work as you might expect:

169# ,$a | where {$_ % 2}
Method invocation failed because [System.Object[]] doesn't contain a method
named 'op_Modulus'.
At line:1 char:18
+ ,$a | where {$_ % <<<< 2}

--
Keith

My System SpecsSystem Spec
Old 09-06-2007   #5 (permalink)
Keith Hill [MVP]


 
 

Re: object pipeline?

"Keith Hill [MVP]" <r_keith_hill@xxxxxx_no_spam_I> wrote in message
news:39E38D48-E47A-4FF5-9126-FE5F36CF34AE@xxxxxx
Quote:

> BTW the following doesn't work as you might expect:
>
> 169# ,$a | where {$_ % 2}
> Method invocation failed because [System.Object[]] doesn't contain a
> method named 'op_Modulus'.
> At line:1 char:18
> + ,$a | where {$_ % <<<< 2}
Doh. I meant that the command above doesn't work which is not surprising.

--
Keith

My System SpecsSystem Spec
Old 09-07-2007   #6 (permalink)
Hal Rottenberg


 
 

Re: object pipeline?

Brandon Shell wrote:
Quote:

> There are other subtle difference between Function and Filter...
> Basically the way I understand it
> - Function collects all data in the pipe and processes it'
> - Filter is process as you go.
Also note that you can make a function behave as a filter by using the Process{}
named scriptblock. e.g.:

function test-pipeline {
Begin { # do init stuff here }
Process { write-object $_ }
End { # do end stuff here }
}

that's functionally (haha, a pun) equal to:

filter test-pipeline { write-object $_ }

--

Hal Rottenberg
blog: http://halr9000.com
powershell category:
http://halr9000.com/article/category...ng/powershell/
My System SpecsSystem Spec
Old 09-07-2007   #7 (permalink)
Mike Blake-Knox


 
 

Re: object pipeline?

In article <39E38D48-E47A-4FF5-9126-FE5F36CF34AE@xxxxxx>, Keith Hill
[MVP] wrote:
Quote:

> PowerShell unrolls (shreds) collections and sends each individual element*
> down the pipeline.
Thanks! That's exactly what the problem was.
Quote:

> This is what you want the vast majority of the time.
I don't know that I'd want the behaviour but I can certainly see that your
examples show it can be useful. I'd prefer simpler, more consistent
operations instead of special cases.

How did you learn of this behavior? What should I have read?

Thanks again.

Mike

My System SpecsSystem Spec
Old 09-07-2007   #8 (permalink)
Mike Blake-Knox


 
 

Re: object pipeline?

In article <#qSYL7N8HHA.5316@xxxxxx>, Brandon Shell
wrote:
Quote:

> - Function collects all data in the pipe and processes it'
> - Filter is process as you go.
Apparently the second function/filter can be started before the first
has generated data. As a result, $_ is "null" which causes various
problems.

How is one supposed to block untill something has arrived from the
pipeline? Should a function/filter test to see if $_ is "null" and if
so just return on the expectation that it will be called when data
arrives through the pipeline? At one point I thought I had seen
something with pseudo functions where one was run when a .ps1 file was
read, a second was called when the file was closing and a third was
called once for each pipeline object.

Thanks

Mike

My System SpecsSystem Spec
Old 09-08-2007   #9 (permalink)
Keith Hill


 
 

Re: object pipeline?

"Mike Blake-Knox" <mikebk@xxxxxx> wrote in message
news:VA.000000bb.111d3e82@xxxxxx
Quote:

> In article <39E38D48-E47A-4FF5-9126-FE5F36CF34AE@xxxxxx>, Keith
> Hill
> [MVP] wrote:
Quote:

>> PowerShell unrolls (shreds) collections and sends each individual element
>> down the pipeline.
>
> Thanks! That's exactly what the problem was.
>
Quote:

>> This is what you want the vast majority of the time.
>
> I don't know that I'd want the behaviour but I can certainly see that your
> examples show it can be useful. I'd prefer simpler, more consistent
> operations instead of special cases.
>
> How did you learn of this behavior? What should I have read?
>
If you are looking for a book to unlock most of PowerShell's secrets then I
recommend "Windows PowerShell in Action" by Bruce Payette. You might also
want to check out my blog (http://keithhill.spaces.live.com). I'm working
on an Effective PowerShell series of blog posts that you might find useful.

--
Keith

My System SpecsSystem Spec
Old 09-08-2007   #10 (permalink)
Keith Hill [MVP]


 
 

Re: object pipeline?

"Mike Blake-Knox" <mikebk@xxxxxx> wrote in message
news:VA.000000bc.111d5258@xxxxxx
Quote:

> In article <#qSYL7N8HHA.5316@xxxxxx>, Brandon Shell
> wrote:
Quote:

>> - Function collects all data in the pipe and processes it'
>> - Filter is process as you go.
>
> Apparently the second function/filter can be started before the first
> has generated data. As a result, $_ is "null" which causes various
> problems.
filters don't execute until they receive input from the pipe. BTW that
input might be a $null object (value):

filter IsNull { Write-Host ($_ -eq $null); $_ }

$null | IsNull
True

functions can also participate in the pipeline but with more flexibility -
actually behaving very similar to the way a CMDLET works e.g.:

function Sum {
begin {
Write-Host "begin"
$total = 0
}
process {
Write-Host "processing $_"
if ($_) {
$total += [int]$_
}
}
end {
Write-Host "end"
$total
}
}

215# 1..5 | Sum
begin
processing 1
processing 2
processing 3
processing 4
processing 5
end
15

Now this is a lame function (since you could just use Measure-Object -sum)
but it illustrates a few things. First, begin does get called before the
first object is processed by the function. This gives the filtering
function a chance to initialize any state or do other prep work in the begin
function. The process function gets called for each object that is received
from the pipe. Again, you probably should check for $null here if that does
cause problems for you. BTW if it wasn't clear above, $null doesn't mean
"no pipeline output" in this context. $null is a legitimate scalar object 1
and "hi". When there are no more objects left in the pipe, then the end
function is called to perform any cleanup or in this case output the
"folded" result.

--
Keith

My System SpecsSystem Spec
Reply

Thread Tools


Similar Threads
Thread Forum
Re: Access object property while passing through pipeline? PowerShell
Can I pass object along the pipeline to a ps1? PowerShell
Select a random object from pipeline effectively PowerShell
WMI Object Win32_Product and Pipeline woes PowerShell
Add full (to pipeline) multicasting to tee-object? PowerShell


Vista Forums is an independent web site and has not been authorized,
sponsored, or otherwise approved by Microsoft Corporation.
"Windows Vista", the Start Orb, and related materials are trademarks of Microsoft Corp.
© Designer Media Ltd

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46