<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type='text/xsl' href='http://jtruher.spaces.live.com/mmm2008-07-17_13.29/rsspretty.aspx?rssquery=en-US;http%3a%2f%2fjtruher.spaces.live.com%2ffeed.rss' version='1.0'?><rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:msn="http://schemas.microsoft.com/msn/spaces/2005/rss" xmlns:live="http://schemas.microsoft.com/live/spaces/2006/rss" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:cf="http://www.microsoft.com/schemas/rss/core/2005" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Time is an illusion. Lunchtime doubly so.</title><description /><link>http://jtruher.spaces.live.com/</link><language>en-US</language><pubDate>Thu, 24 Jul 2008 06:37:23 GMT</pubDate><lastBuildDate>Thu, 24 Jul 2008 06:37:23 GMT</lastBuildDate><generator>Microsoft Spaces v1.1</generator><docs>http://www.rssboard.org/rss-specification</docs><ttl>60</ttl><live:identity><live:id>8161607117076325005</live:id><live:alias>jtruher</live:alias></live:identity><image><title>Time is an illusion. Lunchtime doubly so.</title><url>http://blufiles.storage.live.com/y1pCV65471MCeokXN3e44edaG8kZhkmtrsamoKp9MArNlxaq3DVJ_pwA_BlYyxitfHV</url><link>http://jtruher.spaces.live.com/</link></image><cf:listinfo><cf:group ns="http://schemas.microsoft.com/live/spaces/2006/rss" element="typelabel" label="Type" /><cf:group ns="http://schemas.microsoft.com/live/spaces/2006/rss" element="tag" label="Tag" /><cf:group element="category" label="Category" /><cf:sort element="pubDate" label="Date" data-type="date" default="true" /><cf:sort element="title" label="Title" data-type="string" /><cf:sort ns="http://purl.org/rss/1.0/modules/slash/" element="comments" label="Comments" data-type="number" /></cf:listinfo><item><title>And now for a little Rossini</title><link>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!208.entry</link><description>&lt;div&gt;More music performed by the 1978 PCC Chamber Singers.  This time it's a little Rossini: &lt;/div&gt;
&lt;div&gt;&lt;a href="http://www.truhernet.org/media/PCC78RossiniLaPasseggiata.mp3" rel=nofollow&gt;La Passeggiata&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;Accompanied again by Twyla Meyer and the soprano (heard around 4:20) is the spectacular Rebecca Sherburn.  This group was really quite impressive, I know that a number of the singers in this group have careers as singers.   Twyla is in great demand throughout LA and Bill Hatcher has had stellar career in choral music.  I feel extremely fortunate that I had the opportunity to learn from these amazing musicians.&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=8161607117076325005&amp;page=RSS%3a+And+now+for+a+little+Rossini&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=jtruher.spaces.live.com&amp;amp;GT1=jtruher"&gt;</description><category>Music</category><comments>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!208.entry#comment</comments><guid isPermaLink="true">http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!208.entry</guid><pubDate>Tue, 16 Oct 2007 06:42:55 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://jtruher.spaces.live.com/blog/cns!7143DA6E51A2628D!208/comments/feed.rss</wfw:commentRss><wfw:comment>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!208.entry#comment</wfw:comment><dcterms:modified>2007-10-16T06:42:55Z</dcterms:modified></item><item><title>more from PCC - 1978</title><link>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!205.entry</link><description>&lt;div&gt;&lt;a href="http://www.truhernet.org/media/PCC78AuditeNova.mp3" rel=nofollow&gt;Audite Nova &lt;/a&gt;by Lassus this time - it's a very silly piece.  &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;I remember really liking this piece and having a great time performing it.  Listening to it now, it seems so heavy, i suppose it should, with 6 on a part.  I've performed and listened to so much one-on-a-part that it's clear how much &lt;em&gt;I've &lt;/em&gt;changed in the past 30 years.  Thank goodness for that - it would be horrible to think that I hadn't changed.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;I've got a few more of these and also some recordings of the Pasadena Chorale from around 79 to 83.  I'll get them posted after I finish the Chamber Singers stuff&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=8161607117076325005&amp;page=RSS%3a+more+from+PCC+-+1978&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=jtruher.spaces.live.com&amp;amp;GT1=jtruher"&gt;</description><category>Music</category><comments>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!205.entry#comment</comments><guid isPermaLink="true">http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!205.entry</guid><pubDate>Thu, 11 Oct 2007 07:42:11 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://jtruher.spaces.live.com/blog/cns!7143DA6E51A2628D!205/comments/feed.rss</wfw:commentRss><wfw:comment>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!205.entry#comment</wfw:comment><dcterms:modified>2007-10-11T07:42:11Z</dcterms:modified></item><item><title>I love Twitter</title><link>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!182.entry</link><description>&lt;div&gt;I love the idea of twitter - I think it's the logical intersection between blogging and reduced attention spans.  I started to play about with it and I was frustrated with the way I needed to create entries.  Having a separate app to create twitter updates seemed wrong to me.  I don't want to change focus from my current shell to create an update and best case, I want to update my status automatically so I don't think about it, it just happens.  &lt;/div&gt;
&lt;div&gt;  &lt;/div&gt;
&lt;div&gt;I know that there are some command line tools to do this, but I I want a native solution for PowerShell, so I created a Send-TwitterStatus cmdlet to allow me to send updates directly from my shell.  Not only that, but I can use this cmdlet in other scripts to automatically push my activity to Twitter as well.  I created media player script and it seems like a natural thing to do is to push my playlist to Twitter so my friends can see what I'm listening to (if they want).  I have a line now in the script when I append an album to my playlist is a line that calls my cmdlet and pushes my update:&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;   Send-TwitterStatus &amp;quot;Adding to office playlist: $album&amp;quot; $credential&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;$album is the name of the album 
&lt;li&gt;$credential is a global variable that contains a PSCredential which is used by the cmdlet to authenticate with the Twitter service.   &lt;/ul&gt;
&lt;div&gt;I grabbed the &lt;a href="http://devblog.yedda.com/index.php/2007/05/16/twitter-c-library/" target="_blank" rel=nofollow&gt;Yedda.Twitter &lt;/a&gt;code to do the actual Twitter interaction and the rest is just the code to stitch the cmdlet together.  I also convert the XML results into a custom object so I can eventually create the appropriate formatting.  &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Anyway - here you go.  &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Here's the &lt;a href="http://cid-7143da6e51a2628d.skydrive.live.com/self.aspx/PowerShell Files/twitter.cs" rel=nofollow&gt;Yedda.Twitter library &lt;/a&gt;&lt;/div&gt;
&lt;div&gt;and the &lt;a href="http://cid-7143da6e51a2628d.skydrive.live.com/self.aspx/PowerShell Files/twitter_snapin.cs" rel=nofollow&gt;cmdlet code&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;My post &lt;a href="http://jtruher.spaces.live.com/blog/cns!7143DA6E51A2628D!119.entry"&gt;http://jtruher.spaces.live.com/blog/cns!7143DA6E51A2628D!119.entry&lt;/a&gt; will show how to compile and install a snapin and use.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Next steps are to create the various twitter getters and create the format file so I can get activity directly from the shell.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New" size=1&gt;&lt;/font&gt; &lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New" size=1&gt;&lt;/font&gt; &lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=8161607117076325005&amp;page=RSS%3a+I+love+Twitter&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=jtruher.spaces.live.com&amp;amp;GT1=jtruher"&gt;</description><category>PowerShell</category><comments>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!182.entry#comment</comments><guid isPermaLink="true">http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!182.entry</guid><pubDate>Sat, 01 Sep 2007 00:31:43 GMT</pubDate><slash:comments>3</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://jtruher.spaces.live.com/blog/cns!7143DA6E51A2628D!182/comments/feed.rss</wfw:commentRss><wfw:comment>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!182.entry#comment</wfw:comment><dcterms:modified>2007-09-01T00:31:43Z</dcterms:modified></item><item><title>More media - PCC Chamber Singers, 1978</title><link>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!179.entry</link><description>&lt;div&gt;It seems like the time just flies - it's been a couple months since I updated here, and I would like to post more often.  &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;In any event, I have another audio file to post!  This is the third of the Trois Chanson Britonnes Soir d'été.  My memory of the recording circumstances is a little fuzzy, since it was nearly 30 years ago, but I seem to remember that we did this recording around the end of the calendar year, and we hadn't yet learned the second chanson, so I only have this one (the last) and the first.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Conducted by Bill Hatcher and accompanied by the magnificent Twyla Meyer .&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Here it is: &lt;a href="http://www.truhernet.org/media/PCC78Baddings3.mp3" rel=nofollow&gt;Soir d'été&lt;/a&gt; &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Some of the other pieces from this recording session are:&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Audite Nova 
&lt;li&gt;I Heard a Voice 
&lt;li&gt;Deck the Halls&lt;/ul&gt;
&lt;div&gt;There are more, and I'll post them as I can&lt;/div&gt;
&lt;div&gt;
&lt;div&gt; &lt;/div&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=8161607117076325005&amp;page=RSS%3a+More+media+-+PCC+Chamber+Singers%2c+1978&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=jtruher.spaces.live.com&amp;amp;GT1=jtruher"&gt;</description><category>Music</category><comments>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!179.entry#comment</comments><guid isPermaLink="true">http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!179.entry</guid><pubDate>Fri, 31 Aug 2007 07:20:01 GMT</pubDate><slash:comments>2</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://jtruher.spaces.live.com/blog/cns!7143DA6E51A2628D!179/comments/feed.rss</wfw:commentRss><wfw:comment>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!179.entry#comment</wfw:comment><dcterms:modified>2007-08-31T22:40:01Z</dcterms:modified></item><item><title>Tracing the script stack</title><link>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!172.entry</link><description>&lt;p&gt;It's not uncommon that after I've created a fairly complicated script after a while of using it, something bad happens that I wasn't expecting. And I would really like to know how I got to this state, so a stacktrace of my script would be really, really nice. Sadly, this isn't something that is a default behavior or PowerShell, but fortunately, this sort of thing is actually possible to do with just a little bit of script! 
&lt;p&gt;Most of the real world examples are more complicated than we really need to use to illuminate the problem.  So, I've created a simple example that is useful for discussion. 
&lt;p&gt;Take the following script:&lt;br&gt;&lt;font face="Courier New, Courier, Monospace"&gt;# test-stacktrace1.ps1&lt;br&gt;param ( $startVal )&lt;br&gt;function func1&lt;br&gt;{&lt;br&gt;    param ( $startVal )&lt;br&gt;    1/$startVal--&lt;br&gt;    func2 $startVal&lt;br&gt;}&lt;br&gt;function func2&lt;br&gt;{&lt;br&gt;    param ( $startVal )&lt;br&gt;    1/$startVal--&lt;br&gt;    func3 $startVal&lt;br&gt;}&lt;br&gt;function func3&lt;br&gt;{&lt;br&gt;    param ( $startVal )&lt;br&gt;    1/$startVal--&lt;br&gt;}&lt;br&gt;func1 $startVal&lt;/font&gt; 
&lt;p&gt;When I run this script, depending on the value of my argument, the script will run or fail: 
&lt;p&gt;&lt;font face="Courier New, Courier, Monospace"&gt;PS# c:\temp\test-stacktrace 5&lt;br&gt;0.2&lt;br&gt;0.25&lt;br&gt;0.333333333333333&lt;br&gt;PS# c:\temp\test-stacktrace1 2&lt;br&gt;0.5&lt;br&gt;1&lt;/font&gt;&lt;br&gt;&lt;font color="#ff0000"&gt;Attempted to divide by zero.&lt;br&gt;At c:\temp\test-stacktrace1.ps1:18 char:7&lt;br&gt;+     1/$ &amp;lt;&amp;lt;&amp;lt;&amp;lt; startVal--&lt;/font&gt; 
&lt;p&gt;The message is ok - it tells me that I had a &lt;font face="Verdana, Geneva, Arial, Sans-serif"&gt;problem&lt;/font&gt; on the appropriate line in the script, but I don't know how I got there by looking at the message.  What I would really like to see is both the error and the way I got there.  Here are some examples of what I want to see: 
&lt;p&gt;This example is the normal behavior&lt;br&gt;&lt;font face="Courier New, Courier, Monospace" color="#ff0000"&gt;&lt;font color="#000000"&gt;PS# c:\temp\test-stacktrace2 3&lt;br&gt;0.333333333333333&lt;br&gt;0.5&lt;br&gt;1&lt;/font&gt;&lt;/font&gt; 
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace" color="#ff0000"&gt;&lt;font color="#000000"&gt;&lt;font face="Verdana, Geneva, Arial, Sans-serif"&gt;This example will show what happens when an error occurs deep in the stack:&lt;/font&gt;&lt;br&gt;&lt;/font&gt;&lt;font color="#000000"&gt;PS# c:\temp\test-stacktrace2 2&lt;br&gt;0.5&lt;br&gt;1&lt;br&gt;&lt;/font&gt;&lt;font color="#ff0000"&gt;func3 : Attempted to divide by zero.&lt;br&gt;At c:\temp\test-stacktrace2.ps1:25 char:10&lt;br&gt;+     func3  &amp;lt;&amp;lt;&amp;lt;&amp;lt; $startVal&lt;br&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;At c:\temp\test-stacktrace2.ps1:31 char:42+     trap { write-error $_; get-stacktrace  &amp;lt;&amp;lt;&amp;lt;&amp;lt; }&lt;br&gt;At c:\temp\test-stacktrace2.ps1:25 char:10+     func3  &amp;lt;&amp;lt;&amp;lt;&amp;lt; $startVal&lt;br&gt;At c:\temp\test-stacktrace2.ps1:17 char:10+     func2  &amp;lt;&amp;lt;&amp;lt;&amp;lt; $startVal&lt;br&gt;At c:\temp\test-stacktrace2.ps1:36 char:6+ func1  &amp;lt;&amp;lt;&amp;lt;&amp;lt; $startVal&lt;br&gt;At line:1 char:25+ c:\temp\test-stacktrace2  &amp;lt;&amp;lt;&amp;lt;&amp;lt; 2&lt;/font&gt;&lt;/font&gt;&lt;/div&gt;
&lt;p&gt;&lt;font face="Courier New, Courier, Monospace" color="#ff0000"&gt;&lt;font face=Verdana color="#000000"&gt;Notice that I see the functions that I called on the way to this error - This way I can see the path of woe that generated the error - which means I have a &lt;em&gt;much &lt;/em&gt;better chance of actually fixing the problem.  &lt;/font&gt;&lt;/font&gt;
&lt;p&gt;&lt;font face="Courier New, Courier, Monospace" color="#ff0000"&gt;&lt;font face=Verdana color="#000000"&gt;Here's another example of what happens when an error occurs sooner in the stack, notice that we only see func1 and func2 calls:&lt;/font&gt;&lt;br&gt;&lt;font color="#000000"&gt;PS# c:\temp\test-stacktrace2 1&lt;br&gt;1&lt;br&gt;&lt;/font&gt;&lt;font color="#ff0000"&gt;func2 : Attempted to divide by zero.&lt;br&gt;At c:\temp\test-stacktrace2.ps1:17 char:10&lt;br&gt;+     func2  &amp;lt;&amp;lt;&amp;lt;&amp;lt; $startVal&lt;br&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;At c:\temp\test-stacktrace2.ps1:23 char:42+     trap { write-error $_; get-stacktrace  &amp;lt;&amp;lt;&amp;lt;&amp;lt; }&lt;br&gt;At c:\temp\test-stacktrace2.ps1:17 char:10+     func2  &amp;lt;&amp;lt;&amp;lt;&amp;lt; $startVal&lt;br&gt;At c:\temp\test-stacktrace2.ps1:36 char:6+ func1  &amp;lt;&amp;lt;&amp;lt;&amp;lt; $startVal&lt;br&gt;At line:1 char:25+ c:\temp\test-stacktrace2  &amp;lt;&amp;lt;&amp;lt;&amp;lt; 1&lt;/font&gt;&lt;/font&gt; 
&lt;p&gt;&lt;font face="Courier New, Courier, Monospace" color="#ff0000"&gt;&lt;font face=Verdana color="#000000"&gt;And finally what happens when an error occurs right away, notice that we only see func1 in the stack:&lt;/font&gt;&lt;br&gt;&lt;font color="#000000"&gt;PS# c:\temp\test-stacktrace2 0&lt;br&gt;&lt;/font&gt;&lt;font color="#ff0000"&gt;func1 : Attempted to divide by zero.&lt;br&gt;At c:\temp\test-stacktrace2.ps1:36 char:6&lt;br&gt;+ func1  &amp;lt;&amp;lt;&amp;lt;&amp;lt; $startVal&lt;br&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;At c:\temp\test-stacktrace2.ps1:15 char:42+     trap { write-error $_; get-stacktrace  &amp;lt;&amp;lt;&amp;lt;&amp;lt; }&lt;br&gt;At c:\temp\test-stacktrace2.ps1:36 char:6+ func1  &amp;lt;&amp;lt;&amp;lt;&amp;lt; $startVal&lt;br&gt;At line:1 char:25+ c:\temp\test-stacktrace2  &amp;lt;&amp;lt;&amp;lt;&amp;lt; 0&lt;/font&gt;&lt;/font&gt; 
&lt;p&gt;So, here's the code - and a brief discussion follows: 
&lt;p&gt;&lt;font face="Courier New, Courier, Monospace"&gt;param ( $startVal )&lt;br&gt;function get-stacktrace&lt;br&gt;{&lt;br&gt;    trap { continue }&lt;br&gt;    1..100 | %{&lt;br&gt;        $inv = &amp;amp;{ gv -sc $_ myinvocation } 2&amp;gt;$null&lt;br&gt;        if ($inv) { write-host -for blue $inv.value.positionmessage.replace(&amp;quot;`n&amp;quot;,&amp;quot;&amp;quot;) }&lt;br&gt;        }&lt;br&gt;    exit&lt;br&gt;}&lt;br&gt;&lt;/font&gt;&lt;font face="Courier New, Courier, Monospace"&gt;function func1&lt;br&gt;{&lt;br&gt;    param ( $startVal )&lt;br&gt;    trap { write-error $_; get-stacktrace }&lt;br&gt;    1/$startVal--&lt;br&gt;    func2 $startVal&lt;br&gt;}&lt;br&gt;&lt;/font&gt;&lt;font face="Courier New, Courier, Monospace"&gt;function func2&lt;br&gt;{&lt;br&gt;    param ( $startVal )&lt;br&gt;    trap { write-error $_; get-stacktrace }&lt;br&gt;    1/$startVal--&lt;br&gt;    func3 $startVal&lt;br&gt;}&lt;br&gt;&lt;/font&gt;&lt;font face="Courier New, Courier, Monospace"&gt;function func3&lt;br&gt;{&lt;br&gt;    param ( $startVal )&lt;br&gt;    trap { write-error $_; get-stacktrace }&lt;br&gt;    1/$startVal&lt;br&gt;}&lt;br&gt;&lt;/font&gt;&lt;font face="Courier New, Courier, Monospace"&gt;# Main&lt;br&gt;func1 $startVal&lt;/font&gt; 
&lt;p&gt;Notice the addition of the &amp;quot;get-stacktrace&amp;quot; function: 
&lt;p&gt;&lt;font face="Courier New"&gt;function get-stacktrace&lt;br&gt;{&lt;br&gt;    trap { continue }&lt;br&gt;    1..100 | %{&lt;br&gt;        $inv = &amp;amp;{ gv -sc $_ myinvocation } 2&amp;gt;$null&lt;br&gt;        if ($inv) { write-host -for blue $inv.value.positionmessage.replace(&amp;quot;`n&amp;quot;,&amp;quot;&amp;quot;) }&lt;br&gt;        }&lt;br&gt;    exit&lt;br&gt;}&lt;/font&gt;  
&lt;p&gt;This function takes advantage of the fact that the PowerShell scoping rules allow you to inspect variables in different scopes from your current scope.  This isn't available via syntax, but it is available via the get-variable cmdlet (aliased to gv).  So our little get-stacktrace function just drills down our scopes looking for the myInvocation property which has the information about what line on the script we're on.  There are some other things that are going on.  The trap statement assures me that if I get any terminating errors that I ignore them and I've placed the call of gv in a script block - this allows me to really throw away any messages that get-variable may throw that aren't terminating errors.   Lastly, I want to be sure that my message is on a single line, so I replace the carriage returns with empty strings. 
&lt;p&gt;Notice also that each function now has a trap statement.  I think that this is generally good practice regardless, but these do two things.  First they write the error and then call the get-stacktrace function.  We need to write the error because the get-stacktrace function is going to exit, so if we didn't have this write-error we wouldn't actually see what the error was, just the stack trace which isn't enough info. 
&lt;p&gt;So, if you've got a complicated script and you would really like to discover how you got where you are, I hope this little bit of script will help! 
&lt;p&gt;Jim 
&lt;p&gt; &lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=8161607117076325005&amp;page=RSS%3a+Tracing+the+script+stack&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=jtruher.spaces.live.com&amp;amp;GT1=jtruher"&gt;</description><category>PowerShell</category><comments>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!172.entry#comment</comments><guid isPermaLink="true">http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!172.entry</guid><pubDate>Sun, 15 Jul 2007 08:37:55 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://jtruher.spaces.live.com/blog/cns!7143DA6E51A2628D!172/comments/feed.rss</wfw:commentRss><wfw:comment>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!172.entry#comment</wfw:comment><dcterms:modified>2007-07-15T08:37:55Z</dcterms:modified></item><item><title>Blasts from the past</title><link>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!164.entry</link><description>&lt;div&gt;Wow - I haven't written for a long time - however, I think I'll be doing more because while I was cleaning up my home office, I found a number of cassette tapes to which I've been hanging for an even &lt;em&gt;longer&lt;/em&gt; time.  &lt;/div&gt;
&lt;div&gt;I've been incredibly fortunate to perform with a number of very excellent ensembles over the years.  I found recordings dating back to when I I first started singing at Pasadena City College in 1976-78 - I'm going to be sharing them here in my blog so the folks can get access to them as I can convert them from tape to digital.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;So, I'll try to reduce the noise, and do some of the usual mastering activities.  We'll see how successful I am at that, it will be a learning experience for me.  With the first one, I haven't done any noise reduction of mastering, it's just right off the tape, so you'll hear some tape hiss.  Also, as I recall, the recording was done by some pretty crummy omnidirectional mics (and I seem to remember that it was recorded on reel-to-reel, so this cassette might be a copy of that).  This is a recording from 1978 of the first movement of &lt;em&gt;Trois Chanson &lt;/em&gt;by Henk Badings performed by the Pasadena City College Chamber Singers, conducted by Bill Hatcher who inspired me greatly and accompanied by the amazing Twyla Meyer.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Here you go: &lt;a href="http://www.truhernet.org/media/Pcc78Baddings1.mp3"&gt;La Nuit En Mer&lt;/a&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;jim &lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=8161607117076325005&amp;page=RSS%3a+Blasts+from+the+past&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=jtruher.spaces.live.com&amp;amp;GT1=jtruher"&gt;</description><category>Music</category><comments>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!164.entry#comment</comments><guid isPermaLink="true">http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!164.entry</guid><pubDate>Fri, 22 Jun 2007 07:57:23 GMT</pubDate><slash:comments>2</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://jtruher.spaces.live.com/blog/cns!7143DA6E51A2628D!164/comments/feed.rss</wfw:commentRss><wfw:comment>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!164.entry#comment</wfw:comment><dcterms:modified>2007-06-22T08:02:11Z</dcterms:modified></item><item><title>PowerShell Extended Types (includes a TYPES.XSD)</title><link>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!148.entry</link><description>&lt;div&gt;One of my favorite features of PowerShell is the extended type system.  This system allows us to extend the .NET objects that are returned by the underlying .NET framework with bits of interesting stuff.  There's two way to go about this.  First, by using the add-member cmdlet, it's possible to add methods and properties to an instance of an object.  If we start with a &amp;quot;blank&amp;quot; object, we can create an object out of whole cloth.  Take a look at the following output&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;PS&amp;gt; get-stock|ft Symbol,Last,Change,@{l=&amp;quot;ChangeP&amp;quot;;f=&amp;quot;{0:N2}&amp;quot;;e={$_.ChangeP}} -auto&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;Symbol     Last Change ChangeP&lt;br&gt;------     ---- ------ -------&lt;br&gt;MSFT      28.74  -0.72   -2.51&lt;br&gt;SCO        2.77  -0.02   -0.72&lt;br&gt;^DJI   12767.57   2.56    0.02&lt;br&gt;INFY      59.84   0.23    0.38&lt;br&gt;SUNW       6.29  -0.02   -0.32&lt;/font&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;I have a little script that collects the stock quotes for a number of companies.   (I have a special formatting file for the output, but that's another blog).  Here's the script, you can see how it takes advantage of the extendable type system. &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;$SYMS = &amp;quot;MSFT&amp;quot;,&amp;quot;SCO&amp;quot;,&amp;quot;^DJI&amp;quot;,&amp;quot;INFY&amp;quot;,&amp;quot;SUNW&amp;quot;&lt;br&gt;$wc = new-object net.webclient&lt;br&gt;foreach ( $SYM in $SYMS )&lt;br&gt;{&lt;br&gt;    $yahoo = &amp;quot;&lt;/font&gt;&lt;a href="http://finance.yahoo.com/d/quotes.csv?s"&gt;&lt;font face="Courier New, Courier, Monospace"&gt;http://finance.yahoo.com/d/quotes.csv?s&lt;/font&gt;&lt;/a&gt;&lt;font face="Courier New, Courier, Monospace"&gt;=&amp;quot;&lt;br&gt;    $url = &amp;quot;${yahoo}${SYM}&amp;amp;f=sl1d1t1c1ohgv&amp;amp;e=.csv&amp;quot;&lt;br&gt;    $string = $wc.DownloadString($url)&lt;br&gt;    if ( $string )&lt;br&gt;    {&lt;br&gt;        trap { continue }&lt;br&gt;        $stock = $string.replace(&amp;quot;`&amp;quot;&amp;quot;,&amp;quot;&amp;quot;).replace(&amp;quot;N/A&amp;quot;,&amp;quot;0&amp;quot;).Trim().split(&amp;quot;,&amp;quot;)&lt;br&gt;        $obj = new-object System.Management.Automation.PSObject&lt;br&gt;        $obj.psobject.typenames[0] = &amp;quot;Custom.Stock&amp;quot;&lt;br&gt;        $obj | add-member NoteProperty Symbol  ([string]$stock[0])&lt;br&gt;        $obj | add-member NoteProperty Last    ([double]$stock[1])&lt;br&gt;        $obj | add-member NoteProperty Date    ([datetime]$stock[2])&lt;br&gt;        $obj | add-member NoteProperty Time    ([datetime]$stock[3])&lt;br&gt;        $obj | add-member NoteProperty Change  ([double]$stock[4])&lt;br&gt;        $obj | add-member NoteProperty ChangeP ([double]$stock[4]/[double]$stock[1] * 100)&lt;br&gt;        $obj | add-member NoteProperty Open    ([double]$stock[5])&lt;br&gt;        $obj | add-member NoteProperty High    ([double]$stock[6])&lt;br&gt;        $obj | add-member NoteProperty Low     ([double]$stock[7])&lt;br&gt;        $obj | add-member NoteProperty Volume  ([int]$stock[8])&lt;br&gt;        $obj | add-member NoteProperty InPort  ($pf -contains $SYM)&lt;br&gt;        $obj&lt;br&gt;    }&lt;br&gt;}&lt;/font&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;So, that's a way to use the add-member cmdlet to dynamically extend an object.   This could be done with any object, in this example, I'm creating an object out of nothing, but you can do the same thing with any object.  Here's another example, where I interact with some performance counters, specifically the idle time.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace" size=1&gt;PS&amp;gt; $idle = get-idle&lt;br&gt;PS&amp;gt; $idle&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;br&gt;&lt;font face="Courier New, Courier, Monospace" size=1&gt;CPUCount         : 2&lt;br&gt;Percent          : 100&lt;br&gt;CategoryName     : Process&lt;br&gt;CounterHelp      : % Processor Time is the percentage of elapsed time that all&lt;br&gt;                   of process threads used the processor to execution instructi&lt;br&gt;                   ons. An instruction is the basic unit of execution in a comp&lt;br&gt;                   uter, a thread is the object that executes instructions, and&lt;br&gt;                    a process is the object created when a program is run. Code&lt;br&gt;                    executed to handle some hardware interrupts and trap condit&lt;br&gt;                   ions are included in this count.&lt;br&gt;CounterName      : % Processor Time&lt;br&gt;CounterType      : Timer100Ns&lt;br&gt;InstanceLifetime : Global&lt;br&gt;InstanceName     : Idle&lt;br&gt;ReadOnly         : True&lt;br&gt;MachineName      : JIMTRUD4&lt;br&gt;RawValue         : 10053571562500&lt;br&gt;Site             :&lt;br&gt;Container        :&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace" size=1&gt;&lt;/font&gt; &lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace" size=1&gt;PS&amp;gt; $idle.getidle()     # I'll call my custom script method!&lt;br&gt;99&lt;br&gt;PS&amp;gt; $idle.getidle()&lt;br&gt;88                                        # the reason this fell so much is that I put some load on the system&lt;br&gt;PS&amp;gt; $idle.getidle()&lt;br&gt;90&lt;br&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;Here's the script - I'm sure it could be written better, but that's not the point.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;param ( $systems = @( $env:computername ))&lt;br&gt;$PerfCnt = &amp;quot;System.Diagnostics.PerformanceCounter&amp;quot;&lt;br&gt;$PerfCat = &amp;quot;System.Diagnostics.PerformanceCounterCategory&amp;quot;&lt;br&gt;foreach($system in $systems )&lt;br&gt;{&lt;br&gt;    $Info = &amp;quot;Process&amp;quot;,&amp;quot;% Processor Time&amp;quot;,&amp;quot;Idle&amp;quot;,$system&lt;br&gt;    $obj = new-object $PerfCnt $Info&lt;br&gt;    $pcc = new-object $PerfCat Processor,$system&lt;br&gt;    $idColCol = $pcc.ReadCategory()&lt;br&gt;    [int]$CPUCount = $idColcol['% idle time'].keys.count - 1&lt;br&gt;    $per = $obj.nextvalue() / $CPUCount&lt;br&gt;    # for some reason, we need to sleep here and then check again&lt;br&gt;    # I haven't bothered to find out why&lt;br&gt;    sleep 1&lt;br&gt;    [int]$per = $obj.nextvalue() / $CPUCount&lt;br&gt;&lt;font color="#800080"&gt;    # add some members to the the performance counter&lt;br&gt;    $obj | add-member NoteProperty CPUCount $CPUCount&lt;br&gt;    $obj | add-member NoteProperty Percent $per&lt;br&gt;    $obj | add-member ScriptMethod GetIdle { &lt;br&gt;        $this.Percent = [int]($this.NextValue() / $this.CPUCount) &lt;br&gt;        $this.Percent&lt;br&gt;        }&lt;br&gt;&lt;/font&gt;    # emit the object&lt;br&gt;    $obj&lt;br&gt;}&lt;/font&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Viola!  I've extended the instances of the PerformanceCounter objects created in this script&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;However, there is another way to extend an object instance.  You can create a blob of XML (in a file) and then load that file into your session with the update-typedata cmdlet - whammo! - everytime you create an instance of a specific object, it will have your custom extensions.   We have a number of these extensions in the standard release to ease using the shell.  The best case in point is the difference between System.Array and System.Collections.ArrayList.  &amp;quot;Length&amp;quot; is the property in System.Array that provides the count of the elements of the array, but System.Collections.ArrayList uses &amp;quot;Count&amp;quot;.  We extended the System.Array type with a &amp;quot;Count&amp;quot; property that is an alias to the Length property which actually exists.  This way, regardless of whether you've got an array or arraylist, &amp;quot;Count&amp;quot; will work!  Here's the blob of XML that does the trick.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;&amp;lt;Types&amp;gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt; &amp;lt;Type&amp;gt;&lt;br&gt;  &amp;lt;Name&amp;gt;System.Array&amp;lt;/Name&amp;gt;&lt;br&gt;  &amp;lt;Members&amp;gt;&lt;br&gt;   &amp;lt;AliasProperty&amp;gt;&lt;br&gt;    &amp;lt;Name&amp;gt;Count&amp;lt;/Name&amp;gt;&lt;br&gt;    &amp;lt;ReferencedMemberName&amp;gt;Length&amp;lt;/ReferencedMemberName&amp;gt;&lt;br&gt;   &amp;lt;/AliasProperty&amp;gt;&lt;br&gt;  &amp;lt;/Members&amp;gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt; &amp;lt;/Type&amp;gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;&amp;lt;Types&amp;gt;&lt;/font&gt;&lt;br&gt; &lt;/div&gt;
&lt;div&gt;Once you have this bit of XML in a file, you can use the update-typedata cmdlet to add the blob to your environment.  Let's make our own little extension so you can see how it works.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;PS&amp;gt; cat mynewtype.ps1xml&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;&amp;lt;Types&amp;gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt; &amp;lt;Type&amp;gt;&lt;br&gt;  &amp;lt;Name&amp;gt;System.Array&amp;lt;/Name&amp;gt;&lt;br&gt;  &amp;lt;Members&amp;gt;&lt;br&gt;   &amp;lt;AliasProperty&amp;gt;&lt;br&gt;    &amp;lt;Name&amp;gt;HappyAlias&amp;lt;/Name&amp;gt;&lt;br&gt;    &amp;lt;ReferencedMemberName&amp;gt;Length&amp;lt;/ReferencedMemberName&amp;gt;&lt;br&gt;   &amp;lt;/AliasProperty&amp;gt;&lt;br&gt;  &amp;lt;/Members&amp;gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt; &amp;lt;/Type&amp;gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;&amp;lt;/Types&amp;gt;&lt;/font&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;As you can see, it's pretty simple.  Now let's load it:&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;PS&amp;gt; update-typedata mynewtype.ps1xml&lt;br&gt;PS&amp;gt; ,(1,2,3,4)|gm&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;br&gt;&lt;font face="Courier New, Courier, Monospace"&gt;   TypeName: System.Object[]&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;Name               MemberType    Definition&lt;br&gt;----               ----------    ----------&lt;br&gt;Count              AliasProperty Count = Length&lt;br&gt;HappyAlias         AliasProperty HappyAlias = Length&lt;br&gt;...&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;SyncRoot           Property      System.Object SyncRoot {get;}&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;br&gt;&lt;font face="Courier New, Courier, Monospace"&gt;PS&amp;gt; ,(1,2,3,4).happyalias&lt;br&gt;4&lt;br&gt;PS&amp;gt;&lt;br&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;We've extended the array type!  However, figuring out what is possible isn't documented anywhere, so it's a little tricky to create these.  We allow all sorts of extensions; a bunch of different property extensions, methods (both script and code). With this in mind, I created an XSD that allows me to create types extensions &lt;em&gt;much &lt;/em&gt;more easily.  Now I can edit my type extensions in Visual Studio and they nearly write themselves.  Note that this XSD may have some errors, and as time goes on, I'll correct it as I can.  However, in the mean time, it's better than a poke in the eye with a sharp stick.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;I'm also working on an XSD for our formatting - stay tuned for that&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot; ?&amp;gt; &lt;br&gt;&amp;lt;xs:schema attributeFormDefault=&amp;quot;unqualified&amp;quot; elementFormDefault=&amp;quot;qualified&amp;quot; xmlns:xs=&amp;quot;&lt;/font&gt;&lt;a href="http://www.w3.org/2001/XMLSchema"&gt;&lt;font face="Courier New, Courier, Monospace"&gt;http://www.w3.org/2001/XMLSchema&lt;/font&gt;&lt;/a&gt;&lt;font face="Courier New, Courier, Monospace"&gt;&amp;quot;&amp;gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;  &amp;lt;xs:element name=&amp;quot;Name&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;  &amp;lt;xs:complexType name=&amp;quot;NoteProperty&amp;quot;&amp;gt;&lt;br&gt;      &amp;lt;xs:all&amp;gt;&lt;br&gt;        &amp;lt;xs:element ref=&amp;quot;Name&amp;quot; /&amp;gt;&lt;br&gt;        &amp;lt;xs:element name=&amp;quot;Value&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;&lt;br&gt;      &amp;lt;/xs:all&amp;gt;&lt;br&gt;    &amp;lt;/xs:complexType&amp;gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;  &amp;lt;xs:complexType name=&amp;quot;AliasProperty&amp;quot;&amp;gt;&lt;br&gt;      &amp;lt;xs:all&amp;gt;&lt;br&gt;        &amp;lt;xs:element ref=&amp;quot;Name&amp;quot; /&amp;gt;&lt;br&gt;        &amp;lt;xs:element name=&amp;quot;ReferencedMemberName&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;&lt;br&gt;      &amp;lt;/xs:all&amp;gt;&lt;br&gt;    &amp;lt;/xs:complexType&amp;gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;  &amp;lt;xs:complexType name=&amp;quot;ScriptMethod&amp;quot;&amp;gt;&lt;br&gt;      &amp;lt;xs:all&amp;gt;&lt;br&gt;        &amp;lt;xs:element ref=&amp;quot;Name&amp;quot; /&amp;gt;&lt;br&gt;        &amp;lt;xs:element name=&amp;quot;Script&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;&lt;br&gt;      &amp;lt;/xs:all&amp;gt;&lt;br&gt;    &amp;lt;/xs:complexType&amp;gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;  &amp;lt;xs:complexType name=&amp;quot;ScriptProperty&amp;quot;&amp;gt;&lt;br&gt;      &amp;lt;xs:sequence&amp;gt;&lt;br&gt;        &amp;lt;xs:element minOccurs=&amp;quot;1&amp;quot; maxOccurs=&amp;quot;1&amp;quot; ref=&amp;quot;Name&amp;quot; /&amp;gt;&lt;br&gt;        &amp;lt;xs:element minOccurs=&amp;quot;0&amp;quot; maxOccurs=&amp;quot;1&amp;quot; name=&amp;quot;GetScriptBlock&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;&lt;br&gt;        &amp;lt;xs:element minOccurs=&amp;quot;0&amp;quot; maxOccurs=&amp;quot;1&amp;quot; name=&amp;quot;SetScriptBlock&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;&lt;br&gt;      &amp;lt;/xs:sequence&amp;gt;&lt;br&gt;    &amp;lt;/xs:complexType&amp;gt;&lt;br&gt;  &lt;br&gt;  &amp;lt;xs:complexType name=&amp;quot;CodeReference&amp;quot;&amp;gt;&lt;br&gt;      &amp;lt;xs:all&amp;gt;&lt;br&gt;        &amp;lt;xs:element name=&amp;quot;TypeName&amp;quot;/&amp;gt;&lt;br&gt;        &amp;lt;xs:element name=&amp;quot;MethodName&amp;quot;/&amp;gt;&lt;br&gt;      &amp;lt;/xs:all&amp;gt;&lt;br&gt;    &amp;lt;/xs:complexType&amp;gt;&lt;br&gt;  &lt;br&gt;  &amp;lt;xs:complexType name=&amp;quot;CodeMethod&amp;quot;&amp;gt;&lt;br&gt;      &amp;lt;xs:sequence&amp;gt;&lt;br&gt;        &amp;lt;xs:element name=&amp;quot;Name&amp;quot; type=&amp;quot;xs:string&amp;quot;/&amp;gt;&lt;br&gt;        &amp;lt;xs:element name=&amp;quot;CodeReference&amp;quot; type=&amp;quot;CodeReference&amp;quot;/&amp;gt;&lt;br&gt;      &amp;lt;/xs:sequence&amp;gt;&lt;br&gt;    &amp;lt;/xs:complexType&amp;gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;  &amp;lt;xs:complexType name=&amp;quot;CodeProperty&amp;quot;&amp;gt;&lt;br&gt;      &amp;lt;xs:all&amp;gt;&lt;br&gt;        &amp;lt;xs:element name=&amp;quot;Name&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;&lt;br&gt;        &amp;lt;xs:element minOccurs=&amp;quot;0&amp;quot; maxOccurs=&amp;quot;1&amp;quot; name=&amp;quot;GetCodeReference&amp;quot; type=&amp;quot;CodeReference&amp;quot; /&amp;gt;&lt;br&gt;        &amp;lt;xs:element minOccurs=&amp;quot;0&amp;quot; maxOccurs=&amp;quot;1&amp;quot; name=&amp;quot;SetCodeReference&amp;quot; type=&amp;quot;CodeReference&amp;quot; /&amp;gt;&lt;br&gt;      &amp;lt;/xs:all&amp;gt;&lt;br&gt;    &amp;lt;/xs:complexType&amp;gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;  &amp;lt;xs:complexType name=&amp;quot;PropertySet&amp;quot;&amp;gt;&lt;br&gt;      &amp;lt;xs:sequence&amp;gt;&lt;br&gt;       &amp;lt;xs:element ref=&amp;quot;Name&amp;quot; /&amp;gt;&lt;br&gt;       &amp;lt;xs:element name=&amp;quot;ReferencedProperties&amp;quot; /&amp;gt;&lt;br&gt;      &amp;lt;/xs:sequence&amp;gt;&lt;br&gt;    &amp;lt;/xs:complexType&amp;gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;  &amp;lt;xs:complexType name=&amp;quot;Members&amp;quot;&amp;gt;&lt;br&gt;     &amp;lt;xs:sequence&amp;gt;&lt;br&gt;      &amp;lt;xs:choice maxOccurs=&amp;quot;unbounded&amp;quot;&amp;gt;&lt;br&gt;       &amp;lt;xs:element name=&amp;quot;NoteProperty&amp;quot; type=&amp;quot;NoteProperty&amp;quot; /&amp;gt;&lt;br&gt;       &amp;lt;xs:element name=&amp;quot;AliasProperty&amp;quot; type=&amp;quot;AliasProperty&amp;quot; /&amp;gt;&lt;br&gt;       &amp;lt;xs:element name=&amp;quot;ScriptProperty&amp;quot; type=&amp;quot;ScriptProperty&amp;quot; /&amp;gt;&lt;br&gt;       &amp;lt;xs:element name=&amp;quot;CodeProperty&amp;quot; type=&amp;quot;CodeProperty&amp;quot; /&amp;gt;&lt;br&gt;       &amp;lt;xs:element name=&amp;quot;ScriptMethod&amp;quot; type=&amp;quot;ScriptMethod&amp;quot; /&amp;gt;&lt;br&gt;       &amp;lt;xs:element name=&amp;quot;CodeMethod&amp;quot; type=&amp;quot;CodeMethod&amp;quot; /&amp;gt;&lt;br&gt;       &amp;lt;xs:element name=&amp;quot;MemberSet&amp;quot; type=&amp;quot;MemberSet&amp;quot; /&amp;gt;&lt;br&gt;       &amp;lt;xs:element name=&amp;quot;PropertySet&amp;quot; type=&amp;quot;PropertySet&amp;quot; /&amp;gt;&lt;br&gt;      &amp;lt;/xs:choice&amp;gt;&lt;br&gt;     &amp;lt;/xs:sequence&amp;gt;&lt;br&gt;   &amp;lt;/xs:complexType&amp;gt;&lt;br&gt;  &lt;br&gt;  &amp;lt;xs:complexType name=&amp;quot;MemberSet&amp;quot;&amp;gt;&lt;br&gt;      &amp;lt;xs:all&amp;gt;&lt;br&gt;        &amp;lt;xs:element name=&amp;quot;Name&amp;quot; type=&amp;quot;xs:string&amp;quot;/&amp;gt;&lt;br&gt;        &amp;lt;xs:element name=&amp;quot;Members&amp;quot; type=&amp;quot;Members&amp;quot; /&amp;gt;&lt;br&gt;      &amp;lt;/xs:all&amp;gt;&lt;br&gt;  &amp;lt;/xs:complexType&amp;gt;&lt;br&gt;  &lt;br&gt;  &amp;lt;xs:element name=&amp;quot;Types&amp;quot;&amp;gt;&lt;br&gt;    &amp;lt;xs:complexType&amp;gt;&lt;br&gt;      &amp;lt;xs:sequence&amp;gt;&lt;br&gt;        &amp;lt;xs:element maxOccurs=&amp;quot;unbounded&amp;quot; name=&amp;quot;Type&amp;quot;&amp;gt;&lt;br&gt;          &amp;lt;xs:complexType&amp;gt;&lt;br&gt;            &amp;lt;xs:sequence&amp;gt;&lt;br&gt;              &amp;lt;xs:element name=&amp;quot;Name&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;&lt;br&gt;              &amp;lt;xs:element name=&amp;quot;Members&amp;quot; type=&amp;quot;Members&amp;quot; /&amp;gt;&lt;br&gt;            &amp;lt;/xs:sequence&amp;gt;&lt;br&gt;          &amp;lt;/xs:complexType&amp;gt;&lt;br&gt;        &amp;lt;/xs:element&amp;gt;&lt;br&gt;      &amp;lt;/xs:sequence&amp;gt;&lt;br&gt;    &amp;lt;/xs:complexType&amp;gt;&lt;br&gt;  &amp;lt;/xs:element&amp;gt;&lt;br&gt;&amp;lt;/xs:schema&amp;gt;&lt;br&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;I'm sorry about the length - i should learn to stop typing.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=8161607117076325005&amp;page=RSS%3a+PowerShell+Extended+Types+(includes+a+TYPES.XSD)&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=jtruher.spaces.live.com&amp;amp;GT1=jtruher"&gt;</description><category>PowerShell</category><comments>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!148.entry#comment</comments><guid isPermaLink="true">http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!148.entry</guid><pubDate>Tue, 20 Feb 2007 00:50:02 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://jtruher.spaces.live.com/blog/cns!7143DA6E51A2628D!148/comments/feed.rss</wfw:commentRss><wfw:comment>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!148.entry#comment</wfw:comment><dcterms:modified>2007-02-20T00:50:02Z</dcterms:modified></item><item><title>Getting more out of help</title><link>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!146.entry</link><description>&lt;p&gt;As we were developing PowerShell, we knew that we wanted to provide a capability for searching through the help. Unfortunately, we don't always get to everything, and this is one of those things that we couldn't get to.  However, I still sometimes need to search through the help, so I created this little function to do the search.  It searches through the conceptual topics for the string for which I'm looking and with the switch parameter &amp;quot;-all&amp;quot;, I search through the descriptions of the cmdlet help as well.
&lt;p&gt;Like most things in PowerShell, it turns out to be pretty simple.  Here's how I would look for help that has the word &amp;quot;process&amp;quot; in it, I use -all to retrieve cmdlet help in addition to the conceptural (about*) topics. &lt;pre&gt;PS&amp;gt; search-help process -all
 
