Format output to console in cmdlets

by Lembasts at 2013-02-05 13:15:10

I recently wrote an advanced function with begin, process and end blocks.
I was able to output the necessary objects to the pipeline using the write-output statement.
I also wanted to display output in the console.
When I used code like:
$obj | format-table -autosize
…not only wouldnt it display output in the console but the data ended up going to the pipeline.
Can someone please explain this?
by poshoholic at 2013-02-05 13:46:23
Hi David,

Without seeing your function, I can’t identify the specific problem you’re facing. I could provide my own example that shows how some of this works, but it would probably be more beneficial to you if we started with yours. Can you share your function, or a short version of it that illustrates the logic inside the function, as well as the logic you use to invoke the function, so that I can provide appropriate guidance?

Thanks,
by Lembasts at 2013-02-05 14:37:28
Well my script is part of the scripting games event and I guess I cannot reveal it.
Talking generally though, I have a valid object with about 5 properties and one or more instances in a variable called $diskobj.
This variable gets its data from within a Process block in an advanced function.
Once the object has been created the following statement successfully writes the object to the pipeline:
write-output $diskobj
What I did then was to put in a line of code after this to display the results to the console:
$diskobj | format-table -autosize
When running the advanced function, no output was produced on the console.
by poshoholic at 2013-02-06 06:50:24
Sounds like you are doing something like this then:

$results = & {
begin {
$collection = @()
}
process {
$collection += New-Object PSObject -Property @{One=1;Two=2;Red=‘Red’;Blue=‘Blue’}
}
end {
Write-Output $collection
$collection | Format-Table *
}
}

This won’t output anything to the console because all output is being sent to the pipeline, both using Write-Output and Format-Table, and therefore it’s being caught by the variable that collects the results.

Now consider this example:

$results = $null
$shouldBeEmpty = 1…5 | & {
process {
New-Object PSObject -Property @{One=1;Two=2;Red=‘Red’;Blue=‘Blue’}
}
} | Tee-Object -Variable results | Format-Table -AutoSize | Out-Host
"Results has $($results.Count) objects."
"ShouldBeEmpty has $($shouldBeEmpty.Count) objects."

This shows one way you can use to force tabular output to be sent to the host without affecting what is returned from the pipeline, while at the same time collecting the objects that are output in a collection. Even though the results of the script block are assigned to a variable, that collection is empty in the end, demonstrating that the pipeline doesn’t actually return anything.

If this doesn’t help solve your problem, please share an example script (not the actual script, just an example) that illustrates the problem so that I can help you more easily.
by Lembasts at 2013-02-06 16:13:16
So you are invoking a Process script block and assigning it to a variable? Didnt know you could do that.
Thanks for coming up with a solution. I think though that Id probably prefer not to output to the console from advanced functions…we are only supposed to output objects :slight_smile:
I was just interested in this question because of the first practice scripting games event.
I worked out how to display results using html and I think if I really need to output something, Ill do it that way.
by poshoholic at 2013-02-06 17:05:31
Cool, glad this helped resolve the problem David. And yes, absolutely, avoiding outputting directly to the console from functions is a good idea (although like most everything in programming/scripting, there is a time and place when it is useful).
by poshoholic at 2013-02-06 17:06:41
Oh, one more thing. Technically I’m not invoking a process block. I’m invoking an unnamed function (a script block is really just an unnamed function…it can have begin, process and end blocks, parameters, attributes, etc).