James O'Neill's Blog

August 28, 2007

Powershell again. Pipes, and "This is not an output"

Filed under: Powershell — jamesone111 @ 3:18 pm

My experiences with PowerShell continue and every so often realize that I never really understood something I thought I’d “got” some while back

I’ve spent most of my time trying not to use the WRITE cmdlets to send output to the screen. After all if I want to write “Hello, World” to the screen I can have a function

function hw
  { ‘Hello, World’ }

No need for a Print, Write, Echo or any other command: in PowerShell an output with nowhere else to go ends up on the screen. If I want formatted output  FORMAT-LIST and FORMAT-TABLE do a great job, especially since I “discovered” calculated fields. Since I always used to get my queries in Access to do loads of work, shoving the work onto FORMAT-TABLE seems natural enough, even if the syntax is little weird. The field is actually written as a hash table @{ label=”Text”, Expression={some code}    }. Of course “Some code” can do anything you want and what it returns goes in the table. So I had a bright idea over the weekend. I can have a menu using format-table. Here the code

Function Choose-Process
Format-Table -inputobject $Proc @{ Label = “ID”; Expression={($global:counter++) }} , processName
$proc[(read-host “Which one ?”)]

So I set a counter, get a list of processes, and then format a table, in formatting the table I output and increment the counter; the I ask the user to input a number to choose one and that gives me the offset into the array of processes of the one to return. When I run it here’s what I get:

PS C:\Users\Jamesone> choose-proc

ID ProcessName
— ———–
0 audiodg
1 CcmExec

Which one ?: 1

Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
——- —— —– —– —– —— — ———–
744 29 13128 10560 92 2204 CcmExec


Of course I  want to save this. So I type in $proc=choose-proc and I get

Which one ?:

What the … ? Where did my menu go ? And the answer is: the menu was OUTPUT. Where did I tell PowerShell that  format-table wasn’t to go to standard output but $proc[offset] was ? I didn’t so both ended up being stored in the result.

Anyone who’s explored PowerShell’s providers will have found there is one for variables. Now I get it … $varName= MyFunction is actually MyFunction > Variable:varName. This behaviour can work for or against you depending on the situation, and here I have to use a for loop and use WRITE-HOST to force output to go the screen [Update: no I don’t need to. See Jeffrey’s comment below]

I guess I was still thinking in Basic, where the last line of your function usually returns the result.  PowerShell’s Outputs are different, they go down the “Standard Output” pipe unless told otherwise and standard output ends up on the screen if the “end of pipe” is left Open; just like you’d expect from a Shell.   And since I was quoting my university lecturers a little while ago here’s something which was written on the board in our first programming class.

It is practically impossible to teach good programming style to students that have had prior exposure to BASIC; as potential programmers they are mentally mutilated beyond hope of regeneration.
Edsger Dijkstra )

Technorati tags: ,

This post originally appeared on my technet blog.


Blog at WordPress.com.

%d bloggers like this: