Wednesday, November 07, 2007

More on PowerShell Background Jobs (PSJobs)

In a blog  post yesterday, I talked about the new background job feature in PowerShell Version 2 CTP. One thing I did not entirely appreciate till today (and it should be blindingly obvious), a PSJob produces objects just like any other cmdlet. That means if your the background script produces objects of any kind, the Receive-PSJob cmdlet can retrieve them for manipulation locally. As should be obvious the remoting feature of PowerShell V2 works the same way (you remote a script to a system and get back objects).

Here's a demo of this (with a lot of lines cut out for brevity!)

[ 0]PS D:\foo\v2 > #
[ 1]PS D:\foo\v2 > # Examine PowerShell V2 jobs feature
[ 2]PS D:\foo\v2 > # Demonstrates Start-PSJob, Get-PSJob, Wait-PSJob, Receive-PSJob
[ 3]PS D:\foo\v2 > #
[ 4]PS D:\foo\v2 > # start a job, see it is running,
[ 5]PS D:\foo\v2 > #
[ 6]PS D:\foo\v2 > $job = Start-PSJob "Get-Process" -Name "Job-2"
[ 7
]PS D:\foo\v2 > Get-PSJob

SessionId       Name            State           HasMoreData     Command
---------       ----            -----           -----------     -------
1               demo            Completed       True            get-process
9               Job-2           Running         True            Get-Process

[ 8]PS D:\foo\v2 > #
[ 9]PS D:\foo\v2 > #now wait for it to finish
[10]PS D:\foo\v2 > Wait-Psjob $job

SessionId       Name            State           HasMoreData     Command
---------       ----            -----           -----------     -------
9               Job-2           Completed       True            Get-Process

[11]PS D:\foo\v2 > #
[12]PS D:\foo\v2 > # now get output
[13]PS D:\foo\v2 > #
[14]PS D:\foo\v2 > $procs=receive-PSJob $job -keep
[15]PS D:\foo\v2 > $procs

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    240       8    74584      54684   230 1,077.59   4888 AcroRd32
    116       5     1220       1480    32     1.14   3092 alg
     43       2     1320        852    29   700.95   3828 ApntEx
     93       3     1744       1816    37 2,261.53   3960 Apoint

{ And a whole lot of lines snipped for brevity}

[16]PS D:\foo\v2 > #
[17]PS D:\foo\v2 > # look familiar?
[18]PS D:\foo\v2 > #
[19]PS D:\foo\v2 > $procs | gm

   TypeName: Deserialized.System.Diagnostics.Process

Name                       MemberType     Definition
----                       ----------     ----------
Handles                    AliasProperty  Handles = Handlecount
Name                       AliasProperty  Name = ProcessName

{ And a whole lot more lines also snipped for brevity}

[20]PS D:\foo\v2 > #
[21]PS D:\foo\v2 > # so...
[22]PS D:\foo\v2 > #
[23]PS D:\foo\v2 > $procs | sort handles -desc | select -first 5 |ft name, handles, wm,ws,priorityclass -auto

Name          Handles wm       WS PriorityClass
----          ------- --       -- -------------
svchost          9125    30830592 Normal
OUTLOOK          5444    55250944 Normal
searchindexer    1685    43831296 Normal
explorer         1306    43503616 Normal
csrss            1289     6451200 Normal

 

This is really pretty cool!! You get the PSjobs to run and collect objects and then analyze them locally/remotely. There are some things missing from this CTP, like no NEW-PSJOB, and the input to Receive-PSJob is a job object, not the job-object's id. This means Get-Psjob 9 would return the job noted in the above example, but Receive-PSJob 9 does not (yet)  work.

Another point - the objects returned are de-serialized objects, thus you only get their properties - there is no direct way I can see to return the methods (although I'm sure someone will figure it out). So while you can stop or start a process using the objects returned from get-process, the deserialised objects returned from PS job don't have those methods to call. I'm not sure if this is a good thing or not . But I'd bet that rehydrating live objects across a network is non-trivial!

 

But it's still a great start! 

No comments: