<?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; Rant</title>
	<atom:link href="http://ps1.soapyfrog.com/category/rant/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>Cmdlet clashes</title>
		<link>http://ps1.soapyfrog.com/2007/03/06/cmdlet-clashes/</link>
		<comments>http://ps1.soapyfrog.com/2007/03/06/cmdlet-clashes/#comments</comments>
		<pubDate>Tue, 06 Mar 2007 09:56:22 +0000</pubDate>
		<dc:creator>adrian</dc:creator>
				<category><![CDATA[Cmdlets]]></category>
		<category><![CDATA[Grrr]]></category>
		<category><![CDATA[Hint]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Rant]]></category>

		<guid isPermaLink="false">http://ps1.soapyfrog.com/2007/03/06/cmdlet-clashes/</guid>
		<description><![CDATA[One of the things that struck me whilst developing Grrr as a snapin is: what do you do when you have a cmdlet with the same verb-noun pair as an existing cmdlet? If someone else had a cmdlet called, say, out-banner, and that cmdlet was already loaded in a snap-in (perhaps mandated by site policy), [...]]]></description>
			<content:encoded><![CDATA[<p>One of the things that struck me whilst developing <a href="/category/grrr/">Grrr</a> as a snapin is: what do you do when you have a cmdlet with the same verb-noun pair as an existing cmdlet?</p>
<p>If someone else had a cmdlet called, say, <code>out-banner</code>, and that cmdlet was already loaded in a snap-in (perhaps mandated by site policy), would I be able to register and add the Grrr snapin, which also defines it?</p>
<p>I&#8217;ve scanned the available documentation and the language grammar, used introspection in the shell and so on, but could not find anything to deal with this problem.</p>
<p>With projects like <a href="http://www.codeplex.com/PowerShellCX">PowerShell Community Extensions</a> seemingly laying claim to hundreds of common nouns and verbs, I was concerned that the scope for writing unique cmdlets would dry up real fast.</p>
<p><span id="more-62"></span></p>
<p>To determine what would happen, I <a href="/2007/02/26/grrr-11-and-big-invaders/">registered and added</a> <code>Soapyfrog.Grrr</code>, then wrote a new snapin, <code>Soapyfrog.Conflict</code>, with a single cmdlet, <code>out-banner</code>, conflicting with the one in Grrr.</p>
<p>I registered and added this, and was surprised that no warning of a conflict was given. To see if both were added, I tried this:</p>
<pre style='color: #000; background-color: #ccc; '>PS&gt; get-command out-banner

CommandType     Name                        Definition
-----------     ----                        ----------
Cmdlet          Out-Banner                  Out-Banner [-Text] <span>&lt;</span>Str...
Cmdlet          Out-Banner                  Out-Banner [-Text] <span>&lt;</span>Str...
</pre>
<p>Interesting. Both are available, so what happens when I try to invoke it?</p>
<pre style='color: #000; background-color: #ccc; '>PS&gt; out-banner hello
<span style='color: #800; background-color: #ccc'>The term &#39;out-banner&#39; resolved to a cmdlet name that is ambiguous. Pos</span>
<span style='color: #800; background-color: #ccc'>sible matches include: Soapyfrog.Grrr&#x5c;Out-Banner soapyfrog.conflict&#x5c;Ou</span>
<span style='color: #800; background-color: #ccc'>t-Banner.</span>
<span style='color: #800; background-color: #ccc'>At line:1 char:11</span>
<span style='color: #800; background-color: #ccc'>+ out-banner  <span>&lt;</span><span>&lt;</span><span>&lt;</span><span>&lt;</span> hello</span>
</pre>
<p>OK, so at this point, we know it&#8217;s possible to break existing PowerShell scripts by simply registering and adding a new snapin with a same-named cmdlet. Not good. Is there a work-around?</p>
<pre style='color: #000; background-color: #ccc; '>PS&gt; Soapyfrog.Grrr&#x5c;out-banner hello -fg &#39;o&#39;
o   o ooooo o     o      ooo
o   o o     o     o     o   o
ooooo ooo   o     o     o   o
o   o o     o     o     o   o
o   o ooooo ooooo ooooo  ooo
</pre>
<p>Yes! We can fully qualify the cmdlet name with the snapin name and a backslash.</p>
<p>So, it&#8217;s not as bad as I first feared, but as I noted above, you need to be very careful about how you code and run scripts in environments where you can&#8217;t predict what snapins are registered and installed.</p>
<p>I suppose you can create the correct shell environment with Export-Console and run your script with:  </p>
<p><code>powershell -psconsolefile xxx.psc1 -noprofile -command myscript.ps1</code></p>
<p>Or if your script requires a snapin, add the snapin in the script and fully qualify each cmdlet you use.</p>
]]></content:encoded>
			<wfw:commentRss>http://ps1.soapyfrog.com/2007/03/06/cmdlet-clashes/feed/</wfw:commentRss>
		<slash:comments>6</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>Alternate Data Streams</title>
		<link>http://ps1.soapyfrog.com/2007/01/18/alternate-data-streams/</link>
		<comments>http://ps1.soapyfrog.com/2007/01/18/alternate-data-streams/#comments</comments>
		<pubDate>Thu, 18 Jan 2007 11:23:18 +0000</pubDate>
		<dc:creator>adrian</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Rant]]></category>

		<guid isPermaLink="false">http://ps1.soapyfrog.com/2007/01/18/alternate-data-streams/</guid>
		<description><![CDATA[NTFS has the ability to associate multiple data streams (aka forks) to a file. It&#8217;s not very well supported in most Microsoft tools and not very well known, but I use them quite a bit for associating metadata with files. Unfortunately, PowerShell (or rather .NET) doesn&#8217;t support them very well. If I open up a [...]]]></description>
			<content:encoded><![CDATA[<p>NTFS has the ability to associate multiple <a href="http://support.microsoft.com/kb/105763">data streams</a> (aka forks) to a file. It&#8217;s not very well supported in most Microsoft tools and not very well known, but I use them quite a bit for associating metadata with files.</p>
<p>Unfortunately, PowerShell (or rather .NET) doesn&#8217;t support them very well.</p>
<p><span id="more-38"></span></p>
<p>If I open up a  &#8220;Command Prompt&#8221; window (CMD.EXE), I can do things like this:</p>
<pre style="color: white; background-color: black">CMD>echo Hello world > file.txt

CMD>echo Hello other world > file.txt:other

CMD>more < file.txt
Hello world

CMD>more < file.txt:other
Hello other world</pre>
<p>As you can see, file.txt has two streams, the default one and one named other.</p>
<p>Back in PowerShell:</p>
<pre style='color: #eeedf0; background-color: #012456;'>PS>gc file.txt
Hello world
PS>gc file.txt:other
<span style='color: #f00; background-color: #000'>Get-Content : Cannot find drive. A drive with name 'file.txt' does not exist.</span>
<span style='color: #f00; background-color: #000'>At line:1 char:3</span>
<span style='color: #f00; background-color: #000'>+ gc  < < file.txt:other</span>
</pre>
<p>PowerShell doesn't like it. It incorrectly parses the part before the colon as a drive. Even if PowerShell did parse it properly, the underlying .NET bit would fail with <code>System.NotSupportedException: The given path's format is not supported.</code>.</p>
<p>Perhaps Microsoft don't want people using ADS any more... or perhaps they're just not sure... if you <code>Move-Item</code> or <code>Copy-Item</code> the file, the extra stream is moved/copied intact.</p>
]]></content:encoded>
			<wfw:commentRss>http://ps1.soapyfrog.com/2007/01/18/alternate-data-streams/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Text and path gotchas</title>
		<link>http://ps1.soapyfrog.com/2007/01/09/text-and-path-gotchas/</link>
		<comments>http://ps1.soapyfrog.com/2007/01/09/text-and-path-gotchas/#comments</comments>
		<pubDate>Tue, 09 Jan 2007 13:00:45 +0000</pubDate>
		<dc:creator>adrian</dc:creator>
				<category><![CDATA[Rant]]></category>

		<guid isPermaLink="false">http://ps1.soapyfrog.com/2007/01/09/text-and-path-gotchas/</guid>
		<description><![CDATA[PowerShell is now my default Windows shell, but every now and then, little things crop up that make me want to go back to CMD.exe, or better cygwin/zsh. Someone gave me an example of filtering an ASCII text file, stripping out the first 3 characters of each line. On a Mac/UNIX box, you&#8217;d simply do: [...]]]></description>
			<content:encoded><![CDATA[<p>PowerShell is now my default Windows shell, but every now and then, little things crop up that make me want to go back to CMD.exe, or better cygwin/zsh.</p>
<p>Someone gave me an example of filtering an ASCII text file, stripping out the first 3 characters of each line.</p>
<p>On a Mac/UNIX box, you&#8217;d simply do:</p>
<p><code>cut -c4- infile.txt  > outfile.txt</code></p>
<p>With PowerShell, you do:</p>
<p><code>gc infile.txt | % { $_.remove(0,3) } | sc outfile.txt</code></p>
<p><em>As an asside, on my machine, the latter takes 80 times longer to do the job on a 8MB text file than the former , but we&#8217;ll skip over that <img src='http://ps1.soapyfrog.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </em> So, to the gotchas.</p>
<p><strong>Gotcha 1 &#8211; text gets recoded</strong></p>
<p>You might be tempted to do this instead:</p>
<p><code>gc infile.txt | % { $_.remove(0,3) } > outfile.txt</code></p>
<p>If you did, the resulting outfile.txt would be UTF16 and so be double the  size of the original (less the cut 3 chars per line).</p>
<p>You might not notice this at first, as PS1 handles all this sort of thing transparently, but at some point, something might choke on it. You can be specific about output encoding, but that&#8217;s not something you might think about.</p>
<p><strong>Gotcha 2 &#8211; path weirdness</strong></p>
<p>My working area is: <code>c:\Documents and Settings\adrian\My Documents\proj\top</code>. That&#8217;s quite a lot to deal with, so I usually make it shorter by doing this:</p>
<p><code>new-psdrive -name doc: -psprovider filesystem -root "c:\Documents and Settings\adrian\My Documents"</code></p>
<p>so my working directory is actually <code>doc:\proj\top</code>. Much shorter, however, when I run the first command above, I get this:</p>
<pre>
PS doc:\\proj\\top> gc infile.txt | % { $_.remove(0,3) } | sc outfile.txt
Set-Content : The given path's format is not supported.
At line:1 char:42
+ gc infile.txt | % { $_.remove(0,3) } | sc  ﹤﹤﹤﹤ outfile.txt
The pipeline has been stopped.
At line:1 char:30
+ gc 100.txt | % { $_.remove( ﹤﹤﹤﹤ 0,3) } | sc outfile.txt
Set-Content : The given path's format is not supported.
At line:1 char:42
</pre>
<p>Odd that <code>gc</code> didn&#8217;t mind, but <code>sc</code> did.</p>
<p>You can&#8217;t even use <code>resolve-path</code> to fix it because if outfile.txt didn&#8217;t already exist, you&#8217;d get an error&#8230; maybe you need to use <code>new-item -type file</code> or something first? </p>
<p>To be honest, I gave up. PowerShell should really be making things easier, not throwing up barriers at every turn.  </p>
]]></content:encoded>
			<wfw:commentRss>http://ps1.soapyfrog.com/2007/01/09/text-and-path-gotchas/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Minor gripes</title>
		<link>http://ps1.soapyfrog.com/2007/01/04/minor-gripes/</link>
		<comments>http://ps1.soapyfrog.com/2007/01/04/minor-gripes/#comments</comments>
		<pubDate>Thu, 04 Jan 2007 12:09:48 +0000</pubDate>
		<dc:creator>adrian</dc:creator>
				<category><![CDATA[Rant]]></category>

		<guid isPermaLink="false">http://ps1.soapyfrog.com/2007/01/04/minor-gripes/</guid>
		<description><![CDATA[A number of little things bother me about PowerShell, and I&#8217;d just like to outline them here. Adding to arrays According to get-help about_array : &#8220;You can append an element to an existing array by using the += operator. When the operator is used on the array itself, it appends the value.&#8221; This isn&#8217;t completely [...]]]></description>
			<content:encoded><![CDATA[<p>A number of little things bother me about PowerShell, and I&#8217;d just like to outline them here.</p>
<p><strong>Adding to arrays</strong></p>
<p>According to get-help about_array :</p>
<p><em>&#8220;You can append an element to an existing array by using the += operator. When the operator is used on the array itself, it appends the value.&#8221;</em></p>
<p>This isn&#8217;t completely true. If the right hand side of the += is also an array, then the elements of that array are added, not the array itself. This makes it very difficult to build up an array of arrays:</p>
<pre>$a = @() # start with an empty array
$a += 1,2 # this doesn't work - it adds 1 and 2</pre>
<p>so you need to do:</p>
<pre>$a += 1
$a[-1] = 1,2</pre>
<p>I think that either a) the documentation be updated to make this clear or b) fix += so it really does add the RHS as a new element. Otherwise, I&#8217;m going to have to use something like this, which is a bit ugly (but actually much more efficient):</p>
<pre>$a = new-object collections.ArrayList
$a.add( @(1,2) )</pre>
<p><strong>Update</strong>: I&#8217;ve since discovered you can do this instead with the unary comma operator followed by a parenthesised list. The syntax is a bit weird (and hard to guess) but I believe the next version of PowerShell will get better documentation in this area.</p>
<pre>
$a=@()
$a += ,(1,2)</pre>
<p><strong>Integer division</strong></p>
<p>Many languages support integer division, yielding an integer result. Many languages compliment this by offering a modulus division aswell. This is great, because one often has an index into a pseudo-2d array and you want to get the row and column values. Notionally:</p>
<pre>width=10
offset = 17
row = offset DIV width
column = offset MOD width</pre>
<p>This should yield row=1, column=7</p>
<p>In PowerShell:</p>
<pre>[int]$width = 10
[int]$offset = 17
[int]$row = $offset / $width
[int]$column = $offset % $width</pre>
<p>This yields a row of 2. The division, even though both sides are [int] is done using floating point and rounded up.</p>
<p>To work around it, we have to do this:</p>
<pre>[int]$row = [Math]::Floor($offset/$width)</pre>
<p>Not sure of a sensible fix for this&#8230; maybe a new operator like <tt>-idiv</tt> ? or the pythonesque <tt>//</tt></p>
]]></content:encoded>
			<wfw:commentRss>http://ps1.soapyfrog.com/2007/01/04/minor-gripes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PNG and Internet Explorer</title>
		<link>http://ps1.soapyfrog.com/2007/01/01/png-and-internet-explorer/</link>
		<comments>http://ps1.soapyfrog.com/2007/01/01/png-and-internet-explorer/#comments</comments>
		<pubDate>Mon, 01 Jan 2007 11:04:04 +0000</pubDate>
		<dc:creator>adrian</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Rant]]></category>

		<guid isPermaLink="false">http://ps1.soapyfrog.com/2007/01/01/png-and-internet-explorer/</guid>
		<description><![CDATA[Oh dear, it seems that even though this is 2007, the most popular web browser on the planet (IE Will change it over to olde worlde JPEGs later, but in the mean time, if you&#8217;re using Windows, do yourself a favour and install Firefox or IE7. Update: I&#8217;m not entirely sure what the problem is [...]]]></description>
			<content:encoded><![CDATA[<p>Oh dear, it seems that even though this is 2007, the most popular web browser on the planet (IE <br />Will change it over to olde worlde JPEGs later, but in the mean time, if you&#8217;re using Windows, do yourself a favour and install Firefox or IE7.</p>
<p><strong>Update:</strong> I&#8217;m not entirely sure what the problem is here&#8230; this site looks fine with IE6 on Win2k, but not on IE6 on my Wife&#8217;s XP. IE7 looks fine. There appear to be known problems with IE and PNG alpha, and overlapping PNGs, but I don&#8217;t know.</p>
]]></content:encoded>
			<wfw:commentRss>http://ps1.soapyfrog.com/2007/01/01/png-and-internet-explorer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PowerShell is slow</title>
		<link>http://ps1.soapyfrog.com/2007/01/01/powershell-is-slow/</link>
		<comments>http://ps1.soapyfrog.com/2007/01/01/powershell-is-slow/#comments</comments>
		<pubDate>Mon, 01 Jan 2007 08:44:32 +0000</pubDate>
		<dc:creator>adrian</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Rant]]></category>

		<guid isPermaLink="false">http://ps1.soapyfrog.com/2007/01/01/powershell-is-slow/</guid>
		<description><![CDATA[I was going to start the new year with a positive note, but then I thought, lets get a PS1 pet hate out of the way first. PowerShell is slow. There are many ways to demonstrate this, but for this case I&#8217;m going to use a small snippet of code I found to render the [...]]]></description>
			<content:encoded><![CDATA[<p>I was going to start the new year with a positive note, but then I thought, lets get a PS1 pet hate out of the way first.</p>
<p>  PowerShell is slow.</p>
<p>  There are many ways to demonstrate this, but for this case I&#8217;m going to use a small snippet of code I found to render the mandelbrot set to the console window. It&#8217;s not my code and don&#8217;t know where it came from, but algorithm is fairly well known.</p>
<p>  The code to demonstrate this is in a <a href="/assets/mandel2.zip" rel="self">zip file here</a>.</p>
<p>  If you run <code>./mandel2.ps1</code> you get this <a href="/assets/mandel2-screenshot.png" rel="external">pretty picture</a>.</p>
<p>  There is a Windows Scripting Host version. Run this with <code>cscript mandel2.wsf</code>.</p>
<p>  There is a JScript.NET version. Compile it with JSC and or run the supplied one with <code>./mandel2.js.exe</code>.</p>
<p>  There is even a javascript-embedded-in-a-HTML-page version, just click on <a href="/assets/mandel2.html" rel="external">mandel2.html</a>.</p>
<p>  Now on my machine (a 2.66ghz quad core MacPro running XP in Parallels Desktop), I get these results:</p>
<table border="0" >
<tr>
<td >PowerShell</td>
<td >1510 ms</td>
</tr>
<tr>
<td >Windows Scripting Host</td>
<td >90 ms</td>
</tr>
<tr>
<td >JScript.NET</td>
<td >160 ms</td>
</tr>
<tr>
<td >HTML (IE7)</td>
<td >110 ms</td>
</tr>
<tr>
<td >HTML (Firefox 2)</td>
<td >140 ms</td>
</tr>
<tr>
<td >HTML (Safari on OSX)</td>
<td >103 ms</td>
</tr>
</table>
<p>
  OK, so the existing javascript engine in Windows (used by IE and WSF) are pretty good at this. Safari&#8217;s is pretty good (using KJS). So why is this brand spanking new language, PowerShell, so very poor?</p>
<p>  It&#8217;s more than an order of magnitude slower than Microsoft&#8217;s previous attempt at a scripting environment!</p>
<p>  This tardiness really shows itself in other inappropriate projects I&#8217;m working on in PS1. I really hope the PowerShell team at Microsoft address this for version 1.1 &#8211; maybe they should go speak to the jscript team.</p>
]]></content:encoded>
			<wfw:commentRss>http://ps1.soapyfrog.com/2007/01/01/powershell-is-slow/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

