<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ps1.soapyfrog.com &#187; Cool</title>
	<atom:link href="http://ps1.soapyfrog.com/category/cool/feed/" rel="self" type="application/rss+xml" />
	<link>http://ps1.soapyfrog.com</link>
	<description>doing inappropriate things with powershell</description>
	<lastBuildDate>Sun, 26 Aug 2007 22:01:08 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>Grrr 1.1 and Big Invaders</title>
		<link>http://ps1.soapyfrog.com/2007/02/26/grrr-11-and-big-invaders/</link>
		<comments>http://ps1.soapyfrog.com/2007/02/26/grrr-11-and-big-invaders/#comments</comments>
		<pubDate>Mon, 26 Feb 2007 16:29:41 +0000</pubDate>
		<dc:creator>adrian</dc:creator>
				<category><![CDATA[Announce]]></category>
		<category><![CDATA[Cmdlets]]></category>
		<category><![CDATA[Cool]]></category>
		<category><![CDATA[Grrr]]></category>
		<category><![CDATA[Invaders]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://ps1.soapyfrog.com/2007/02/22/grrr-11-and-big-invaders/</guid>
		<description><![CDATA[So I&#8217;ve been spending a bit of time getting to grips with Cmdlets and resurrecting interest in PSInvaders using Grrr and now have something to post. Grrr 1.1 is now Cmdlet based and comes as a Snap-In. The most obvious benefit from this is performance, as I can now present a playable version of PowerShell [...]]]></description>
			<content:encoded><![CDATA[<p>So I&#8217;ve been spending a bit of time getting to grips with Cmdlets and resurrecting interest in <a href="http://ps1.soapyfrog.com/2007/01/02/space-invaders/">PSInvaders</a> using <strong>Grrr</strong> and now have something to post.</p>
<p><strong>Grrr 1.1</strong> is now Cmdlet based and comes as a Snap-In. The most obvious benefit from this is performance, as I can now present a playable version of <strong>PowerShell Big Invaders</strong>.</p>
<p><a href='http://ps1.soapyfrog.com/wp-content/uploads/2007/02/biginvaders-11-inplay.gif' title='BigInvaders 1.1 in play'><img src='http://ps1.soapyfrog.com/wp-content/uploads/2007/02/biginvaders-11-inplay-smooth.jpg' alt='BigInvaders 1.1 in play' /></a></p>
<p>BigInvaders is one of the demo PowerShell scripts that makes use of the Grrr.</p>
<p><strong><a href="http://ps1.soapyfrog.com/downloads/grrr-release-1.1.zip">Download this prerelease version 1.1 of the Grrr snap-in.</a></strong></p>
<p><em>Update: this should now install on Vista &#8211; thanks to Chris Warwick for pointing out some issues</em></p>
<p>There&#8217;s no installer (yet) so to get going, follow this instructions:</p>
<p>Unzip the archive where you want to use it and CD to the top level director where the README file is.</p>
<p>Type: <code>./installgrrr.ps1 -r</code></p>
<p>The <code>-r</code> switch forces it to re-register the snap-in if a (possibly) older version exists. It then adds the snap-in to the current shell.</p>
<p>From here you can CD into the <code>demos</code> directory and run any of the scripts. Each one shows a feature of Grrr, but perhaps the most interesting is in the <code>biginvaders</code> directory.</p>
<p>To run BigInvaders, you need to have a very large console. To achieve this you probably need to set the font size of your console window to 6&#215;8.</p>
<p>If you want sound, you need to install <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=2DA43D38-DB71-4C1B-BC6A-9B6652CD92A3&#038;displaylang=en">DirectX DirectSound</a>. More on why later.</p>
<p>It should work without, silently, but this hasn&#8217;t had much testing as all my XP boxes have it installed <img src='http://ps1.soapyfrog.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  If there are exceptions, start it with the <code>-nosound</code> switch.</p>
<p>Assuming all is well, type <code>./biginvaders.ps1</code> and you should see this title screen:</p>
<p><a href='http://ps1.soapyfrog.com/wp-content/uploads/2007/02/biginvaders-11-intro.gif' title='BigInvaders 1.1 intro screen'><img src='http://ps1.soapyfrog.com/wp-content/uploads/2007/02/biginvaders-11-intro.thumbnail.gif' alt='BigInvaders 1.1 intro screen' /></a></p>
<p>Hit ESC to quit or Space to play. In play, Space fires a missile and arrow keys move left and right. Hit F to toggle FPS display in the top-righthand corner. </p>
<p>The target FPS is 33. I achieve this easily on my MacPro, and my wife&#8217;s Dell (a core 1 duo, 1.66ghz) also just manages.</p>
<p>There are still a few snags to iron out here and I want to add proper PowerShell help and an installer, but it is functional.</p>
<p>I&#8217;ve learned a lot about C#, PowerShell SDK and .NET these last weeks and will write about my findings over the next days. It&#8217;s not all been rosy.</p>
<p>I&#8217;ll also be writing about the features of <strong>Grrr</strong>, and where I want to go with it.</p>
<p>That&#8217;s it for now.</p>
]]></content:encoded>
			<wfw:commentRss>http://ps1.soapyfrog.com/2007/02/26/grrr-11-and-big-invaders/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>IRC chat bot and monitor</title>
		<link>http://ps1.soapyfrog.com/2007/01/31/irc-chat-bot-and-monitor/</link>
		<comments>http://ps1.soapyfrog.com/2007/01/31/irc-chat-bot-and-monitor/#comments</comments>
		<pubDate>Wed, 31 Jan 2007 14:52:16 +0000</pubDate>
		<dc:creator>adrian</dc:creator>
				<category><![CDATA[Cool]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Utility]]></category>

		<guid isPermaLink="false">http://ps1.soapyfrog.com/2007/01/31/irc-chat-bot-and-monitor/</guid>
		<description><![CDATA[Last weekend, I asked my wife if she could think of anything inappropriate or unusual to do with PowerShell. She came up with some good ideas and one of them was to write a chat/IM client. A full client takes time, so with a nod toward PowerShell&#8217;s administrative uses, I wrote a script that forms [...]]]></description>
			<content:encoded><![CDATA[<p>Last weekend, I asked my wife if she could think of anything inappropriate or unusual to do with PowerShell. She came up with some good ideas and one of them was to write a chat/IM client.</p>
<p>A full client takes time, so with a nod toward PowerShell&#8217;s administrative uses, I wrote a script that forms the basis of an <a href="http://www.faqs.org/rfcs/rfc1459.html">IRC</a> chat bot.</p>
<p>This script can be used to pipe messages to a chat channel and/or join a set of channels, returning all messages posted there.</p>
<p>I&#8217;ve sure most of you out there use <del>Microsoft</del> <del>MSN</del> Windows Live Messenger, or even Yahoo! or AOL, so this may just serve as an example of synchronous TCP/IP messaging in PowerShell.</p>
<p><strong>You can download the script here: <a href='http://ps1.soapyfrog.com/wp-content/uploads/2007/01/chat-ircps1.txt' title='chat-irc.ps1'>chat-irc.ps1</a>. </strong></p>
<p>You may need to unblock it according the the instructions in <code>help about_signing</code>.</p>
<p><span id="more-52"></span></p>
<p><strong>Summary of use</strong></p>
<p>This script operates in two modes, sender, or monitor (or both).</p>
<p>Regardless, you need to set up connection info in a hash, eg:</p>
<pre>$coninfo = @{
  server="chat.freenode.net"
  port=6667
  nick="mynick"
  user="myuser"
  pwd="my password if required"
  realname="This is my real name"
  hostname"This is my host name, but is generally ignored"
}
</pre>
<p> <img src='http://ps1.soapyfrog.com/wp-includes/images/smilies/icon_idea.gif' alt=':idea:' class='wp-smiley' />  I&#8217;ve been using chat.freenode.net and my own local hybrid irc server for testing.</p>
<p>To send a message to the #test channel and quit:</p>
<p><code>chat-irc -coninfo $coninfo -sendto "#test" -message "Hello, world"</code></p>
<p>To send output from the pipeline, eg a file:</p>
<p><code>gc file.txt | chat-irc -coninfo $coninfo</code></p>
<p>To monitor a channel for messages:</p>
<p><code>chat-irc -coninfo $coninfo -monitor "#test"</code></p>
<p>This will stay connected until you ctrl+C, are killed by the server, etc, or if <code>chat-irc</code> is sent the message &#8220;stopstopstop&#8221;.</p>
<p>The output is formatted strings containing from/to/message, however these strings are annotated with noteproperties, so you can do:</p>
<p><code>chat-irc -coninfo $coninfo -monitor "#test" select *</code></p>
<p>The properties include sender info (<code>user</code>,<code>host</code>,<code>nick</code>,<code>full</code>), <code>date</code>, <code>to</code> and <code>message</code>.</p>
<p>These two modes can be used together, and the monitor parameter can take<br />
more than one channel, so for example:</p>
<p><code>chat-irc -coninfo $coninfo -monitor "#foo","#bar" -sendto "#test" -message "hello"</code></p>
<p>will send &#8220;hello&#8221; to #test then monitor #foo,#bar and #test for messages.</p>
<p>By default, only messages sent to the monitored channel(s) are output, but you can include private messages with the switch <code>-incprivate</code>, the message of the day with <code>-incmotd</code>, notices with <code>-incnotice</code> and other with <code>-incother</code>.</p>
<p>You can see debug info with -debug and verbose output (all messages)<br />
with -verbose. These latter switches just set the $DebugPreference and $VerbosePreference variables to &#8220;Continue&#8221; in the script&#8217;s scope See <a href="http://ps1.soapyfrog.com/2007/01/29/debug-and-verbose-colouring/">Debug and Verbose Colouring</a> for more information on that.</p>
<p><strong>Examples</strong></p>
<p>Here we get chat-irc to monitor the channel #test2 whilst I (millinad) chat to it in a normal IRC chat client.</p>
<pre>PS> chat-irc -coninfo $coninfo -monitor "#test2" | select date,nick,message|ft -wrap

date                         nick                        message
----                         ----                        -------
31/01/2007 14:21:20          millinad                    hello soapybot
31/01/2007 14:21:30          millinad                    nice to see you here
31/01/2007 14:21:38          millinad                    time for you to go now
31/01/2007 14:21:40          millinad                    stopstopstop
</pre>
<p>and in the chat client:</p>
<pre> * soapybot (n=soapybot@*******) has joined #test2
 <millinad> hello soapybot
 <millinad> nice to see you here
 <millinad> time for you to go now
 <millinad> stopstopstop
 * soapybot (n=soapybot@*******) has left #test2
</pre>
<p>Now lets do the same thing again, but with debug switched on and private messages enabled. We&#8217;ll turn off the pipeline formatting.</p>
<pre style='color: #000; background-color: #ccc; '>PS&gt; chat-irc -coninfo $coninfo -monitor &#34;#test2&#34; -incprivate -debug
<span style='color: #888; background-color: #ccc'>DEBUG: Using connection info:</span>
<span style='color: #888; background-color: #ccc'>DEBUG: server: chat.freenode.net</span>
<span style='color: #888; background-color: #ccc'>DEBUG: port: 6667</span>
<span style='color: #888; background-color: #ccc'>DEBUG: user: soapybot</span>
<span style='color: #888; background-color: #ccc'>DEBUG: nick: soapybot</span>
<span style='color: #888; background-color: #ccc'>DEBUG: pwd: ************</span>
<span style='color: #888; background-color: #ccc'>DEBUG: realname: powershell bot using soapyfrog inout-irc.ps1</span>
<span style='color: #888; background-color: #ccc'>DEBUG: hostname: localhost</span>
freenode-connect : soapybot : ☺VERSION☺
<span style='color: #888; background-color: #ccc'>DEBUG: I *may* have joined channel #test2</span>
millinad : #test2 : hello again
millinad : #test2 : i see you received a ctcp message above. pity you don&#39;t understa
nd them.
millinad : #test2 : time to go again
millinad : soapybot : stopstopstop
</pre>
<p>In the last line, I sent soapybot a direct message to stopstopstop rather than to the channel. Without <code>-incprivate</code> this message would not have been output.</p>
<p><strong>How it works</strong></p>
<p>The script connects to the chat server using <code>System.Net.Sockets.TcpClient</code>. Messages are sent using a <code>System.IO.StreamWriter</code> with ASCII encoding. .NET doesn&#8217;t seem to mind of non ASCII chars are translated in this way.</p>
<p>Reading messages is done differently. We can&#8217;t use a <code>System.IO.StreamReader</code>, because <code>ReadLine</code> blocks if there isn&#8217;t a full line available. </p>
<p>We can&#8217;t use asynchronous reading because it&#8217;s quite hard to use scriptblocks as delegates (although that might change in future versions of PowerShell), and threading is a bit of an unknown quantity in PowerShell.</p>
<p>Instead I use the <code>Net.Sockets.NetworkStream</code> with its <code>DataAvailable</code> and <code>ReadByte</code>. This means I can check if data is available, and if not, idle or send messages, then check again. Reading byte by byte makes the code easier to read, and it&#8217;s not too big a performance hit, we&#8217;re bound by the network and the speed of people typing <img src='http://ps1.soapyfrog.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Lines are processed in the <code>process-line</code> function where the line is parsed and checked for known numeric responses and commands.</p>
<p>The default handling of a message is in the function <code>_onprivmsg</code> where the message is just formatted and decorated and place into the output pipeline.</p>
<p> <img src='http://ps1.soapyfrog.com/wp-includes/images/smilies/icon_idea.gif' alt=':idea:' class='wp-smiley' />  If you wanted to have this bot do something else, you would do it here.</p>
<p><strong>A good chat citizen</strong></p>
<p>This script tries to be a good citizen by throttling it&#8217;s message sending with 1 second delays between messages. This is set with the <code>-throttledelay</code> parameter (milliseconds). The amount of time the script idles when there is no data from the server is 2 seconds, set with the <code>-idledelay</code> parameter.</p>
<p>Even with these values, it&#8217;s still possibly to be killed by a server for flooding. You may want to ask server admin to reduce the flood spec for your bot, or increase the throttledelay.</p>
<p>For example, at chat.freenode.net, piping the output from a directory listing would still cause a flood.</p>
<p>Enjoy <img src='http://ps1.soapyfrog.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://ps1.soapyfrog.com/2007/01/31/irc-chat-bot-and-monitor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Updated get-bufferhtml</title>
		<link>http://ps1.soapyfrog.com/2007/01/25/updated-get-bufferhtml/</link>
		<comments>http://ps1.soapyfrog.com/2007/01/25/updated-get-bufferhtml/#comments</comments>
		<pubDate>Thu, 25 Jan 2007 14:52:11 +0000</pubDate>
		<dc:creator>adrian</dc:creator>
				<category><![CDATA[Announce]]></category>
		<category><![CDATA[Cool]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Utility]]></category>

		<guid isPermaLink="false">http://ps1.soapyfrog.com/2007/01/25/updated-get-bufferhtml/</guid>
		<description><![CDATA[A while back, I posted an article: Console screen grabs in html. I fixed some bugs and added a couple of new features to the script get-bufferhtml.ps1, and have updated the article with examples. Enjoy!]]></description>
			<content:encoded><![CDATA[<p>A while back, I posted an article: <a href="/2007/01/06/console-screen-grabs-in-html/">Console screen grabs in html</a>.</p>
<p>I fixed some bugs and added a couple of new features to the script <a id="p27" href="http://ps1.soapyfrog.com/wp-content/uploads/2007/01/get-bufferhtmlps1.txt" title="get-bufferhtml.ps1">get-bufferhtml.ps1</a>, and have updated the <a href="/2007/01/06/console-screen-grabs-in-html/">article</a> with examples.</p>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://ps1.soapyfrog.com/2007/01/25/updated-get-bufferhtml/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Webserver and RSH in PowerShell</title>
		<link>http://ps1.soapyfrog.com/2007/01/24/webserver-and-rsh-in-powershell/</link>
		<comments>http://ps1.soapyfrog.com/2007/01/24/webserver-and-rsh-in-powershell/#comments</comments>
		<pubDate>Wed, 24 Jan 2007 12:57:45 +0000</pubDate>
		<dc:creator>adrian</dc:creator>
				<category><![CDATA[Cool]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://ps1.soapyfrog.com/2007/01/24/webserver-and-rsh-in-powershell/</guid>
		<description><![CDATA[Ever wanted to control a PowerShell session from a web browser or curl/wget on another machine? Yes? Well it surprisingly simple using PowerShell to script the System.Net.HttpListener. Here&#8217;s a working example with some genuine uses (well useful for me). I&#8217;ll leave all the security and risk concerns as an exercise for the reader What we [...]]]></description>
			<content:encoded><![CDATA[<p>Ever wanted to control a PowerShell session from a web browser or <a href="http://en.wikipedia.org/wiki/CURL">curl/wget</a> on another machine? </p>
<p>Yes? Well it surprisingly simple using PowerShell to script the <code>System.Net.HttpListener</code>. Here&#8217;s a <a id="p46b" href="http://ps1.soapyfrog.com/wp-content/uploads/2007/01/httpdps1.txt">working example</a> with some genuine uses (well useful for me).</p>
<p>I&#8217;ll leave all the security and risk concerns as an exercise for the reader <img src='http://ps1.soapyfrog.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p><span id="more-47"></span></p>
<p>What we have here is a small PowerShell script, <a id="p46" href="http://ps1.soapyfrog.com/wp-content/uploads/2007/01/httpdps1.txt">httpd.ps1</a>, that listens on a port of your choosing (default 8888) using the HTTP protocol, executes supplied PowerShell expressions, the returns the pipeline output to the caller.</p>
<p>To use it, type this in a PowerShell window: </p>
<pre>./httpd</pre>
<p>This will set the web server listening on <code>http://yourhostname:8888/</code>. You can change this to be something else by supplying a prefix as a parameter, eg:</p>
<pre>./httpd http://192.168.0.28:8888/</pre>
<p>or safer (in case it crashes)</p>
<pre>powershell -command ./httpd http://192.168.0.28:8888/</pre>
<p>This parameter must end in a slash.</p>
<p>You&#8217;ll need to open the appropriate port in your firewall, if you intend to try to use this from a different machine.</p>
<p>Once running (and using that example above) you can enter that url into your web browser, and the response you&#8217;ll get should be something like:</p>
<pre>No command supplied.

Syntax is: http://server/?cmd=xxxx

Where xxxx is 'quit' to tell the server to quit
or any PowerShell command.

Eg:  http://server/?cmd=get-process</pre>
<p>You can see from this that you need to supply a command. Try this:</p>
<pre>http://192.168.0.28:8888/?cmd=get-process</pre>
<p>What you get back is a process listing for the host machine.</p>
<p>I use this mostly with the command line tool <a href="http://en.wikipedia.org/wiki/CURL">curl</a> to get command output on my Mac, eg:</p>
<pre>macpro:~ adrian$ curl -g 'http://192.168.0.21:8888/?cmd=ps|where%20{$_.ws%20-gt%2010mb}'

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    836      15    42864      55092   236     8.58   3440 dexplore
    512      14    15736      27316    94    17.20   1512 explorer
    192       6    16092      11160   126     0.12   2748 httpd.vshost
    657      17    20224      31776   112    10.32   3792 iexplore
    419      14     6680      11564    75     9.12   1412 KService
   1004       6    45232      43740   156     2.93   3324 powershell
    185       5    22108      28624   126     0.54   3368 powershell
    163       7    35812      34668   138     1.74   3640 powershell
   1588      57    45812      54516   231   495.46    808 svchost
</pre>
<p>You have to escape the URL for curl, but this executed <code>ps|where {$_.ws -gt 10mb}</code> (all processes with a working set greater than 10mb).</p>
<p>Note that  this script does not show you the output from <code>write-host</code> or any errors, but if you ask for <code>$Error</code> you will get the recent errors returned.</p>
<p>An alternative would be to modify the script to use <a href="/2007/01/06/console-screen-grabs-in-html/">get-bufferhtml</a> to return a full copy of the PowerShell buffer.</p>
<p>Anyways, I learned how easy it is to write a mini web server in .NET and PowerShell, so I&#8217;m happy <img src='http://ps1.soapyfrog.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Oh, one last thing. To stop the script, send it a <code>cmd=quit</code>. You could just ctrl+break in the PowerShell window, but I find that causes the whole host to disappear. </p>
]]></content:encoded>
			<wfw:commentRss>http://ps1.soapyfrog.com/2007/01/24/webserver-and-rsh-in-powershell/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Running pipelines in the background</title>
		<link>http://ps1.soapyfrog.com/2007/01/22/running-pipelines-in-the-background/</link>
		<comments>http://ps1.soapyfrog.com/2007/01/22/running-pipelines-in-the-background/#comments</comments>
		<pubDate>Mon, 22 Jan 2007 14:34:18 +0000</pubDate>
		<dc:creator>adrian</dc:creator>
				<category><![CDATA[Cool]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Rant]]></category>

		<guid isPermaLink="false">http://ps1.soapyfrog.com/2007/01/22/running-pipelines-in-the-background/</guid>
		<description><![CDATA[In the unix world, we&#8217;re used to being able to run the different commands in a pipeline in different threads/processes. This is usually a lot more efficient when the producer/consumer rates vary, and makes use of multiple cores/cpus. For example, cmd1 &#124; cmd2 will run the two commands in separate processes. PowerShell doesn&#8217;t do this. [...]]]></description>
			<content:encoded><![CDATA[<p>In the unix world, we&#8217;re used to being able to run the different commands in a pipeline in different threads/processes. This is usually a lot more efficient when the producer/consumer rates vary, and makes use of multiple cores/cpus.</p>
<p>For example, <code>cmd1 | cmd2</code> will run the two commands in separate processes.</p>
<p>PowerShell doesn&#8217;t do this. Everything runs in one thread, and pipelined objects are processed in batches, one bit at a time. You can control the batch size with the <code>-outBuffer</code> parameter, but things are still done sequentially, with one command in the pipe being busy whilst all others are sitting idle.</p>
<p>Even the venerable CMD.exe will put these two commands <code>tree | more</code> into separate processes.</p>
<p>This aside, what about simply running an arbitrary command (or scriptblock) in the background whilst doing something else?</p>
<p><span id="more-45"></span></p>
<p>PowerShell doesn&#8217;t have any obvious way to do this, but it is possible with <strong>runspaces</strong>. You can create a new runspace and then invoke a pipeline asynchronously.</p>
<p>Here is an <a id="p44" href="http://ps1.soapyfrog.com/wp-content/uploads/2007/01/usingrunspacesps1.txt">example script</a>, but lets go through it step by step.</p>
<pre>$rscfg = [management.automation.runspaces.runspaceconfiguration]::Create()
$rs=[management.automation.runspaces.runspacefactory]::CreateRunspace($rscfg)
$rs.Open()</pre>
<p>Here, we create a <code>runspace</code> with a default configuration. There is an overloaded version of <code>CreateRunspace</code> that takes a <code>PSHost</code> object, so we could pass in <code>$host</code>. In this case we just use the default. We then open the <code>runspace</code>.</p>
<pre>$block = {
  $sum=0
  "adding numbers in background!"
  foreach($i in $input) {
    $sum+=$i
    start-sleep 1 # pretent it takes ages to compute this
    "adding number $i"
  }
  "that's it, sum is $sum"
}
$pipe=$rs.CreatePipeline($block)
</pre>
<p>Here we create the scriptblock <code>$block</code> that we want to run in the background and create a pipeline <code>$pipe</code> for it. The block itself simply takes it time adding up numbers passed to it, yielding textual information to the pipe, ending with the result.</p>
<pre>$writer = $pipe.Input
$pipe.InvokeAsync()
</pre>
<p>Here we simply grab hold of the pipe&#8217;s input then invoke it asynchronously.</p>
<pre>$numwritten = $writer.Write(1..5,$true)
$writer.Close()
</pre>
<p>This is where we give the background pipe some data to play with. <code>Write(1..5,$true)</code> means write the numbers 1 through 5 into the pipeline (<code>$true</code> means send the numbers one at a time instead of all at once).</p>
<pre>1..3 | foreach { start-sleep 1; "busy in foreground $_" }
</pre>
<p>The whole purpose of this example is to show how two different things can be done at once, so here we simply spend 3 seconds pretending to be busy <img src='http://ps1.soapyfrog.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<pre>
$reader = $pipe.Output
while (-not $reader.EndOfPipeline) {
  $o = $reader.Read()
  write-host "$o"
}
</pre>
<p>Here we get the output <code>$reader</code> from the pipeline and whilst there is data, read an object and display it.  </p>
<p>We didn&#8217;t have to do it this way; we could have read the whole thing in one go like this: <code>$out = $reader.ReadToEnd()</code>. The latter might be better if the background work produces a single result, but the line-by-line version may suit something with a lot of output. Although we simple do a <code>write-host "$o"</code> here, this could be a lengthy operation that would run whilst the background operation continues to do work.</p>
<pre>$pipe.Error.ReadToEnd()
$pipe.Dispose()
$rs.Close()
</pre>
<p>Finally we consume any error output and clean up.</p>
<p>If you run the <a id="p44" href="http://ps1.soapyfrog.com/wp-content/uploads/2007/01/usingrunspacesps1.txt">example script</a>, you will see something like this:</p>
<pre>busy in foreground 1
busy in foreground 2
busy in foreground 3
adding numbers in background!
adding number 1
adding number 2
adding number 3
adding number 4
adding number 5
that's it, sum is 15</pre>
<p>This is great, but why is this post categorised as a rant? Well, it&#8217;s very long-winded and in my mind, async job scheduling is something that all shells should do.</p>
<p>It&#8217;s a pity PowerShell doesn&#8217;t let you do something like this:</p>
<pre>{ foo | bar ; wibble}.InvokeAsync()</pre>
<p>or</p>
<pre>invoke-command -async { foo | bar ; wibble }</pre>
<p>You <strong>can</strong> do this, however:</p>
<pre>{ foo | bar ; wibble}.Invoke()</pre>
<p>So how would all this be used? Would it make <a href="/2007/01/02/space-invaders/">space invaders</a> any quicker on a core duo pc? Only a profiler would know.</p>
<p>A single runspace can only have one asynchronous pipeline running and the pipeline cannot be reused. The setup costs are quite high, so you&#8217;d probably have to mess about with a single background pipeline reading work requests and writing them back. </p>
]]></content:encoded>
			<wfw:commentRss>http://ps1.soapyfrog.com/2007/01/22/running-pipelines-in-the-background/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Banners</title>
		<link>http://ps1.soapyfrog.com/2007/01/19/banners/</link>
		<comments>http://ps1.soapyfrog.com/2007/01/19/banners/#comments</comments>
		<pubDate>Fri, 19 Jan 2007 14:37:46 +0000</pubDate>
		<dc:creator>adrian</dc:creator>
				<category><![CDATA[Cool]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Utility]]></category>

		<guid isPermaLink="false">http://ps1.soapyfrog.com/2007/01/19/banners/</guid>
		<description><![CDATA[In the old days, when you printed something out, you&#8217;d have to wander down to the print room and find your output in a stack of fanfold with the job name printed as a large banner on the top. I miss those days so I wrote a banner script to do this: It&#8217;s a script, [...]]]></description>
			<content:encoded><![CDATA[<p>In the old days, when you printed something out, you&#8217;d have to wander down to the print room and find your output in a stack of fanfold with the job name printed as a large banner on the top. I miss those days so I wrote a banner script to do this:</p>
<p><img id="image43" src="http://ps1.soapyfrog.com/wp-content/uploads/2007/01/banner1.gif" alt="banner screenshot" /></p>
<p><span id="more-42"></span></p>
<p>It&#8217;s a script, so execute it directly. It takes a string (or array of strings) as the first argument and two optional parameters, <tt>-fg <em>char</em></tt> to set the foreground character and <tt>-bg <em>char</em></tt> for the background character. The defaults are a solid block and a space. For example:</p>
<pre style='color: #eeedf0; background-color: #012456;'>PS> banner "hello","world" -fg "/"
/   / ///// /     /      ///
/   / /     /     /     /   /
///// ///   /     /     /   /
/   / /     /     /     /   /
/   / ///// ///// /////  ///

/   /  ///  ////  /     ////
/   / /   / /   / /     /   /
/ / / /   / ////  /     /   /
// // /   / /   / /     /   /
/   /  ///  /   / ///// ////

PS>
</pre>
<p><strong>You can download the script here: <a id="p40" href="http://ps1.soapyfrog.com/wp-content/uploads/2007/01/bannerps1.txt">banner.ps1</a>.</strong></p>
<p>Don&#8217;t copy/paste this &#8211; save it directly from the above link. It contains formatted text that may get corrupted.</p>
<p>Enjoy!</p>
<p>[Update] The script will also take input from the pipeline so you can do things like:</p>
<p><tt>[enum]::getnames([consolecolor]) | where { $_ -notlike "dark*"} | banner -fg "#"</tt></p>
<p>to get this:</p>
<pre style='color: #eeedf0; background-color: #012456'>
####  #      ###   ###  #   #
#   # #     #   # #   # #  #
####  #     ##### #     ###
#   # #     #   # #   # #  #
####  ##### #   #  ###  #   #                                                                             

 ###  ####   ###  #   #
#     #   # #   #  # #
#  ## ####  #####   #
#   # #   # #   #   #
 ###  #   # #   #   #                                                                                     

####  #     #   # #####
#   # #     #   # #
####  #     #   # ###
#   # #     #   # #
####  #####  ###  #####                                                                                   

 ###  ####  ##### ##### #   #
#     #   # #     #     ##  #
#  ## ####  ###   ###   # # #
#   # #   # #     #     #  ##
 ###  #   # ##### ##### #   #                                                                             

 ###  #   #  ###  #   #
#   #  # #  #   # ##  #
#       #   ##### # # #
#   #   #   #   # #  ##
 ###    #   #   # #   #                                                                                   

####  ##### ####
#   # #     #   #
####  ###   #   #
#   # #     #   #
#   # ##### ####                                                                                          

#   #  ###   ###  ##### #   # #####  ###
## ## #   # #     #     ##  #   #   #   #
# # # ##### #  ## ###   # # #   #   #####
#   # #   # #   # #     #  ##   #   #   #
#   # #   #  ###  ##### #   #   #   #   #                                                                 

#   # ##### #     #      ###  #   #
 # #  #     #     #     #   # #   #
  #   ###   #     #     #   # # # #
  #   #     #     #     #   # ## ##
  #   ##### ##### #####  ###  #   #                                                                       

#   # #   #  ###  ##### #####
#   # #   #   #     #   #
# # # #####   #     #   ###
## ## #   #   #     #   #
#   # #   #  ###    #   #####                                                                             
</pre>
]]></content:encoded>
			<wfw:commentRss>http://ps1.soapyfrog.com/2007/01/19/banners/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pipe or no pipe?</title>
		<link>http://ps1.soapyfrog.com/2007/01/17/pipe-or-no-pipe/</link>
		<comments>http://ps1.soapyfrog.com/2007/01/17/pipe-or-no-pipe/#comments</comments>
		<pubDate>Wed, 17 Jan 2007 14:50:16 +0000</pubDate>
		<dc:creator>adrian</dc:creator>
				<category><![CDATA[Cool]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Quiz]]></category>

		<guid isPermaLink="false">http://ps1.soapyfrog.com/2007/01/17/pipe-or-no-pipe/</guid>
		<description><![CDATA[Many built-in cmdlets take input from the pipe, but alternatively let you specify an input with the -InputObject parameter. An example is the Get-Member cmdlet. I want to be able to do this with my own functions, but as far as I can tell, there is no built-in mechanism for this for using an specified [...]]]></description>
			<content:encoded><![CDATA[<p>Many built-in cmdlets take input from the pipe, but alternatively let you specify an input with the <code>-InputObject</code> parameter. An example is the <code>Get-Member</code> cmdlet.</p>
<p>I want to be able to do this with my own functions, but as far as I can tell, there is no built-in mechanism for this for using an specified parameter instead of the pipe.</p>
<p>[Updated]</p>
<p><span id="more-37"></span></p>
<p>What I do is this:</p>
<pre># A simple function that multiplies input items by 3
function times3 {
  param($i)
  # this inner function does the actual processing
  function proc($o) {
      $o * 3
  }
  # if -i supplied used instead of std $input
  if ($i) { $input = $i }
  foreach ($o in $input) {
    proc $o
  }
}
</pre>
<p>Normally, you&#8217;d use a function with a <tt>process</tt> block to process each object (<tt>$_</tt>) in the pipeline, but in this case, I iterate over the pipeline&#8217;s <tt>$input</tt> manually. If the <tt>-i</tt> is supplied, <tt>$input</tt> is replaced with its value.</p>
<p>If I run this sequence:</p>
<pre>$debugpreference="Continue"
write-debug "----------- about to call as function"
times3

write-debug "----------- about to pipe 4 numbers in to function"
1..4 | times3

write-debug "----------- about to call as function with -i"
times3 -i (1..4)</pre>
<p>I get this:</p>
<pre style='color: #eeedf0; background-color: #012456;'>PS Documents\\proj\\ps1> ./pipeornot.ps1
<span style='color: #ff0; background-color: #000'>DEBUG: ----------- about to call as function</span>
<span style='color: #ff0; background-color: #000'>DEBUG: ----------- about to pipe 4 numbers in to function</span>
3
6
9
12
<span style='color: #ff0; background-color: #000'>DEBUG: ----------- about to call as function with -in</span>
3
6
9
12
PS Documents\\proj\\ps1> get-bufferhtml > out.html
</pre>
<p>It would be nice if the the manual condition could be avoided by specifying</p>
<pre>param($i=$input)</pre>
<p>but sadly, this does not work.</p>
<p>Maybe in the next version of PowerShell, or perhaps there will be a more specific way of dealing with pipe or no pipe.</p>
]]></content:encoded>
			<wfw:commentRss>http://ps1.soapyfrog.com/2007/01/17/pipe-or-no-pipe/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Getting normality back</title>
		<link>http://ps1.soapyfrog.com/2007/01/14/getting-normality-back/</link>
		<comments>http://ps1.soapyfrog.com/2007/01/14/getting-normality-back/#comments</comments>
		<pubDate>Sun, 14 Jan 2007 07:27:57 +0000</pubDate>
		<dc:creator>adrian</dc:creator>
				<category><![CDATA[Cool]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://ps1.soapyfrog.com/2007/01/14/getting-normality-back/</guid>
		<description><![CDATA[The PowerShelling that I do mostly involves messing around the console window &#8211; dimensions, colours, title, etc. I wanted an easy way to get normality back so I added this to my $PROFILE. Nothing fancy or clever, but here it is: #------------------------------------------------------------------------------ # Save default console state - do it in a script block so [...]]]></description>
			<content:encoded><![CDATA[<p>The PowerShelling that <a href="/2007/01/12/space-invaders-with-sound/">I do</a> mostly involves <a href="/2007/01/03/grrr/">messing around</a> the console window &#8211; dimensions, colours, title, etc.</p>
<p>I wanted an easy way to get normality back so I added this to my <code>$PROFILE</code>.  Nothing fancy or clever, but here it is:</p>
<p><span id="more-35"></span></p>
<pre>#------------------------------------------------------------------------------
# Save default console state - do it in a script block so as not to
# polute global space with the $ui variable
&#038;{
  $ui=$Host.UI.RawUI
  if ($ui) {
    $global:__saved_state = @{
      "wt" = $ui.WindowTitle
      "bw" = $ui.BufferSize.Width
      "bh" = $ui.BufferSize.Height
      "ww" = $ui.WindowSize.Width
      "wh" = $ui.WindowSize.Height
      "fg" = $ui.ForegroundColor
      "bg" = $ui.BackgroundColor
      "cs" = $ui.CursorSize
    }
  }
}
# now a function to reset it
function Reset-Host {
  $ss = $global:__saved_state
  if ($ss) {
    $ui=$Host.UI.RawUI
    $bs=$ui.BufferSize
    $bw=[Math]::Max($ss.bw,$bs.Width)
    $bh=[Math]::Max($ss.bh,$bs.Height)
    $ui.BufferSize = New-Object Management.Automation.Host.Size $bw,$bh
    $ui.WindowSize = New-Object Management.Automation.Host.Size $ss.ww,$ss.wh
    $ui.BufferSize = New-Object Management.Automation.Host.Size $ss.bw,$ss.bh
    $ui.CursorSize=$ss.cs
    $ui.WindowTitle = $ss.wt
    $ui.ForegroundColor = $ss.fg
    $ui.BackgroundColor = $ss.bg
    Clear-Host
  }
  else {
    write-warning "No saved host state"
  }
}
# and a handy alias
New-Alias reset Reset-Host</pre>
<p>The weird bit with setting the buffer size twice is because you can&#8217;t set the buffer size smaller than the current window size.</p>
<p>So that&#8217;s it. Whenever the console is in a terrible state, I just type <code>reset</code> (or <code>Reset-Host</code>) and all is back to normal.</p>
<p>If I ever change my default console window settings through the shortcut that starts it, this will still work.</p>
]]></content:encoded>
			<wfw:commentRss>http://ps1.soapyfrog.com/2007/01/14/getting-normality-back/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Space Invaders with sound!</title>
		<link>http://ps1.soapyfrog.com/2007/01/12/space-invaders-with-sound/</link>
		<comments>http://ps1.soapyfrog.com/2007/01/12/space-invaders-with-sound/#comments</comments>
		<pubDate>Fri, 12 Jan 2007 07:50:23 +0000</pubDate>
		<dc:creator>adrian</dc:creator>
				<category><![CDATA[Cool]]></category>
		<category><![CDATA[Invaders]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://ps1.soapyfrog.com/2007/01/12/space-invaders-with-sound/</guid>
		<description><![CDATA[After yesterday&#8217;s attempts to make noises, I added basic sound support to psinvaders. On my setup, it seems that I can only play one sound at a time, so a new sound stops a previous, and it crackles, but that could be because of poor sound virtualisation in Parallels Desktop (yes, I do all my [...]]]></description>
			<content:encoded><![CDATA[<p>After yesterday&#8217;s attempts to <a href="/2007/01/11/making-noises/">make noises</a>, I added basic sound support to <a href="/2007/01/02/space-invaders/">psinvaders</a>.</p>
<p>On my setup, it seems that I can only play one sound at a time, so a new sound stops a previous, and it crackles, but that could be because of poor sound virtualisation in <a href="http://www.parallels.com/en/products/desktop/">Parallels Desktop</a> (yes, I do all my work on a Mac). </p>
<p><strong>Download it here: <a id="p31" href="http://ps1.soapyfrog.com/wp-content/uploads/2007/01/psinvaders.zip">psinvaders r94</a></strong></p>
<p>Unpack the zipfile, then from the directory where psinvaders.ps1 is, type <code>./psinvaders.ps1</code></p>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://ps1.soapyfrog.com/2007/01/12/space-invaders-with-sound/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Making noises</title>
		<link>http://ps1.soapyfrog.com/2007/01/11/making-noises/</link>
		<comments>http://ps1.soapyfrog.com/2007/01/11/making-noises/#comments</comments>
		<pubDate>Thu, 11 Jan 2007 15:54:08 +0000</pubDate>
		<dc:creator>adrian</dc:creator>
				<category><![CDATA[Cool]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Quiz]]></category>

		<guid isPermaLink="false">http://ps1.soapyfrog.com/2007/01/11/making-noises/</guid>
		<description><![CDATA[There are twothree ways I know of to make noises in PowerShell. 1. Simple and most boring: use the internal speaker&#8217;s beep. write-host "`a`a`a" 2. Slightly better, use the .NET console beep. This plays A above middle C for one second. [console]::beep(440,1000) Both of the above are synchronous, ie, the script blocks until the sound [...]]]></description>
			<content:encoded><![CDATA[<p>There are <del>two</del><ins>three</ins> ways I know of to make noises in PowerShell.</p>
<p>1. Simple and most boring: use the internal speaker&#8217;s beep.</p>
<p><code>write-host "`a`a`a"</code></p>
<p>2. Slightly better, use the .NET console beep. This plays A above middle C for one second.</p>
<p><code>[console]::beep(440,1000)</code></p>
<p>Both of the above are synchronous, ie, the script blocks until the sound has finished. <a href="http://wiredupandfiredup.co.uk/">Richy Rich</a> is doing some interesting stuff with <em>runspaces</em> to do this asynchronously.</p>
<p>3. Lastly, you can play wav files. Sadly, only .wav files. No midi, mp3, mpeg4.. at least I couldn&#8217;t find anything in .net 2.</p>
<pre>$file='C:\\WINDOWS\\Media\\Windows XP Startup.wav'
$sp = new-object Media.SoundPlayer ($file)
$sp.Load();
$sp.Play();
1..5 | % {
  echo "la la"
  sleep 1
}
</pre>
<p>This plays the wav asynchronously, so I feel should be used in a future version of <a href="/2007/01/02/space-invaders/">psinvaders</a> to get those authentic sounds.</p>
<p>So anyone know of a way to play midi files asynchronously in PowerShell with only a few lines of code?</p>
]]></content:encoded>
			<wfw:commentRss>http://ps1.soapyfrog.com/2007/01/11/making-noises/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Script Updates</title>
		<link>http://ps1.soapyfrog.com/2007/01/10/script-updates/</link>
		<comments>http://ps1.soapyfrog.com/2007/01/10/script-updates/#comments</comments>
		<pubDate>Wed, 10 Jan 2007 11:37:20 +0000</pubDate>
		<dc:creator>adrian</dc:creator>
				<category><![CDATA[Cool]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://ps1.soapyfrog.com/2007/01/10/script-updates/</guid>
		<description><![CDATA[After receiving feedback from a few people (thanks!), I&#8217;ve updated two of the scripts posted here previously. Convert images to text (ASCII art) This had a problem where a division by zero error would occur if the specified image file wasn&#8217;t fully qualified. Fixed script is here: convert-image2text.ps1. Console screen grabs in html I&#8217;ve fixed [...]]]></description>
			<content:encoded><![CDATA[<p>After receiving feedback from a few people (thanks!), I&#8217;ve updated two of the scripts posted here previously.</p>
<p><a href="http://ps1.soapyfrog.com/2007/01/07/convert-images-to-text-ascii-art/">Convert images to text (ASCII art)</a></p>
<p>This had a problem where a division by zero error would occur if the specified image file wasn&#8217;t fully qualified. Fixed script is here: <a href="http://ps1.soapyfrog.com/wp-content/uploads/2007/01/convert-image2textps1.txt">convert-image2text.ps1</a>.</p>
<p><a href="http://ps1.soapyfrog.com/2007/01/06/console-screen-grabs-in-html/">Console screen grabs in html</a></p>
<p>I&#8217;ve fixed the colours to match those actually used by the console (ie dark yellow is white and darkmagenta is blue) and fixed a css error. Fixed script is here: <a href="http://ps1.soapyfrog.com/wp-content/uploads/2007/01/get-bufferhtmlps1.txt">get-bufferhtml.ps1</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://ps1.soapyfrog.com/2007/01/10/script-updates/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Convert images to text (ASCII art)</title>
		<link>http://ps1.soapyfrog.com/2007/01/07/convert-images-to-text-ascii-art/</link>
		<comments>http://ps1.soapyfrog.com/2007/01/07/convert-images-to-text-ascii-art/#comments</comments>
		<pubDate>Sun, 07 Jan 2007 11:15:49 +0000</pubDate>
		<dc:creator>adrian</dc:creator>
				<category><![CDATA[Cool]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Utility]]></category>

		<guid isPermaLink="false">http://ps1.soapyfrog.com/2007/01/07/convert-images-to-text-ascii-art/</guid>
		<description><![CDATA[Recently, whilst messing with sprites and the Grrr framework, I got thinking about better graphics for games. As PowerShell is very slow at doing console atomic write operations, a game should really have fewer, larger sprites. I then thought about ASCII art, and wouldn&#8217;t it be great if PowerShell could convert existing images (jpg, png) [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, whilst messing with sprites and the <a href="/2007/01/03/grrr/" rel="self" title="Grrr!">Grrr</a> framework, I got thinking about better graphics for games. </p>
<p>As PowerShell is very slow at doing console atomic write operations, a game should really have fewer, larger sprites. I then thought about ASCII art, and wouldn&#8217;t it be great if PowerShell could convert existing images (jpg, png) and produce lines of text for use with Grrr&#8217;s create-image function.</p>
<p>So my morning&#8217;s work is a PowerShell script that does just that.</p>
<p>You can download it here: <a id="p26" href="http://ps1.soapyfrog.com/wp-content/uploads/2007/01/convert-image2textps1.txt">convert-image2text.ps1 (as a text file)</a></p>
<p>(If you&#8217;re reading this from the RSS feed, the link may be broken &#8211; open the blog page if so)</p>
<p>Unfortunately, it&#8217;s only monochrome. I had a lot of trouble getting a reasonable conversion of RGB or HSV to the console&#8217;s limited colour palette and character range, so in the end, I removed it.</p>
<p>The script uses System.Drawing and demonstrates one (a good?) way of adding an assembly to PowerShell.</p>
<p>Usage:</p>
<pre>./convert-image2text.ps1 imagefile 
      [ -maxwidth nchars ] [-palette ascii | shade | bw ]
</pre>
<p>
Here&#8217;s an example using the default -palette ascii option:</p>
<p><img id="image21" src="http://ps1.soapyfrog.com/wp-content/uploads/2007/01/monolisa-ascii.gif" alt="monolisa-ascii.gif" /></p>
<p>Here&#8217;s the same with the -palette shade option:</p>
<p><img id="image22" src="http://ps1.soapyfrog.com/wp-content/uploads/2007/01/monolisa-shade.gif" alt="monolisa-shade.gif" /><br />
Both are from this source image (click to see full size):</p>
<p><a href="/assets/monalisa.jpg" rel="external"><br />
  <img alt="monalisa-small" src="http://ps1.soapyfrog.com/wp-content/uploads/2007/01/monalisa-small.jpg" /><br />
</a></p>
]]></content:encoded>
			<wfw:commentRss>http://ps1.soapyfrog.com/2007/01/07/convert-images-to-text-ascii-art/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Console screen grabs in html</title>
		<link>http://ps1.soapyfrog.com/2007/01/06/console-screen-grabs-in-html/</link>
		<comments>http://ps1.soapyfrog.com/2007/01/06/console-screen-grabs-in-html/#comments</comments>
		<pubDate>Sat, 06 Jan 2007 19:22:47 +0000</pubDate>
		<dc:creator>adrian</dc:creator>
				<category><![CDATA[Cool]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Utility]]></category>

		<guid isPermaLink="false">http://ps1.soapyfrog.com/2007/01/06/console-screen-grabs-in-html/</guid>
		<description><![CDATA[[Updated 25 Jan 2007, well rewritten ] Something I find myself doing a lot is getting a screen shot of a PowerShell console window and posting it some place. Unfortunately, its always a bitmap, and occasionally, I want it as formatted text. Now, the console is readable via $host.ui.rawui.GetBufferContents, so I wrote a small(ish) script [...]]]></description>
			<content:encoded><![CDATA[<p>[Updated 25 Jan 2007, well rewritten <img src='http://ps1.soapyfrog.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  ]</p>
<p>Something I find myself doing a lot is getting a screen shot of a PowerShell console window and posting it some place. Unfortunately, its always a bitmap, and occasionally, I want it as formatted text.</p>
<p>Now, the console is readable via <code>$host.ui.rawui.GetBufferContents</code>, so I wrote a small(ish) script to do just that, outputting lines of html.</p>
<p>You can download the script here <a id="p27" href="http://ps1.soapyfrog.com/wp-content/uploads/2007/01/get-bufferhtmlps1.txt">get-bufferhtml.ps1</a>.</p>
<p>Put the script somewhere so you can run it by name.</p>
<p>By default, the script will grab lines from the top of the buffer up to, but not including the current line, so if you type in this sequence:</p>
<pre>PS> get-bufferhtml > out.html
PS> get-date
PS> asdasda
PS> get-bufferhtml > out.html
</pre>
<p>You end up with this:</p>
<pre style='color: #eeedf0; background-color: #012456; '>PS> get-bufferhtml > out.html
<span style='color: #ff0; background-color: #000'>WARNING: There must be one or more lines to get</span>
PS> get-date                                                            

25 January 2007 14:17:42                                                

PS> asdasda
<span style='color: #f00; background-color: #000'>The term 'asdasda' is not recognized as a cmdlet, function, operable pr</span>
<span style='color: #f00; background-color: #000'>ogram, or script file. Verify the term and try again.</span>
<span style='color: #f00; background-color: #000'>At line:1 char:7</span>
<span style='color: #f00; background-color: #000'>+ asdasda <span><</span><span><</span><span><</span><span><</span> </span>
</pre>
<p>Note that the first line produced a warning, the second showed the date, the third produced an error and the last command (not shown) produce the above.</p>
<p>That output was then just pasted into this blog entry.</p>
<p><span id="more-7"></span></p>
<p>There are a few options you can play with, all of them described in the comments at the top of the script.</p>
<p>One option is to change the palette. If we continue with the command <code>get-bufferhtml -palette print > out2.html</code>, we get this:</p>
<pre style='color: #000; background-color: #eee; '>PS> get-bufferhtml > out.html
<span style='color: #440; background-color: #fff'>WARNING: There must be one or more lines to get</span>
PS> get-date                                                            

25 January 2007 14:17:42                                                

PS> asdasda
<span style='color: #f00; background-color: #fff'>The term 'asdasda' is not recognized as a cmdlet, function, operable pr</span>
<span style='color: #f00; background-color: #fff'>ogram, or script file. Verify the term and try again.</span>
<span style='color: #f00; background-color: #fff'>At line:1 char:7</span>
<span style='color: #f00; background-color: #fff'>+ asdasda <span><</span><span><</span><span><</span><span><</span> </span>
PS> get-bufferhtml > out.html
</pre>
<p>This is easier on the printer!</p>
<p>Another palette is &#8220;standard&#8221; &#8211; the one used by default if you open a &#8220;Command Prompt&#8221; or indeed any other console application. The key difference here is that DarkMagenta and DarkYellow <em>are</em>. I&#8217;ve no idea why the PowerShell team decided to <a href="/2007/01/08/what-colour-is-yours/">mess the colour palette</a>.</p>
<p>Continuing with the command <code>get-bufferhtml -palette standard > out3.html</code>, we get this:</p>
<pre style='color: #880; background-color: #808; '>PS> get-bufferhtml > out.html
<span style='color: #ff0; background-color: #000'>WARNING: There must be one or more lines to get</span>
PS> get-date                                                            

25 January 2007 14:17:42                                                

PS> asdasda
<span style='color: #f00; background-color: #000'>The term 'asdasda' is not recognized as a cmdlet, function, operable pr</span>
<span style='color: #f00; background-color: #000'>ogram, or script file. Verify the term and try again.</span>
<span style='color: #f00; background-color: #000'>At line:1 char:7</span>
<span style='color: #f00; background-color: #000'>+ asdasda <span><</span><span><</span><span><</span><span><</span> </span>
PS> get-bufferhtml > out.html
PS> get-bufferhtml -palette print > out2.html
</pre>
<p>The default font is whatever your browser wants to use for the PRE tag, but you can override this if you issue a command like <code>get-bufferhtml -palette print -font "tahoma" > out4.html</code> and get:</p>
<pre style='color: #000; background-color: #eee; font-family: "tahoma"; '>PS> get-bufferhtml > out.html
<span style='color: #440; background-color: #fff'>WARNING: There must be one or more lines to get</span>
PS> get-date                                                            

25 January 2007 14:17:42                                                

PS> asdasda
<span style='color: #f00; background-color: #fff'>The term 'asdasda' is not recognized as a cmdlet, function, operable pr</span>
<span style='color: #f00; background-color: #fff'>ogram, or script file. Verify the term and try again.</span>
<span style='color: #f00; background-color: #fff'>At line:1 char:7</span>
<span style='color: #f00; background-color: #fff'>+ asdasda <span><</span><span><</span><span><</span><span><</span> </span>
PS> get-bufferhtml > out.html
PS> get-bufferhtml -palette print > out2.html
PS> get-bufferhtml -palette standard > out3.html
</pre>
<p>Clearly, fixed width fonts are best, but you can do whatever you like. I find that &#8220;Courier New&#8221; is best as the lines naturally line up without inter-line spacing.</p>
]]></content:encoded>
			<wfw:commentRss>http://ps1.soapyfrog.com/2007/01/06/console-screen-grabs-in-html/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Sudoku</title>
		<link>http://ps1.soapyfrog.com/2007/01/05/sudoku/</link>
		<comments>http://ps1.soapyfrog.com/2007/01/05/sudoku/#comments</comments>
		<pubDate>Fri, 05 Jan 2007 11:23:25 +0000</pubDate>
		<dc:creator>adrian</dc:creator>
				<category><![CDATA[Cool]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://ps1.soapyfrog.com/2007/01/05/sudoku/</guid>
		<description><![CDATA[Some time ago, I wrote a Sudoku solver in Java, along with an editor, interactive hint mode, puzzle generator etc, but the project never got finished because of feature creep and I generally got a bit bored of it all. This morning, I resurrected the project and implemented the solver in PowerShell. It&#8217;s not the [...]]]></description>
			<content:encoded><![CDATA[<p>Some time ago, I wrote a Sudoku solver in Java, along with an editor, interactive hint mode, puzzle generator etc, but the project never got finished because of feature creep and I generally got a bit bored of it all.</p>
<p>This morning, I resurrected the project and implemented the solver in PowerShell.</p>
<p>It&#8217;s not the shortest solver in history as it has gone through some performance improvements, but it does work and unless you&#8217;ve got a really hard puzzle, it&#8217;s quite quick too.</p>
<p>Download the script from here:  <a href="/assets/sudoku.ps1.txt" rel="external">sudoku.ps1</a></p>
<p>There are sample puzzles <a href="/assets/sample-puzzle.txt" rel="external">here (simple)</a> and <a href="/assets/profile-puzzle.txt" rel="external">here (very hard)</a>. They are simple text files with numbers separated by white space. A zero indicates a blank in the puzzle.</p>
<p>You run the script like this:</p>
<pre>
PS > ./sudoku.ps1 sample-puzzle.txt
Going to to try to solve this puzzle:
7 . 5  . 3 .  8 . 2
. . 2  8 . 1  4 . .
8 1 .  . . .  . 5 6

. 3 .  1 . 8  . 2 .
. . 1  . 7 .  9 . .
. 9 .  3 . 2  . 4 .

9 8 .  . . .  . 3 7
. . 3  9 . 4  5 . .
2 . 6  . 8 .  1 . 4

Solved!
Guesses 53 (9 were wrong)
Elapsed time 00:00:00.4850316
Result:
7 4 5  6 3 9  8 1 2

3 6 2  8 5 1  4 7 9
8 1 9  2 4 7  3 5 6

4 3 7  1 9 8  6 2 5
6 2 1  4 7 5  9 8 3
5 9 8  3 6 2  7 4 1

9 8 4  5 1 6  2 3 7
1 7 3  9 2 4  5 6 8
2 5 6  7 8 3  1 9 4
</pre>
<p>I welcome any hints on performance or algorithmic improvements. No C# inlining please, it&#8217;s a PowerShell project <img src='http://ps1.soapyfrog.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>The very hard puzzle above takes a very long time to solve. So long, in fact,  that I gave up waiting for it. If there is anyone out there with space time and cpu cycles, please run it and <a href="mailto:ps1@soapyfrog.com?subject=sudoku%20feedback" rel="self">let me know</a> how long it takes <img src='http://ps1.soapyfrog.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p><strong>Update</strong>: I&#8217;ve heard from one person that it takes approx 1.2 <em>days</em> to solve. My original Java app, in contrast takes 4.1 seconds.</p>
<p><strong>Update 2</strong>: It looks like I inspired <a href="http://mark-sheppard.spaces.live.com/blog/cns!1905A40C83BF050F!159.entry">Mark Sheppard to do a better job</a> (ie, not brute force). His PowerShell script solves the hard puzzle in <strong>12 seconds</strong> (9.3 seconds on my Mac). Well done!</p>
]]></content:encoded>
			<wfw:commentRss>http://ps1.soapyfrog.com/2007/01/05/sudoku/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Grrr&#x21;</title>
		<link>http://ps1.soapyfrog.com/2007/01/03/grrr/</link>
		<comments>http://ps1.soapyfrog.com/2007/01/03/grrr/#comments</comments>
		<pubDate>Wed, 03 Jan 2007 11:30:58 +0000</pubDate>
		<dc:creator>adrian</dc:creator>
				<category><![CDATA[Cool]]></category>
		<category><![CDATA[Grrr]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://ps1.soapyfrog.com/2007/01/03/grrr/</guid>
		<description><![CDATA[Despite the title, this is not a rant Grrr is a pet project of mine that came after the exploratory work with psinvaders. I was somewhat dissatisfied with myself for doing so much without seeing how else it could be done, especially with respect to drawing of images, animation, etc. So what is Grrr? Grrr [...]]]></description>
			<content:encoded><![CDATA[<p>Despite the title, this is not a rant <img src='http://ps1.soapyfrog.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>  <strong>Grrr</strong> is a pet project of mine that came after the exploratory work with <a href="/2007/01/02/space-invaders/" rel="self" title="Space Invaders">psinvaders</a>. I was somewhat dissatisfied with myself for doing so much without seeing how else it could be done, especially with respect to drawing of images, animation, etc.</p>
<p>  So what is <strong>Grrr</strong>? <strong>Grrr</strong> is a set of functions written in pure PowerShell that let you create playfields with scrolling viewports, draw lines and images, animate and move sprites, and generally be an inappropriate use of the technology.</p>
<p>  The version of <strong>Grrr</strong> discussed in this article can be <a href="/assets/grrr-r84.zip" rel="self">downloaded from here</a>. Updated versions will appear on the <a href="/downloads/" rel="self" title="Downloads">downloads page</a>.<br />
  To use, you write a script of your own and <em>source</em> it with a dot/period, like this:</p>
<p>  <code>. ./grrr.ps1</code></p>
<p>  I suppose you could do this in your <code>$profile</code>, but I prefer to keep things self contained as PowerShell&#8217;s global scope can get very cluttered very fast.</p>
<div style="float:right">
    <a href="/assets/grrr-test.jpg" rel="external"><img alt="grrr-test_thumb" src="http://ps1.soapyfrog.com/wp-content/uploads/2007/01/grrr-test_thumb.jpg" /></a>
  </div>
<p><strong>Testing</strong></p>
<p>In the Grrr distribution, there is a very mini unit test framework called <code>psunit.ps1</code>.</p>
<p>  The script grrr-test.ps1 uses this to unit test grrr.ps1. Hurrah for test-driven development! The picture shows it in action. Click on it to see the full thing.</p>
<p>  To run the test your self, type <code>./grrr-test.ps1</code> in the directory where this is unzipped.</p>
<p>  <strong>Example scripts<br /></strong><br />
  There are three example scripts. Run them like he unit test script.</p>
<div style="float:right">
    <a href="/assets/grrr-demo-scramble.jpg" rel="external"><img alt="grrr-demo-scramble_thumb" src="http://ps1.soapyfrog.com/wp-content/uploads/2007/01/grrr-demo-scramble_thumb.jpg"/></a>
  </div>
<p>
  They are:<br />
  ⁃ <a href="/assets/grrr-demo-clock.jpg" rel="external">grrr-test-clock.ps1</a> &#8211; a simple script that shows back buffering and drawing lines<br />
  ⁃ <a href="/assets/grrr-demo-sprite.jpg" rel="external">grrr-test-sprite.ps1</a> &#8211; shows animation of sprites&#8230; some controlled semi-manually, and one by a motion path<br />
  ⁃ <a href="/assets/grrr-demo-scramble.jpg" rel="external">grrr-test-scramble.ps1</a> &#8211; show the use of tilemaps to produce the effect of paralax scrolling.</p>
<p>  The latter is very slow and really shows up how poor PowerShell by itself performs.</p>
<p>  Have a look at the code, play around with it, tell me it&#8217;s rubbish if you like <img src='http://ps1.soapyfrog.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>  The next steps for this project are adding a proper game loop controller, with key event handling, fps throttling and a few more motion handlers and behaviours &#8211; I&#8217;d like for sprites to be able to look after themselves, eg respond to proximity of others, shoot things, detect walls, etc.</p>
<p>  I also want to make it faster. Maybe with C# inlining, maybe by making these things cmdlets, maybe by doing it all in C# in a custom host application. Who knows.</p>
]]></content:encoded>
			<wfw:commentRss>http://ps1.soapyfrog.com/2007/01/03/grrr/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