HelpTopic                  Reference
---------                  ---------
about_arithmetic_operators The command then processes the parameters as it w...
about_array                .NET Framework. For example, the objects that Get...
about_assignment_operators current process. For example, the following comma...
about_automatic_variables  Contains objects for which an error occurred whil...
about_commonparameters     the command during processing. This variable is
about_environment_variable system path, the number of processors used by the...
about_filter               processes that begin with the letters a through m...
about_foreach              displays any processes whose working-set (memory ...
about_function             filters. The primary difference between the two i...
about_location             As a result, all commands are processed from this...
about_logical_operator     When PowerShell processes this statement, it eval...
about_object               receives the objects from the first command, proc...
about_operator             fact that PowerShell processes operators in a ver...
about_parsing              When processing a command, the PowerShell parser ...
about_pipeline             down the pipeline to the second command. The seco...
about_provider             Alias                ShouldProcess               ...
about_quoting_rules        is passed to the command for processing. Consider...
about_shell_variable       example, the $PID variable stores the process ID ...
about_signing              export process.
about_switch               The keyword &amp;quot;break&amp;quot; indicates that no more proces...
about_wildcard             in order to return specific results. The process ...
default                    get-help get-process   : Displays help about the ...
ForEach-Object             Performs an operation against each of a set of in...
Where-Object               Creates a filter that controls which objects will...
Get-Process                Gets the processes that are running on the local ...
Stop-Process               Stops one or more running processes.
Set-Content                Writes or replaces the content in an item with ne...
Export-Csv                 Creates a comma-separated values (CSV) file that ...
Sort-Object                Sorts objects by property values.
Get-TraceSource            Gets the Windows PowerShell components that are i...&lt;/pre&gt;
&lt;p&gt;Here’s the search-help script - as you can see, it's just a few lines.   The interesting bit is the use of Select-Object.  With Select-Object, I create custom objects from both about* help and cmdlet help.  Select-Object allows me to specify which properties I want, but it also allows me to &amp;quot;rename&amp;quot; the property.  This way I can take two disparate bits of information (the bits I get back from Select-String and the bits I get out of the help object) and create objects that will act consistently regardless of their origin.&lt;pre&gt;function Search-Help&lt;br&gt;{&lt;br&gt;   param ( $pattern, [switch]$all )
   $path = “${pshome}\about*.txt”
   Select-String -list –pattern ${pattern} –path ${path}|
    select-object @{ n=&amp;quot;HelpTopic&amp;quot;; e = {$_.filename -replace &amp;quot;.help.txt&amp;quot;}},
        @{n=&amp;quot;Reference&amp;quot;;e={$_.line.trim()}}
   if ( $all )
   {
     Get-Help * | where-object { $_.description -match ${pattern}}|
        select-object @{n=&amp;quot;HelpTopic&amp;quot;;e={$_.Name}},
            @{n=&amp;quot;Reference&amp;quot;; e={$_.synopsis}}&lt;br&gt;   }
}
&lt;/pre&gt;&lt;pre&gt;I hope this is useful for you!&lt;/pre&gt;&lt;pre&gt;jim&lt;/pre&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=8161607117076325005&amp;page=RSS%3a+Getting+more+out+of+help&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=jtruher.spaces.live.com&amp;amp;GT1=jtruher"&gt;</description><category>PowerShell</category><comments>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!146.entry#comment</comments><guid isPermaLink="true">http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!146.entry</guid><pubDate>Sun, 03 Dec 2006 00:09:02 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://jtruher.spaces.live.com/blog/cns!7143DA6E51A2628D!146/comments/feed.rss</wfw:commentRss><wfw:comment>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!146.entry#comment</wfw:comment><dcterms:modified>2006-12-03T00:09:02Z</dcterms:modified></item><item><title>Dijkstra</title><link>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!142.entry</link><description>&lt;div&gt;
&lt;p&gt;&lt;span style="color:#1f497d"&gt;&lt;font size=3&gt;&lt;font face=Calibri&gt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt; 
&lt;p&gt;&lt;span style="color:#1f497d"&gt;&lt;font face=Calibri size=3&gt;I recently received the following question:&lt;/font&gt;&lt;/span&gt;&lt;span style="color:#1f497d"&gt;
&lt;blockquote dir=ltr&gt;
&lt;p&gt;&lt;span style="color:#1f497d"&gt;&lt;font face=Calibri&gt;&lt;font size=2&gt;Im  trying to solve the following problem in Powershell:&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;
&lt;p&gt;&lt;span style="color:#1f497d"&gt;&lt;font face=Calibri size=2&gt; &lt;/font&gt;&lt;/span&gt;&lt;span style="color:#1f497d"&gt;&lt;font face=Calibri size=2&gt;I know the name of Active Directory Site A and the name of Active Directory Site B, Site A doesn’t necessarily have a site link to Site B (could go A -&amp;gt; C -&amp;gt; B). What is the total cost of the least cost path between these 2 sites? What is the total cost between any 2 sites? (effectively I’m trying to replace this : &lt;/font&gt;&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ad/ad/dsquerysitesbycost.asp"&gt;&lt;u&gt;&lt;font face=Calibri color="#800080" size=2&gt;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ad/ad/dsquerysitesbycost.asp&lt;/font&gt;&lt;/u&gt;&lt;/a&gt;&lt;font face=Calibri&gt;&lt;font size=2&gt; api with a Powershell version.)&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;
&lt;p&gt;&lt;span style="font-size:11pt;color:#1f497d;font-family:'Calibri','sans-serif'"&gt;&lt;font size=2&gt;To do so, I think I need to implement some kind of Dijkstra engine  to solve this...&lt;/font&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;/span&gt;
&lt;p&gt;&lt;span style="color:#1f497d"&gt;&lt;font face=Calibri size=3&gt;&lt;/font&gt;&lt;/span&gt; &lt;span style="color:#1f497d"&gt;&lt;font size=3&gt;&lt;font face=Calibri&gt;Yay for Wikipedia (&lt;a href="http://en.wikipedia.org/wiki/Dijkstra"&gt;http://en.wikipedia.org/wiki/Dijkstra&lt;/a&gt;)!&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;
&lt;p&gt;&lt;span style="color:#1f497d"&gt;&lt;font face=Calibri size=3&gt; &lt;/font&gt;&lt;/span&gt;&lt;span style="color:#1f497d"&gt;&lt;font size=3&gt;&lt;font face=Calibri&gt;Bruce and I thought it might be fun to put this together – we took it straight from the C code.  &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="color:#1f497d"&gt;&lt;font size=3&gt;&lt;font face=Calibri&gt;Given the following graph&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;
&lt;p&gt;&lt;img style="width:401px;height:224px" height=100 src="http://tkfiles.storage.msn.com/x1pC-7nLWDVofRk3ks1q_3zDuQc3pIvbYBRYZ81Ni5K0Qdtg_daLJB9NOd0Xh5y-mJLxXKqPSeOFUu36wUQqstdWhI7XU8Lfd5kAtZUPabX_LUqPR64pelNLH7hQizDssot_r1W84GCFy0" width=180&gt; 
&lt;p&gt;&lt;span style="color:#1f497d"&gt;&lt;font size=3&gt;&lt;font face=Calibri&gt;Where the weight of the path is written on the line.  Here’s the output from running the script:&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;
&lt;p&gt;&lt;span style="color:#1f497d"&gt;&lt;font face=Calibri size=3&gt;&lt;/font&gt;&lt;/span&gt;
&lt;p&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;PS&amp;gt; get-dijkstra&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;The distance between nodes 0 and 0 is 0&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;The distance between nodes 0 and 1 is 2&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;The distance between nodes 0 and 2 is 1&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;The distance between nodes 0 and 3 is 5&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;The distance between nodes 0 and 4 is 4&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;The distance between nodes 0 and 5 is 6&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;The distance between nodes 0 and 6 is 6&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;The distance between nodes 0 and 7 is 8&lt;/span&gt;
&lt;p&gt;&lt;span style="color:#1f497d"&gt;&lt;font face=Calibri size=3&gt;&lt;/font&gt;&lt;/span&gt;
&lt;p&gt;&lt;span style="color:#1f497d"&gt;&lt;font size=3&gt;&lt;font face=Calibri&gt;Showing that the shortest path is 8!  Unfortunately, this script doesn’t show the nodes in the path.  I’ll leave that as an exercise for the reader.  The real point of the exercise was to show the amount of effort that was needed to convert the C into PowerShell!  We basically had to create the structures in the C code, which we did via HashTables (and used functions to create the hashtables).&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;
&lt;p&gt;&lt;span style="color:#1f497d"&gt;&lt;/span&gt;&lt;span style="color:#1f497d"&gt;&lt;font size=3&gt;&lt;font face=Calibri&gt;Here’s the script (again, a straight forward port of the C code from the Wiki site, it's basic but it works!):&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;
&lt;p&gt;&lt;span style="color:#1f497d"&gt;&lt;font face=Calibri size=3&gt;&lt;/font&gt;&lt;/span&gt;
&lt;p&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;### get-dijkstra.ps1&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;$INFINITY = [int]::MaxValue-1&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;function edge ([int] $weight, [int] $dest)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;    @{weight = $weight; dest = $dest}&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;}&lt;/span&gt;
&lt;p&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;function Vertex( [object[]] $connections)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;    @{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;       connections = $connections; # An array of weighted arcs&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;       numconnect = $connections.length&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;       distance = $INFINITY&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;       isDead = $false&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;    }&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;}&lt;/span&gt;
&lt;p&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;function Dijkstra([object[]] $graph, [int] $source)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;{&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;    [int] $nodecount = $graph.length&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;    $graph[$source].distance = 0&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;    for($i = 0; $i -lt $nodecount; $i++) {&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;        $min = $INFINITY+1&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;        # find the unchecked node closest to the source&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;        for($j = 0; $j -lt $nodecount; $j++) {&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;            if(! $graph[$j].isDead -and $graph[$j].distance -lt $min) {&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;                $next = $j&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;                $min = $graph[$j].distance&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;            }&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;        }&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;        # check all paths from node &lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;        for($j = 0; $j -lt $graph[$next].numconnect; $j++)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;        {&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;            if($graph[$graph[$next].connections[$j].dest].distance -gt&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;               $graph[$next].distance + $graph[$next].connections[$j].weight)&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;            {&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;                $graph[$graph[$next].connections[$j].dest].distance =&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;                    $graph[$next].distance + $graph[$next].connections[$j].weight&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;            }&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;        }&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;        $graph[$next].isDead = $true&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;    }&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;    for([int] $i = 0; $i -lt $nodecount; $i++) {&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;        &amp;quot;The distance between nodes {0} and {1} is {2}&amp;quot; -f&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;            $source, $i, $graph[$i].distance&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;    }&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;}&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;$graph = @()&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;###&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;### Here’s where we define the different vertexi&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;### each vertex is a collection of edges&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;### an edge has a weight and a destination&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;$graph += vertex (edge -w 1 -d 2),(edge -w 2 -d 1) # 0&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;$graph += vertex (edge -w 3 -d 3),(edge -w 4 -d 4) # 1&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;$graph += vertex (edge -w 3 -d 4),(edge -w 5 -d 6),(edge -w 10 -d 7) # 2&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;$graph += vertex (edge -w 3 -d 5) # 3&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;$graph += vertex (edge -w 2 -d 5),(edge -w 3 -d 6) # 4&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;$graph += vertex (edge -w 2 -d 6),(edge -w 2 -d 7) # 5&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;$graph += vertex (edge -w 2 -d 7) # 6&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;$graph += vertex (edge -w 0 -d 0) # 7&lt;br&gt;&lt;/span&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;Dijkstra $graph 0&lt;/span&gt;
&lt;p&gt;&lt;span style="font-size:9pt;font-family:'Lucida Console'"&gt;### END SCRIPT&lt;/span&gt;
&lt;p&gt;&lt;span style="color:#1f497d"&gt;&lt;font face=Calibri size=3&gt; Woo Hoo!&lt;/font&gt;&lt;/span&gt;
&lt;p&gt;&lt;span style="color:#1f497d"&gt;&lt;font face=Calibri size=3&gt; &lt;/font&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt; 
&lt;p&gt; &lt;div&gt;&lt;table cellspacing="0" border="0"&gt;&lt;tr height="8"&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top"&gt;&lt;p&gt;&lt;a href="http://blufiles.storage.live.com&amp;#47;y1pW6WDXHo9A-rFH0LdT0t8sR5sd7dYwUKOtwyjxWrEqfaMIefTfnJcVaPQ-2Cy9rvz"&gt;&lt;img src="http://storage.live.com&amp;#47;items&amp;#47;7143DA6E51A2628D&amp;#33;143&amp;#58;thumbnail" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;&lt;td width="15"&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=8161607117076325005&amp;page=RSS%3a+Dijkstra&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=jtruher.spaces.live.com&amp;amp;GT1=jtruher"&gt;</description><category>PowerShell</category><comments>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!142.entry#comment</comments><guid isPermaLink="true">http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!142.entry</guid><pubDate>Tue, 17 Oct 2006 00:01:57 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://jtruher.spaces.live.com/blog/cns!7143DA6E51A2628D!142/comments/feed.rss</wfw:commentRss><wfw:comment>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!142.entry#comment</wfw:comment><dcterms:modified>2006-10-17T00:01:57Z</dcterms:modified></item><item><title>Getting Disk Usage Information</title><link>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!138.entry</link><description>&lt;div&gt;
&lt;p&gt;Some of you might know that I've spent a lot of time on UNIX systems.  One of the scripts that I used a bunch was /etc/dfspace.  If you don't know what dfspace is, it's a simple wrapper for df that provides disk usage info in a more human readable format than the output of df.  Since I really miss having that on Windows, I built it in powershell using the Get-WMIObject cmdlet.  Here's how it looks when you run it: 
&lt;p&gt;&lt;font face="Courier New, Courier, Monospace"&gt;PS&amp;gt; dfspace&lt;br&gt;&lt;/font&gt;&lt;font face="Courier New, Courier, Monospace"&gt;name                  Size (MB) free (MB) percent&lt;br&gt;----                  --------- --------- -------&lt;br&gt;C:                   152,499.84 76,827.33   50.38&lt;/font&gt; 
&lt;p&gt;By default, it only shows me the local hard drives.  By using the &amp;quot;-all&amp;quot; switch parameter I can get all the drives. 
&lt;p&gt;&lt;font face="Courier New, Courier, Monospace"&gt;PS&amp;gt; dfspace -all&lt;br&gt;&lt;/font&gt;&lt;font face="Courier New, Courier, Monospace"&gt;name                  Size (MB) free (MB) percent&lt;br&gt;----                  --------- --------- -------&lt;br&gt;A:                         0.00      0.00     NaN&lt;br&gt;C:                   152,499.84 76,826.80   50.38&lt;br&gt;D:                         0.00      0.00     NaN&lt;br&gt;Z:                    78,528.64  7,342.27    9.35&lt;/font&gt; 
&lt;p&gt;It can also get me the disk usage on another system via the -computer parameter (but you have to enable WMI remote access) 
&lt;p&gt;&lt;font face="Courier New, Courier, Monospace"&gt;PS&amp;gt; dfspace -computer jimtrup2&lt;br&gt;name                 Size (MB) free (MB) percent&lt;br&gt;----                 --------- --------- -------&lt;br&gt;C:                   57,231.53 11,540.28   20.16&lt;/font&gt; 
&lt;p&gt;It gives me what I like, and it's actually a pretty simple script, where most of the script is creating the appropriate formatting 
&lt;p&gt;&lt;font face="Courier New, Courier, Monospace"&gt;# Get-DiskUsage.ps1 (aliased to dfspace)&lt;br&gt;# Use Get-WMIObject to collect disk free info&lt;br&gt;# Can be used with remote systems&lt;br&gt;#&lt;br&gt;param ( [string]$computer = &amp;quot;.&amp;quot; , [switch]$all)&lt;br&gt;# Formatting &lt;br&gt;$size = @{ l = &amp;quot;Size (MB)&amp;quot;; e = { $_.size/1mb};      f = &amp;quot;{0:N}&amp;quot;}&lt;br&gt;$free = @{ l = &amp;quot;free (MB)&amp;quot;; e = { $_.freespace/1mb}; f = &amp;quot;{0:N}&amp;quot;} &lt;br&gt;$perc = @{ l = &amp;quot;percent&amp;quot;; e = { 100.0 * ([double]$_.freespace/[double]$_.size)}; f=&amp;quot;{0:f}&amp;quot; }&lt;br&gt;$name = @{ e = &amp;quot;name&amp;quot;; f = &amp;quot;{0,-20}&amp;quot; }&lt;br&gt;$fields = $name,$size,$free,$perc&lt;br&gt;&lt;/font&gt;&lt;font face="Courier New, Courier, Monospace"&gt;&lt;br&gt;# in case the user wants to see more than just local drives&lt;br&gt;$filter = &amp;quot;DriveType = '3'&amp;quot;&lt;br&gt;if ( $all ) { $filter = &amp;quot;&amp;quot; }&lt;br&gt;&lt;br&gt;# go do the work by getting the information from the appropriate&lt;br&gt;# computer, &lt;/font&gt;&lt;font face="Courier New, Courier, Monospace"&gt;and send it to format-table with the appropriate &lt;br&gt;# fields and formatting info&lt;br&gt;get-wmiobject -class win32_logicaldisk -filter $filter -comp $computer | &lt;br&gt;    format-table $fields -auto &lt;/font&gt;
&lt;p&gt;I suppose that I could handle division by zero better, but seeing NaN doesn't bother me.  If you don't like it, I'll leave that as an exercise for the reader :^)&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=8161607117076325005&amp;page=RSS%3a+Getting+Disk+Usage+Information&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=jtruher.spaces.live.com&amp;amp;GT1=jtruher"&gt;</description><category>PowerShell</category><comments>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!138.entry#comment</comments><guid isPermaLink="true">http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!138.entry</guid><pubDate>Fri, 08 Sep 2006 21:16:22 GMT</pubDate><slash:comments>4</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://jtruher.spaces.live.com/blog/cns!7143DA6E51A2628D!138/comments/feed.rss</wfw:commentRss><wfw:comment>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!138.entry#comment</wfw:comment><dcterms:modified>2007-05-25T21:07:22Z</dcterms:modified></item><item><title>Background "jobs" and PowerShell</title><link>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!130.entry</link><description>&lt;div&gt;One of the things that I'm used to on my unix systems is the ability to run applications in the background and that functionality is not available in PowerShell.  However, our RunSpace architecture can be used to create a pseudo-job environment.  A &amp;quot;simple&amp;quot; script, a few functions and a custom formatting file leaves me with a pretty good experience.  I'm not able to move jobs between foreground and background, but I never did that very much anyway.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;So, the experience looks like this:&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;PS&amp;gt; new-job { get-date; start-sleep 5; get-date }&lt;br&gt;Job 0 Started&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;&lt;em&gt;#&amp;lt;insert 5 second wait here&amp;gt;&lt;/em&gt;&lt;br&gt;PS&amp;gt;&lt;br&gt;Job 0 Completed&lt;br&gt;PS&amp;gt; jobs 0&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;JobId    Status       Command                      Results&lt;br&gt;-----    ------       -------                      -------&lt;br&gt;5        Completed    get-date; start-sleep 5; ... 8/30/2006 4:47:32 PM&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;PS&amp;gt; (jobs 0).results&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;Wednesday, August 30, 2006 4:47:32 PM&lt;br&gt;Wednesday, August 30, 2006 4:47:37 PM&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New"&gt;&lt;/font&gt; &lt;/div&gt;
&lt;div&gt;&lt;font face="Tahoma,Helvetica,Sans-Serif"&gt;This gives me what I need ok - I can run the command and get the results.  Let's do something a little more interesting (at least it is to me).  I want to find all the files on my system that are larger than 100mb and haven't been written for more than 3months.  This would probably take some time, since I'm going to be going over the entire filesystem.  Here's what I got:&lt;/font&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;PS&amp;gt; new-job { ls -rec c:\ | ?{ $_.length -gt 100mb -and $_.lastwritetime -lt [datetime]::now.adddays(-90) } }&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;Job 1 Started&lt;br&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;I would like to see what's going on - so let's check:&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;PS&amp;gt; jobs&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;JobId    Status       Command                      Results&lt;br&gt;-----    ------       -------                      -------&lt;br&gt;0        Completed    get-date; start-sleep 5; ... 8/30/2006 4:56:25 PM&lt;br&gt;1        Running      ls -rec c:\ | ?{ $_.lengt...&lt;/font&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;after using the shell for a while, I get the following message (when I get a prompt):&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Job 1 Completed&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;yea!  now I can check my results:&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;PS&amp;gt; jobs&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;JobId    Status       Command                      Results&lt;br&gt;-----    ------       -------                      -------&lt;br&gt;0        Completed    get-date; start-sleep 5; ... 8/30/2006 4:56:25 PM&lt;br&gt;1        Completed    ls -rec c:\ | ?{ $_.lengt... MSO060408_0001.wmv&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;PS&amp;gt; (jobs 1).results&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;br&gt;&lt;font face="Courier New, Courier, Monospace"&gt;    Directory: Microsoft.PowerShell.Core\FileSystem::C:\Documents and Settings\jimtru\Desktop\mso&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;br&gt;&lt;font face="Courier New, Courier, Monospace"&gt;Mode                LastWriteTime     Length Name&lt;br&gt;----                -------------     ------ ----&lt;br&gt;-a---          4/9/2006   2:15 PM  368465546 MSO060408_0001.wmv&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;br&gt;&lt;font face="Courier New, Courier, Monospace"&gt;    Directory: Microsoft.PowerShell.Core\FileSystem::C:\Documents and Settings\jimtru\Desktop\mso\audio\051204 msoWav&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;br&gt;&lt;font face="Courier New, Courier, Monospace"&gt;Mode                LastWriteTime     Length Name&lt;br&gt;----                -------------     ------ ----&lt;br&gt;-a---         12/5/2005  10:53 AM  121192364 2005-12-05 10_26.wav&lt;br&gt;-a---         12/5/2005  10:54 AM  213057644 2005-12-05 10_36.wav&lt;/font&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;
&lt;div&gt;So, I've got a bunch of huge wav files that I haven't touched for a while (they're recordings of the Microsoft Orchestra for those of you that are curious).   I can even stop the jobs if I want:&lt;/div&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;PS&amp;gt; new-job { ls -rec c:\ | ?{ $_.length -gt 100mb -and $_.lastwritetime -lt [da&lt;br&gt;tetime]::now.adddays(-90) } }&lt;br&gt;Job 2 Started&lt;br&gt;PS&amp;gt; (jobs 2)&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;JobId    Status       Command                      Results&lt;br&gt;-----    ------       -------                      -------&lt;br&gt;2        Running      ls -rec c:\ | ?{ $_.lengt...&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;br&gt;&lt;font face="Courier New, Courier, Monospace"&gt;PS&amp;gt; (jobs 2).stop()&lt;br&gt;Job 2 Stopped&lt;br&gt;PS&amp;gt; jobs&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;JobId    Status       Command                      Results&lt;br&gt;-----    ------       -------                      -------&lt;br&gt;0        Completed    get-date; start-sleep 5; ... 8/30/2006 4:56:25 PM&lt;br&gt;1        Completed    ls -rec c:\ | ?{ $_.lengt... MSO060408_0001.wmv&lt;br&gt;2        Stopped      ls -rec c:\ | ?{ $_.lengt... MSO060408_0001.wmv&lt;br&gt;&lt;/font&gt;&lt;br&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;The new-job script has all the magic in it, so here it is:&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;# New-Job.ps1&lt;br&gt;# This script creates an object that can be used to invoke a &lt;br&gt;# scriptblock asynchronously.&lt;br&gt;#&lt;br&gt;param ( [scriptblock]$scriptToRun )&lt;br&gt;##&lt;br&gt;## Object Created - Custom Object&lt;br&gt;##&lt;br&gt;## METHODS&lt;br&gt;##&lt;br&gt;## void InvokeAsync([string] $script, [array] $input = @())  &lt;br&gt;## Invokes a script asynchronously.&lt;br&gt;## void Stop([bool] $async = $false) # Stop the pipeline.&lt;br&gt;## &lt;br&gt;## PROPERTIES&lt;br&gt;##&lt;br&gt;## [System.Management.Automation.Runspaces.LocalPipeline] LastPipeline      &lt;br&gt;##      The last pipeline that executed.&lt;br&gt;## [bool] IsRunning                                                         &lt;br&gt;##      Whether the last pipeline is still running.&lt;br&gt;## [System.Management.Automation.Runspaces.PipelineState] LastPipelineState &lt;br&gt;##      The state of the last pipeline to be created.&lt;br&gt;## [array] Results                                                          &lt;br&gt;##      The output of the last pipeline that was run.&lt;br&gt;## [array] LastError                                                        &lt;br&gt;##      The errors produced by the last pipeline run.&lt;br&gt;## [object] LastException                                                   &lt;br&gt;##      If the pipeline failed, the exception that caused it to fail.&lt;br&gt;##&lt;br&gt;## Private Fields&lt;br&gt;##&lt;br&gt;## [array] _lastOutput    # The objects output from the last pipeline run.&lt;br&gt;## [array] _lastError     # The errors output from the last pipeline run.&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;#region Message&lt;br&gt;$MultiplePipeline = &amp;quot;A pipeline was already running.   &amp;quot; +&lt;br&gt;    &amp;quot;Cannot invoke two pipelines concurrently.&amp;quot;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;##&lt;br&gt;## MAIN&lt;br&gt;##&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;# First check to be sure that there is a Job array&lt;br&gt;if ( test-path variable:jobs )&lt;br&gt;{&lt;br&gt;    if ( $global:jobs -isnot [array] )&lt;br&gt;    {&lt;br&gt;        throw '$jobs exists and is not an array'&lt;br&gt;    }&lt;br&gt;}&lt;br&gt;else&lt;br&gt;{&lt;br&gt;    $global:jobs = @()&lt;br&gt;}&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;br&gt;&lt;font face="Courier New, Courier, Monospace"&gt;# Create a runspace and open it&lt;br&gt;$config = [Management.Automation.Runspaces.RunspaceConfiguration]::Create()&lt;br&gt;$runspace = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace($config)&lt;br&gt;$runspace.Open()&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;# Create the object - we'll use this as the collector for the entire job.&lt;br&gt;$object = new-object System.Management.Automation.PsObject&lt;br&gt;# Add the object as a note on the runspace&lt;br&gt;$object | add-member Noteproperty Runspace $runspace &lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;# Add a field for storing the last pipeline that was run.&lt;br&gt;$object | add-member Noteproperty LastPipeline $null &lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;# Add an invoke method to the object that takes a script to invoke asynchronously.&lt;br&gt;$invokeAsyncBody = {&lt;br&gt;  if ($args.Count -lt 1)&lt;br&gt;  {&lt;br&gt;    throw 'Usage: $obj.InvokeAsync([string] $script, [Optional][params][array]$inputObjects)'&lt;br&gt;  }&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;  &amp;amp; { &lt;br&gt;    [string]$script, [array] $inputArray =  @($args[0])&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;    $PipelineRunning = [System.Management.Automation.Runspaces.PipelineState]::Running&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;    # Check that there isn't a currently executing pipeline.&lt;br&gt;    # Only one pipeline may run at a time.&lt;br&gt;    if ($this.LastPipeline -eq $null -or &lt;br&gt;        $this.LastPipeline.PipelineStateInfo.State -ne $PipelineRunning )&lt;br&gt;    {&lt;br&gt;      $this.LastPipeline = $this.Runspace.CreatePipeline($script)&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;      # if there's input, write it into the input pipeline.&lt;br&gt;      if ($inputArray.Count -gt 0)&lt;br&gt;      {&lt;br&gt;        $this.LastPipeline.Input.Write($inputArray, $true) &lt;br&gt;      }&lt;br&gt;      $this.LastPipeline.Input.Close()&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;      # Set the Results and LastError to null.&lt;br&gt;      $this.Results   = $null&lt;br&gt;      $this.LastError = $null&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;      # GO!&lt;br&gt;      $this.LastPipeline.InvokeAsync()&lt;br&gt;    }&lt;br&gt;    else&lt;br&gt;    {&lt;br&gt;      # A pipeline was running.  Report an error.&lt;br&gt;      throw &lt;br&gt;    }&lt;br&gt;  } $args&lt;br&gt;}&lt;br&gt;$object | add-member ScriptMethod InvokeAsync $invokeAsyncBody &lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;# Adds a getter script property that lets you determine whether the runspace is still running.&lt;br&gt;$get_isRunning = { &lt;br&gt;  $PipelineRunning = [System.Management.Automation.Runspaces.PipelineState]::Running  &lt;br&gt;  return -not ($this.LastPipeline -eq $null -or&lt;br&gt;               $this.LastPipeline.PipelineStateInfo.State -ne $PipelineRunning  )&lt;br&gt;}&lt;br&gt;$object | add-member ScriptProperty IsRunning $get_isRunning&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;# Add a getter for finding out the state of the last pipeline.&lt;br&gt;$get_PipelineState = { return $this.LastPipeline.PipelineStateInfo.State }&lt;br&gt;$object | add-member ScriptProperty LastPipelineState $get_PipelineState&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;# Add a getter script property that lets you get the last output.&lt;br&gt;$get_lastOutput = {&lt;br&gt;  if ($this._lastOutput -eq $null -and -not $this.IsRunning)&lt;br&gt;  {&lt;br&gt;    $this._lastOutput = @($this.LastPipeline.Output.ReadToEnd())&lt;br&gt;  }&lt;br&gt;  return $this._lastOutput&lt;br&gt;}&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;$set_lastOutput = { $this._lastOutput = $_ }&lt;br&gt;$object | add-member ScriptProperty Results $get_lastOutput $set_lastOutput&lt;br&gt;$object | add-member Noteproperty _lastOutput $null &lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;# Add a getter for finding out the last exception thrown if any.&lt;br&gt;$get_lastException = {&lt;br&gt;  if ($this.LastPipelineState -eq &amp;quot;Failed&amp;quot; -and -not $this.IsRunning)&lt;br&gt;  {&lt;br&gt;    return $this.LastPipeline.PipelineStateInfo.Reason&lt;br&gt;  }&lt;br&gt;}&lt;br&gt;$object | add-member ScriptProperty LastException $get_lastException&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;# Add a getter script property that lets you get the last errors.&lt;br&gt;$get_lastError = {&lt;br&gt;  if ($this._lastError -eq $null -and -not $this.IsRunning)&lt;br&gt;  {&lt;br&gt;    $this._lastError = @($this.LastPipeline.Error.ReadToEnd())&lt;br&gt;  }&lt;br&gt;  return $this._lastError&lt;br&gt;}&lt;br&gt;$set_lastError = { $this._lastError = $args[0] }&lt;br&gt;$object | add-member ScriptProperty LastError $get_lastError $set_lastError&lt;br&gt;$object | add-member Noteproperty _lastError $null &lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;# Add a script method for stopping the execution of the pipeline.&lt;br&gt;$stopScript = {&lt;br&gt;  if ($args.Count -gt 1)&lt;br&gt;  {&lt;br&gt;    throw 'Too many arguments.  Usage: $object.Stop([optional] [bool] $async'&lt;br&gt;  }&lt;br&gt;  if ($args.Count -eq 1 -and [bool] $args[0])&lt;br&gt;  {&lt;br&gt;    $this.LastPipeline.StopAsync()&lt;br&gt;  }&lt;br&gt;  else&lt;br&gt;  {&lt;br&gt;    $this.LastPipeline.Stop()&lt;br&gt;  }&lt;br&gt;}&lt;br&gt;$object | add-member ScriptMethod Stop $stopScript &lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;# finally, attach the script to run to the object&lt;br&gt;$object | add-member Noteproperty Command $scriptToRun  &lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;# Ensure that the object has a &amp;quot;type&amp;quot; for which we can build a &lt;br&gt;# formatting file.&lt;br&gt;$object.Psobject.typenames[0] = &amp;quot;PowerShellJobObject&amp;quot;&lt;br&gt;$object.InvokeAsync($scriptToRun)&lt;br&gt;#$object&lt;br&gt;$object | add-member NoteProperty JobId $jobs.count &lt;br&gt;&amp;quot;Job &amp;quot; + $jobs.count + &amp;quot; Started&amp;quot;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;# Since we add this job to the we need to be sure that&lt;br&gt;# we can remove jobs.  The clear-job function will allow for that&lt;br&gt;$global:jobs += $object&lt;/font&gt;&lt;br&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;I've created 2 functions to help me with getting the job information (and an alias to make it a bit more UNIX like) add these to your profile.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;# get my job&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;function get-job&lt;br&gt;([int[]]$range = 0..($jobs.count-1))&lt;br&gt;{&lt;br&gt;    $jobs[$range] &lt;br&gt;}&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;# make a UNIX like alias&lt;br&gt;alias jobs get-job&lt;br&gt;function clear-job&lt;br&gt;{&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;    # remove all the variables that hold my job info&lt;br&gt;    rm variable:jobs&lt;br&gt;    rm variable:jobshash&lt;br&gt;    # call the garbage collector, just because I can&lt;br&gt;    [system.gc]::Collect()&lt;br&gt;}&lt;br&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Then to be sure that I know when a job is finished, I added this to my prompt function:&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;    ### Job info code - only useful for new-job script&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;    ### paranoia - make a jobhash hashtable so I can track what jobs are done&lt;br&gt;    if ( $jobshash -isnot [hashtable] ) { $global:jobshash = @{} }&lt;br&gt;    $global:jobs | where { $_.lastpipelinestate -ne &amp;quot;Running&amp;quot; } | foreach-object { &lt;br&gt;        if ( ! $global:jobshash[([string]$_.jobid)] ) &lt;br&gt;        {         &lt;br&gt;            $global:jobshash[([string]$_.jobid)] = 1&lt;br&gt;            if ( $_ ) { write-host Job $_.jobid   $_.lastpipelinestate }&lt;br&gt;        }&lt;br&gt;    }&lt;br&gt;    ### End job info code&lt;br&gt;&lt;/font&gt; &lt;/div&gt;
&lt;div&gt;Finally, I created a format table view so I can see the output the way I want (when I get a PowerShellJobObject - see the new-job script).  My profile runs &lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;    update-formatdata c:\powershell\format\job.format.ps1xml&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;to ensure that the format file get loaded.  Here's the content of the format file&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;PS&amp;gt; get-content c:\powershell\format\job.format.ps1xml&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot; ?&amp;gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font face="Courier New, Courier, Monospace"&gt;&amp;lt;Configuration&amp;gt;&lt;br&gt;    &amp;lt;ViewDefinitions&amp;gt;&lt;br&gt;        &amp;lt;View&amp;gt;&lt;br&gt;            &amp;lt;Name&amp;gt;PowerShellJobObject&amp;lt;/Name&amp;gt;&lt;br&gt;            &amp;lt;ViewSelectedBy&amp;gt;&lt;br&gt;                &amp;lt;TypeName&amp;gt;PowerShellJobObject&amp;lt;/TypeName&amp;gt;&lt;br&gt;            &amp;lt;/ViewSelectedBy&amp;gt;&lt;br&gt;            &amp;lt;TableControl&amp;gt;&lt;br&gt;                &amp;lt;TableHeaders&amp;gt;&lt;br&gt;                    &amp;lt;TableColumnHeader&amp;gt;&lt;br&gt;                        &amp;lt;Label&amp;gt;JobId&amp;lt;/Label&amp;gt;&lt;br&gt;                        &amp;lt;Width&amp;gt;8&amp;lt;/Width&amp;gt;&lt;br&gt;                    &amp;lt;/TableColumnHeader&amp;gt;&lt;br&gt;                    &amp;lt;TableColumnHeader&amp;gt;&lt;br&gt;                        &amp;lt;Label&amp;gt;Status&amp;lt;/Label&amp;gt;&lt;br&gt;                        &amp;lt;Width&amp;gt;12&amp;lt;/Width&amp;gt;&lt;br&gt;                    &amp;lt;/TableColumnHeader&amp;gt;&lt;br&gt;                    &amp;lt;TableColumnHeader&amp;gt;&lt;br&gt;                        &amp;lt;Label&amp;gt;Command&amp;lt;/Label&amp;gt;&lt;br&gt;                    &amp;lt;/TableColumnHeader&amp;gt;&lt;br&gt;                    &amp;lt;TableColumnHeader&amp;gt;&lt;br&gt;                        &amp;lt;Label&amp;gt;Results&amp;lt;/Label&amp;gt;&lt;br&gt;                    &amp;lt;/TableColumnHeader&amp;gt;&lt;br&gt;                &amp;lt;/TableHeaders&amp;gt;&lt;br&gt;                &amp;lt;TableRowEntries&amp;gt;&lt;br&gt;                    &amp;lt;TableRowEntry&amp;gt;&lt;br&gt;                        &amp;lt;TableColumnItems&amp;gt;&lt;br&gt;                            &amp;lt;TableColumnItem&amp;gt;&lt;br&gt;                                &amp;lt;PropertyName&amp;gt;JobId&amp;lt;/PropertyName&amp;gt;&lt;br&gt;                            &amp;lt;/TableColumnItem&amp;gt;&lt;br&gt;                            &amp;lt;TableColumnItem&amp;gt;&lt;br&gt;                                &amp;lt;PropertyName&amp;gt;LastPipelineState&amp;lt;/PropertyName&amp;gt;&lt;br&gt;                            &amp;lt;/TableColumnItem&amp;gt;&lt;br&gt;                            &amp;lt;TableColumnItem&amp;gt;&lt;br&gt;                                &amp;lt;PropertyName&amp;gt;Command&amp;lt;/PropertyName&amp;gt;&lt;br&gt;                            &amp;lt;/TableColumnItem&amp;gt;&lt;br&gt;                            &amp;lt;TableColumnItem&amp;gt;&lt;br&gt;                                &amp;lt;ScriptBlock&amp;gt;&lt;br&gt;                                    if ( $_.results -is [array])&lt;br&gt;                                    { &lt;br&gt;                                        $_.results[0] &lt;br&gt;                                    } &lt;br&gt;                                    else &lt;br&gt;                                    { &lt;br&gt;                                        $_.results&lt;br&gt;                                    }&lt;br&gt;                                &amp;lt;/ScriptBlock&amp;gt;&lt;br&gt;                            &amp;lt;/TableColumnItem&amp;gt;&lt;br&gt;                        &amp;lt;/TableColumnItems&amp;gt;&lt;br&gt;                    &amp;lt;/TableRowEntry&amp;gt;&lt;br&gt;                &amp;lt;/TableRowEntries&amp;gt;&lt;br&gt;            &amp;lt;/TableControl&amp;gt;&lt;br&gt;        &amp;lt;/View&amp;gt;&lt;br&gt;    &amp;lt;/ViewDefinitions&amp;gt;&lt;br&gt;&amp;lt;/Configuration&amp;gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;The extra functions and addition to my prompt and the formatting file are all extra's and not really necessary to the operation of the runspace.  It just makes it easier for me to deal with.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;There you have it - you can run background &amp;quot;jobs&amp;quot; too!  Right now, I use a simple array to hold all my jobs - in the future I'll use an array list, so that way I can remove the old jobs if I want (rather than just blowing away the entire array as clear-job does.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;jim&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=8161607117076325005&amp;page=RSS%3a+Background+%22jobs%22+and+PowerShell&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=jtruher.spaces.live.com&amp;amp;GT1=jtruher"&gt;</description><category>PowerShell</category><comments>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!130.entry#comment</comments><guid isPermaLink="true">http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!130.entry</guid><pubDate>Thu, 31 Aug 2006 00:20:27 GMT</pubDate><slash:comments>11</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://jtruher.spaces.live.com/blog/cns!7143DA6E51A2628D!130/comments/feed.rss</wfw:commentRss><wfw:comment>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!130.entry#comment</wfw:comment><dcterms:modified>2008-05-15T17:02:53Z</dcterms:modified></item><item><title>PowerShell and file version information</title><link>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!125.entry</link><description>&lt;div&gt;I often want to get the version information about the files on my system.  Version information is provided as part of the System.Diagnostics.Process object, but I often want the version information about applications that &lt;em&gt;aren't&lt;/em&gt; running.  This script allows me to get that information.  I've written the script so it handles both piped input and command line arguments.  It uses the begin/process/end features of the scripting language, so I can get it to behave almost like a compiled cmdlet.  &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Here's what it looks like when I use it:&lt;/div&gt;
&lt;div&gt;&lt;pre&gt;PS&amp;gt; ls c:\windows\*.exe | get-fileversion

ProductVersion   FileVersion      FileName
--------------   -----------      --------
1.6.0.2          1.6.0.2          C:\windows\Alcmtr.exe
1.1.0.27         1.1.0.27         C:\windows\alcwzrd.exe
6.00.2900.2180   6.00.2900.218... C:\windows\explorer.exe
5.2.3790.2453    5.2.3790.2453... C:\windows\hh.exe
5, 51            5, 51, 138, 0    C:\windows\IsUninst.exe
1.1.0.8          1.1.0.8          C:\windows\MicCal.exe
5.1.2600.2180    5.1.2600.2180... C:\windows\NOTEPAD.EXE
5.1.2600.2180    5.1.2600.2180... C:\windows\regedit.exe
2.0.1.7          2.0.1.7          C:\windows\RTHDCPL.exe
1.0.1.51         1.0.1.51         C:\windows\RTLCPL.exe
2, 5, 0, 5       2, 5, 0, 5       C:\windows\RtlUpd.exe
1, 0, 0, 21      1, 0, 0, 21      C:\windows\SoundMan.exe
5.1.2600.0       5.1.2600.0 (x... C:\windows\TASKMAN.EXE
1,7,0,0          1,7,0,0          C:\windows\twunk_16.exe
1,7,1,0          1,7,1,0          C:\windows\twunk_32.exe
3.10.425         3.10.425         C:\windows\winhelp.exe
5.1.2600.2180    5.1.2600.2180... C:\windows\winhlp32.exe
&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;or&lt;/div&gt;
&lt;div&gt;&lt;pre&gt;PS&amp;gt; get-fileversion C:\monad\rc1\System.Management.Automation.dll

ProductVersion   FileVersion      FileName
--------------   -----------      --------
1.0.9567.1       1.0.9567.1       C:\monad\rc1\System.Management.Automation.dll
&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;Here's the script - it's pretty straight forward. Since I don't know whether I'm going to have piped input or not, I use the begin script block to declare a couple of functions that will be used by either of the process or end blocks.&lt;/div&gt;
&lt;div&gt;The real work is done in the function GetVersionInfo where I simply call the GetVersionInfo static method on the System.Diagnostics.FileVersionInfo type. Note that most of the code is error correction and ensuring that I get a proper path when I call the GetVersionInfo method. &lt;/div&gt;
&lt;div&gt;&lt;pre&gt;param ( [string[]]$paths )
begin {
    # I want to do some stuff with relative paths.   
    # create a variable that I can use later
    $P = [string](get-location)

    # the workhorse of the script
    function GetVersionInfo
    {
        param ( [string]$path )
        # resolve the path, we're going to need a fully qualified path to hand
        # to the method, so go get it.  I may not have that depending on how
        # was called
        $rpath = resolve-path $path 2&amp;gt;$null
        # the thing we hand to the method is the path string, so we'll tuck that away
        $path = $rpath.path
        # check to be sure that we're in the filesystem
        if ( $rpath.provider.name -ne &amp;quot;FileSystem&amp;quot; ) 
        { 
            &amp;quot;$path is not in the filesystem&amp;quot;
            return $null
        }
        # now that I've determined that I'm in the filesystem, go get the fileversion
        $o = [system.diagnostics.fileversioninfo]::GetVersionInfo($path)
        # this little dance adds a new property to the versioninfo object
        # I add the relative path to the versioninfo so I can inspect that in the output object
        # the way that add-member works is to not emit the object, so I need to 
        # use the -passthrough parameter
        $o|add-member noteproperty RelativePath ($path.replace($P,&amp;quot;.&amp;quot;)) -pass
    }
    # whoops! something bad happened
    function ShowFileError
    {
        param ( [string]$path )
        if ( test-path $path -pathtype container )
        {
            &amp;quot;$path is a container&amp;quot;
        }
        else
        {
            &amp;quot;$path not found&amp;quot;
        }
    }
}

# data could have been piped - check $_ to see if this cmdlet had data
# piped to it
process {
    if ( $_ )
    {
        # make sure that I'm not trying to get a versioninfo of a directory
        if ( test-path $_ -pathtype leaf )
        {
            GetVersionInfo $_
        }
        else
        {
            ShowFileError $_
        }
    }
}

# we could have also gotten arguments on the command line
end {
    if ( $paths )
    {
        # by calling resolve path first, I can deal with wildcards on the command line
        foreach ( $path in resolve-path $paths )
        {
            # make sure it's a file, not a directory
            if ( test-path $path -pathtype leaf )
            {
                GetVersionInfo $path
            }
            else
            {
                ShowFileError $path
            }
        }
    }
}
&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=8161607117076325005&amp;page=RSS%3a+PowerShell+and+file+version+information&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=jtruher.spaces.live.com&amp;amp;GT1=jtruher"&gt;</description><category>PowerShell</category><comments>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!125.entry#comment</comments><guid isPermaLink="true">http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!125.entry</guid><pubDate>Sun, 14 May 2006 19:31:26 GMT</pubDate><slash:comments>5</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://jtruher.spaces.live.com/blog/cns!7143DA6E51A2628D!125/comments/feed.rss</wfw:commentRss><wfw:comment>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!125.entry#comment</wfw:comment><dcterms:modified>2006-05-16T17:15:38Z</dcterms:modified></item><item><title>PowerShell: Hashtables and Objects</title><link>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!119.entry</link><description>&lt;div&gt;I use hash tables all the time - they're dead useful and when we were building PowerShell I used them as surrogate objects.  However, they don't &lt;em&gt;quite &lt;/em&gt;behave like an object - display is problematic and it's tougher to add methods, etc, so, how do I get what I want?  There are a couple of ways to add functionality to the PowerShell environment. Scripts and functions are the usual way to add to a shell environment, but one of the things I &lt;em&gt;really&lt;/em&gt; like about PowerShell is the dynamic nature of the snapin model. This allows me to add cmdlets and providers to my environment - and since one of the things I use all the time is a hashtable as an object, I figured that I would create a hashtable converterto do the trick.   The converter itself could be done as a script (and is left as an excercise for the reader)&lt;/div&gt;
&lt;div&gt;&lt;pre&gt;using System;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Management.Automation;
using System.Management.Automation.Runspaces;

namespace System.Management.Automation.Demos
{
    // This class defines the properties of a snapin
    [RunInstaller(true)]
    public class ConversionCmdlets : PSSnapIn
    {
        /// &amp;lt;summary&amp;gt;Creates an instance of DemoSnapin class.&amp;lt;/summary&amp;gt;
        public ConversionCmdlets() : base()
        {
        }
        ///&amp;lt;summary&amp;gt;The snapin name which is used for registration&amp;lt;/summary&amp;gt;
        public override string Name
        { get
            { return &amp;quot;ConversionCmdlets&amp;quot;;
            }
        }
        /// &amp;lt;summary&amp;gt;Gets vendor of the snapin.&amp;lt;/summary&amp;gt;
        public override string Vendor
        { get
            { return &amp;quot;Vendor String - JWT&amp;quot;;
            }
        }
        /// &amp;lt;summary&amp;gt;Gets description of the snapin. &amp;lt;/summary&amp;gt;
        public override string Description
        { get
            { return &amp;quot;This snapin contains demo conversion cmdlets&amp;quot;;
            }
        }
        private string[] formats = null;

        public override string[] Formats
        { get 
            { return formats;
            }
        }
    }
}

&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;That's the code that allows me to create a snapin, now I need the actual cmdlet code &lt;/div&gt;
&lt;div&gt;&lt;pre&gt;using System;
using System.Management.Automation;
using System.Collections;
using System.Collections.ObjectModel;

namespace JWT.Conversion.Cmdlets
{
    [Cmdlet(&amp;quot;Convert&amp;quot;,&amp;quot;HashToObject&amp;quot;)]
    public class ConvertHashToObjectCommand : PSCmdlet
    {
        private Hashtable hash;
        [Parameter(Mandatory=true,Position=0,ValueFromPipeline=true)]
        public Hashtable Hash
        {
            get { return hash; }
            set { hash = value; }
        }
        private String[] name = { &amp;quot;ConvertedHashTable&amp;quot; };
        [Parameter(Position=1)]
        public String[] Names
        {
            get { return name; }
            set { name = value; }
        }
        protected override void ProcessRecord()
        {
            PSObject obj = new PSObject();
            // Go through each key and create a property and
            // assign the value to the new property.
            // In the case that the value is a script block, create
            // a ScriptMethod instead.
            foreach ( string key in Hash.Keys )
            {
                if ( Hash[key].GetType().Name == &amp;quot;ScriptBlock&amp;quot; )
                    obj.Methods.Add(
                        new PSScriptMethod(key,(ScriptBlock)Hash[key])
                        );
                else
                    obj.Properties.Add(
                        new PSNoteProperty(key, Hash[key])
                        );
            }
            // update the type names for the new object
            Collection&amp;lt;string&amp;gt; tnames = new Collection&amp;lt;string&amp;gt;();
            obj.TypeNames.Clear();
            foreach ( string tname in Names )
            {
                obj.TypeNames.Add(tname);
            }
            WriteObject(obj);
        }
    }
}

&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;Then I built a script to build and install the snapin &lt;/div&gt;
&lt;div&gt;&lt;pre&gt;# make.ps1
# build my ConversionCmdlets PowerShell
$out          = &amp;quot;Conversion-Cmdlets.dll&amp;quot;
$src          = &amp;quot;convert-HashToObject.cs&amp;quot;,&amp;quot;convert-snapin.cs&amp;quot;
$ref          = &amp;quot;${pshome}/system.management.automation.dll&amp;quot;
$frameworkDir = &amp;quot;${env:windir}/Microsoft.Net/Framework/v2.0.50727&amp;quot;
$csc          = &amp;quot;${frameworkDir}/csc.exe&amp;quot;
$installutil  = &amp;quot;${frameworkDir}/installutil.exe&amp;quot;
&amp;amp;$csc /target:library /out:$out /r:$ref $src
if ( ! (test-path $out) )
{
    Write-Host -red &amp;quot;$out could not be built&amp;quot;
    exit
}
&amp;amp;$installutil $out &amp;gt; install.out 2&amp;gt; install.err
$snapin = get-pssnapin -reg | where {$_.modulename -match $out}
if ( ! $snapin )
{
    Write-Host -red &amp;quot;$out could not be installed&amp;quot;
    exit
}
else
{
    &amp;quot;Snapin created and installed&amp;quot;
}

&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;Here's what it looks like when you use it!&lt;/div&gt;
&lt;div&gt;&lt;pre&gt;PS&amp;gt; add-pssnapin ConversionCmdlets
PS&amp;gt; get-command convert-hashtoobject

CommandType     Name                            Definition
-----------     ----                            ----------
Cmdlet          Convert-HashToObject            Convert-HashToObject [-Hash]...

PS&amp;gt; $a = @{A=1;B=2;C={$this.A};D={$this.A=$args[0]}}|convert-hashtoobject
PS&amp;gt; $a|format-table -auto
A B
- -
1 2
PS&amp;gt; $a.C()
1
PS&amp;gt; $a.D(10)
PS&amp;gt; $a|format-table -auto
 A B
 - -
10 2
PS&amp;gt; $A.C()
10
PS&amp;gt;
&lt;/pre&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=8161607117076325005&amp;page=RSS%3a+PowerShell%3a+Hashtables+and+Objects&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=jtruher.spaces.live.com&amp;amp;GT1=jtruher"&gt;</description><category>PowerShell</category><comments>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!119.entry#comment</comments><guid isPermaLink="true">http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!119.entry</guid><pubDate>Fri, 05 May 2006 21:13:34 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://jtruher.spaces.live.com/blog/cns!7143DA6E51A2628D!119/comments/feed.rss</wfw:commentRss><wfw:comment>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!119.entry#comment</wfw:comment><dcterms:modified>2006-05-14T19:31:54Z</dcterms:modified></item><item><title>All this rushing about</title><link>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!121.entry</link><description>&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;em&gt;This was originally started life as a blog I made for the Microsoft Orchestra&lt;/em&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;I've been thinking about tempo and what it is that makes people rush - here are my thoughts on the topic. &lt;/div&gt;
&lt;div&gt;Many times, we rush &lt;em&gt;when it &lt;b&gt;is&lt;/b&gt; hard&lt;/em&gt;. I think that the reason is that you get nervous about the hard bits and then you think &lt;i&gt;ok - this goes really, really fast, if I play it as fast as I can, I should be able to keep up&lt;/i&gt;. There are a few problems with this: 
&lt;ol&gt;
&lt;li&gt;It may be that you can play it faster than you think
&lt;li&gt;Rushing can be contagious; you're playing with your standmate, and they might go a little fast, and you want to catch up
&lt;li&gt;Not enough time is given to the spaces between the notes
&lt;li&gt;(and most importantly) you lose the connection with the rest of the &lt;em&gt;whole&lt;/em&gt; group in concentrating on your little corner of the world. So, in the microcosm of your standmates, you're together, but rushing ahead of the entire orchestra.&lt;/ol&gt;
&lt;p&gt;
&lt;p&gt;Then, of course, there's the rushing where it's too easy, I think that this is associated with music that has a lot of silence in the individual parts. A good example of this is probably the Donizetti &amp;quot;Daughter of the Regiment&amp;quot;. Lots of the parts have little &amp;quot;oom-pah&amp;quot; or &amp;quot;dit-dit&amp;quot; parts - I think these have a tendency to rush because the overall tempo is not internalized (&lt;i&gt;&lt;b&gt;not&lt;/b&gt; by tapping the foot but getting the right subdivision of the overall tempo&lt;/i&gt;).  It's incredibly important that when you play these accompaniment parts that you tune into the player that's got the melody - be sure that you are supporting the melody rather than trying to fill in the silences - the melody takes care of filling in the silence, the accompaning parts just need to &lt;em&gt;accompany&lt;/em&gt;. 
&lt;p&gt; 
&lt;p&gt;What can we do about this?  I think that the &lt;em&gt;most&lt;/em&gt; important thing to do is to take the time to listen to the sounds around you.  Playing together does &lt;em&gt;not&lt;/em&gt; mean that you play your part, the guy next to you plays his part and the whole thing comes together like magic.  Playing together means listening to &lt;em&gt;everything, &lt;/em&gt;especially the players that don't happen to play the part you play.  Also, remember that music making is a &lt;em&gt;social&lt;/em&gt; process, not a technical exercise - &lt;span title="I'm not suggesting that technique is unimportant, it's just not the most important.  I've attended too many performances that were technically excellent but left me unmoved because of the lack of musicality.  I have more to say on that topic, but later"&gt;concentrate on making music, not the technique&lt;/span&gt;(1) - anyway, that's what I try to do.  
&lt;p&gt; 
&lt;p&gt;jim
&lt;p&gt; 
&lt;p&gt;
&lt;dl&gt;
&lt;dt&gt;1
&lt;dd&gt;I'm not suggesting that technique is unimportant, it's just not the most important.  I've attended too many performances that were technically excellent but left me unmoved because of the lack of musicality.  I have more to say on that topic, but later.
&lt;dl&gt;
&lt;p&gt;&lt;/dl&gt;&lt;/dl&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=8161607117076325005&amp;page=RSS%3a+All+this+rushing+about&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=jtruher.spaces.live.com&amp;amp;GT1=jtruher"&gt;</description><category>Music</category><comments>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!121.entry#comment</comments><guid isPermaLink="true">http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!121.entry</guid><pubDate>Fri, 05 May 2006 20:42:43 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://jtruher.spaces.live.com/blog/cns!7143DA6E51A2628D!121/comments/feed.rss</wfw:commentRss><wfw:comment>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!121.entry#comment</wfw:comment><dcterms:modified>2006-05-17T01:05:06Z</dcterms:modified></item><item><title>Music, Hark!</title><link>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!120.entry</link><description>&lt;div&gt;While I make my living working with and planning software, I consider myself a musician rather than a &amp;quot;software guy&amp;quot;. My background is all music, my education was in music, then as a teacher and performer (both singer and instrumentalist). I've been very lucky to have the opportunity to perform with some really great musicians.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;My latest musical endeavor finds me the conductor of the Microsoft Orchestra - when the post opened up a few years ago, I volunteered.  I never thought that I would be an orchestra conductor; I studied choral music and was a choir director and singer for 20 years and have conducted orchestras, but mostly in combination with choirs (like the Brahms Requiem, Dona Nobis Pacem, etc), but never thought I would regularly conduct an orchestra.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;I &lt;em&gt;really &lt;/em&gt;love it - it's a chance for me to learn, to teach, and to make music that I never thought I would get the chance to do.  It is so much fun to build rapport with the players and to bring music out that they didn't think they had in them.  It's also been a great learning experience for me, and has made me a better musician by trying to keep ahead of these folks; making sure that I have something to say that inspires, cajoles or amuses these wonderful people into playing better.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;The MS orchestra is made up of MS employees, family and friends and has been around since the early 90s.  We're getting better and better with each concert and it is &lt;em&gt;so&lt;/em&gt; much fun.  (if you're interested, you can see more at &lt;a href="http://www.msorchestra.org/"&gt;http://www.msorchestra.org/&lt;/a&gt;)&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;j&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=8161607117076325005&amp;page=RSS%3a+Music%2c+Hark!&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=jtruher.spaces.live.com&amp;amp;GT1=jtruher"&gt;</description><category>Music</category><comments>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!120.entry#comment</comments><guid isPermaLink="true">http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!120.entry</guid><pubDate>Wed, 03 May 2006 07:33:40 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://jtruher.spaces.live.com/blog/cns!7143DA6E51A2628D!120/comments/feed.rss</wfw:commentRss><wfw:comment>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!120.entry#comment</wfw:comment><dcterms:modified>2006-05-03T07:33:40Z</dcterms:modified></item><item><title>First PowerShell Blog</title><link>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!116.entry</link><description>&lt;div&gt;I keep getting hounded to blog so here you go.  I'm a PM on the PowerShell team and i'm largely responsible for the PowerShell language (Bruce Payette shares the blame with me in equal portion).  I thought that one of the things that I could do here would be to keep track of all the scripts that I use on a somewhat daily basis.  They've been posted in other venues before, but I can post them here too. I have more on my mind than just PowerShell, but I'll post that under a different category&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;This first script is a script that I use &lt;em&gt;all&lt;/em&gt; the time. I only remember the parameters of cmdlets that I use all the time, and while I can get the parameter information via &lt;code&gt;(get-command &lt;em&gt;cmdlet&lt;/em&gt;).definition&lt;/code&gt;, or from help I don't care for the formatting. I wrote this script to help me with that, it provides me the information in a way that I like. You might like it too. &lt;/div&gt;
&lt;div&gt;&lt;pre&gt;# The Command to retrieve information, Verbose output, show Ubiquitous Parameter info
# get-paraminfo
param ( [string]$cmd, [bool]$raw = $false, [bool]$ubp = $false )

# Formatting directives used in out-special
$type = @{ label = &amp;quot;Type&amp;quot;;      e = { $_.Parametertype.name }}
$man  = @{ label = &amp;quot;Mandatory&amp;quot;; e = { $_.IsMandatory}}
$pos  = @{ label = &amp;quot;Pos&amp;quot;;       e = { $_.Positional}; Align = &amp;quot;right&amp;quot; }
$vp   = @{ label = &amp;quot;PipeValue&amp;quot;; e = { $_.ValueFromPipeline } ; width = 10}
$vppn = @{ label = &amp;quot;PipeName&amp;quot;;  e = { $_.ValueFromPipelineByPropertyName } ; 
           width = 10 }
$parms = &amp;quot;name&amp;quot;,$type,$man,$pos,$vp,$vppn

# Use the special formatting built to output the results in a 
# palatable way
function out-special ()
{
    if ( $raw ) { $input }
    else { $input | format-table $parms -auto }
}

#
# Start Here
#
if ( ! $cmd -or (get-command $cmd ).count )
{
    get-command $cmd 
    Throw &amp;quot;
    -cmd -raw -ubp
    Need single Cmdlet
    &amp;quot;
}

# show the name of the command
$cmd
# and the DLL
get-command $cmd|format-list dll,helpfile | out-host

# here are the ubiquitous parameters
$ub = &amp;quot;ErrorVariable&amp;quot;,&amp;quot;ErrorAction&amp;quot;,&amp;quot;OutBuffer&amp;quot;,&amp;quot;Verbose&amp;quot;,&amp;quot;OutBuffer&amp;quot;,&amp;quot;Debug&amp;quot;
# Get the parameter sets and display the interesting info
foreach ( $pset in (get-command $cmd ).parametersets )
{
    &amp;quot;Parameter Set: &amp;quot; + $pset.name 
    # create a custom &amp;quot;object&amp;quot; so we can print it nicely
    $pset.parameters | foreach-object { 
        # optionally toss the ubiquitous parameters
        if ( $_.Position -lt 0 ) { $p = &amp;quot;named&amp;quot; } else { $p = $_.Position } 
        if ( !($ub -contains $_.name) -or $ubp )
        {
            $_ | add-member NoteProperty Positional $p -pass |
                 add-member NoteProperty ParameterSetName $pset.name -pass  
        }
    } | sort-object Positional | out-special
}
&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;I think that the interesting bits are the additional properties that I add, which extends the object where I want. Also, this script emits either objects or text, depending on whether you use the -raw parameter. You can also get the ubiquitious parameters (-ubp), which I usually suppress. Most of the time, I just use the text output. Here's how it looks against the get-command cmdlet. &lt;/div&gt;
&lt;div&gt;&lt;pre&gt;PS&amp;gt; get-paraminfo get-command
get-command

DLL      : C:\WINDOWS\assembly\GAC_MSIL\System.Management.Automation\1.0.9567.0
           __31bf3856ad364e35\System.Management.Automation.dll
HelpFile : System.Management.Automation.dll-Help.xml

Parameter Set: CmdletSet

Name         Type            Mandatory   Pos PipeValue PipeName
----         ----            ---------   --- --------- --------
ArgumentList Object[]            False     1     False    False
Usage        SwitchParameter     False named     False     True
OutVariable  String              False named     False    False
TotalCount   Int32               False named     False     True
Verb         String[]            False named     False     True
Noun         String[]            False named     False     True
PSSnapin     String[]            False named     False     True


Parameter Set: AllCommandSet

Name         Type            Mandatory   Pos PipeValue PipeName
----         ----            ---------   --- --------- --------
Name         String[]            False     0      True     True
ArgumentList Object[]            False     1     False    False
OutVariable  String              False named     False    False
Usage        SwitchParameter     False named     False     True
CommandType  CommandTypes        False named     False     True
TotalCount   Int32               False named     False     True
&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;So this tells me where the positional parameters are and whether they take pipeline input which is what I want, most of the time. &lt;/div&gt;
&lt;div&gt;jim&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=8161607117076325005&amp;page=RSS%3a+First+PowerShell+Blog&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=jtruher.spaces.live.com&amp;amp;GT1=jtruher"&gt;</description><category>PowerShell</category><comments>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!116.entry#comment</comments><guid isPermaLink="true">http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!116.entry</guid><pubDate>Tue, 02 May 2006 01:08:03 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://jtruher.spaces.live.com/blog/cns!7143DA6E51A2628D!116/comments/feed.rss</wfw:commentRss><wfw:comment>http://jtruher.spaces.live.com/Blog/cns!7143DA6E51A2628D!116.entry#comment</wfw:comment><dcterms:modified>2006-05-02T01:08:03Z</dcterms:modified></item><item><title>Photo Album: May 25</title><link>http://jtruher.spaces.live.com/photos/cns!7143DA6E51A2628D!157/</link><description>&lt;p&gt;May 25&lt;/p&gt;&lt;div&gt;&lt;table cellspacing="0" border="0"&gt;&lt;tr height="8"&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top"&gt;&lt;p&gt;&lt;a href="http://jtruher.spaces.live.com&amp;#47;photos&amp;#47;cns&amp;#33;7143DA6E51A2628D&amp;#33;157&amp;#47;cns&amp;#33;7143DA6E51A2628D&amp;#33;158"&gt;&lt;img src="http://storage.live.com&amp;#47;items&amp;#47;7143DA6E51A2628D&amp;#33;158&amp;#58;thumbnail" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;me&lt;/p&gt;&lt;/td&gt;&lt;td width="15"&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;p&gt;&lt;a href="http://jtruher.spaces.live.com&amp;#47;photos&amp;#47;cns&amp;#33;7143DA6E51A2628D&amp;#33;157&amp;#47;cns&amp;#33;7143DA6E51A2628D&amp;#33;159"&gt;&lt;img src="http://storage.live.com&amp;#47;items&amp;#47;7143DA6E51A2628D&amp;#33;159&amp;#58;thumbnail" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;caturday&lt;/p&gt;&lt;/td&gt;&lt;td width="15"&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;p&gt;&lt;a href="http://jtruher.spaces.live.com&amp;#47;photos&amp;#47;cns&amp;#33;7143DA6E51A2628D&amp;#33;157&amp;#47;cns&amp;#33;7143DA6E51A2628D&amp;#33;160"&gt;&lt;img src="http://storage.live.com&amp;#47;items&amp;#47;7143DA6E51A2628D&amp;#33;160&amp;#58;thumbnail" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;dangerous&lt;/p&gt;&lt;/td&gt;&lt;td width="15"&gt;&lt;/td&gt;&lt;td valign="top"&gt;&lt;p&gt;&lt;a href="http://jtruher.spaces.live.com&amp;#47;photos&amp;#47;cns&amp;#33;7143DA6E51A2628D&amp;#33;157&amp;#47;cns&amp;#33;7143D