<?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>Huddled Masses &#187; My Software</title>
	<atom:link href="http://huddledmasses.org/tag/my-software/feed/" rel="self" type="application/rss+xml" />
	<link>http://huddledmasses.org</link>
	<description>You can do more than breathe for free...</description>
	<lastBuildDate>Sat, 28 Jan 2012 21:37:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<cloud domain='huddledmasses.org' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
		<item>
		<title>Writing Cmdlets for the PowerShell Pipeline</title>
		<link>http://huddledmasses.org/writing-cmdlets-for-the-powershell-pipeline/</link>
		<comments>http://huddledmasses.org/writing-cmdlets-for-the-powershell-pipeline/#comments</comments>
		<pubDate>Tue, 06 Nov 2007 05:25:57 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Cmdlet]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[My Software]]></category>
		<category><![CDATA[Pipeline]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[SourceCode]]></category>

		<guid isPermaLink="false">http://HuddledMasses.org/writing-cmdlets-for-the-powershell-pipeline/</guid>
		<description><![CDATA[In a continuation of what is, sadly, becoming a series on how the PowerShell Pipeline works &#8230; Karl Prosser brought to my attention that certain powershell commands which have an -InputObject parameter don&#8217;t actually work when you pass something into it &#8230; so I thought I should create a cmdlet to show you how to [...]]]></description>
			<content:encoded><![CDATA[	<p>In a continuation of what is, <em>sadly</em>, becoming a series on how the <a href="/tag/Pipeline">PowerShell Pipeline</a> works &#8230; <a href="http://powershelllive.com/members/karl.aspx">Karl Prosser</a> brought to my attention that certain powershell commands which have an -InputObject parameter don&#8217;t actually work when you pass something into it &#8230; so I thought I should create a cmdlet to show you how to correctly handle the <code>InputObject</code> parameter with the <code>ValueFromPipeline</code> set so you can pass the input in either way.  </p>

	<h4>To demonstrate the problem, try this:</h4>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #660033; font-weight: bold;">$a</span> <span style="color: #66cc66;">=</span> @<span style="color: #333;">&#40;</span><span style="color: #009900;">&quot;A&quot;</span>,<span style="color: #009900;">&quot;B&quot;</span>,<span style="color: #009900;">&quot;A&quot;</span>,<span style="color: #009900;">&quot;C&quot;</span><span style="color: #333;">&#41;</span><br />
<span style="color: #660033; font-weight: bold;">$a</span> <span style="color: #66cc66;">|</span> <span style="color: #660033;">Select</span> <span style="color: #000066;">-First</span> <span style="color: #cc66cc;">3</span> <span style="color: #000066;">-Unique</span><br />
<span style="color: #660033;">Select</span> <span style="color: #000066;">-First</span> <span style="color: #cc66cc;">3</span> <span style="color: #000066;">-Unique</span> <span style="color: #000066;">-InputObject</span> <span style="color: #660033; font-weight: bold;">$a</span> </div>

	<p>This should expose two weirdnesses about how the <code>Select-Object</code> cmdlet works: </p>

	<ol>
		<li>The -First parameter affects the input before the -Unique parameter does.</li>
	</ol>
	<ol>
		<li>When you pass the input in via -InputObject, the whole array is treated as a single object, and the command basically doesn&#8217;t do anything.</li>
	</ol>

	<p>The big problem with this behavior is that there&#8217;s essentially no hint that you&#8217;ve done something wrong &#8212; there&#8217;s actually no way to make Select-Object work properly <strong>except</strong> by passing the objects in via the pipeline.  The bigger problem is that it would have been simple for the Microsoft team to catch this and alert you, but they didn&#8217;t &#8212; so you probably won&#8217;t even notice there&#8217;s a problem until you run it on a trivial data set like my example.  The even <strong>bigger problem</strong> is that it doesn&#8217;t just affect Select-Object (try it with Where-Object, just for instance). <span id="more-458"></span></p>

	<h4>The simplest fix</h4>

	<p>When this came up in the #PowerShell <span class="caps">IRC</span> channel <a href="http://nivot.org">Oisin</a> initially defended this as an unavoidable side effect of the way the cmdlet system works. However, after playing with the idea for a bit, we found it&#8217;s actually trivial to stop, although I found it hard to explain without actually <a href="/wordpress/wp-content/uploads/2007/11/testpipelinecommand1.cs">demonstrating an alternative</a>. The simplest possible alternative is just to throw an exception if the value is passed in as an argument instead of via the pipeline. That would preserve the same level of functionality you have now &#8212; but cause an error in those cases where it wouldn&#8217;t work anyway.</p>

	<div class="csharp code csharp" style="font-family:monospace;"><br />
<span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">override</span> <span style="color: #0600FF;">void</span> BeginProcessing<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>_input <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">throw</span> <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> ArgumentException<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;You must pass InputObject via the pipeline!&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp;<span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">BeginProcessing</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
<span style="color: #000000;">&#125;</span></div>

	<h4>A better way to handle input</h4>

	<p>Of course, you can do better than that  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=';)' class='wp-smiley' /> .  So, I hereby present the first version of my <a href="/wordpress/wp-content/uploads/2007/11/testpipelinecommand2.cs">PowerShell Pipeline Template Cmdlet</a>.  It&#8217;s pretty simple really (once you get past all the cmdlet overhead): basically, you check in the <code>BeginProcess()</code> method to see if the <code>InputObject</code> parameter has been set, and set an alternate private variable. Then, in the <code>ProcessRecord()</code> method, we have two alternate computation paths: the normal path, and a second path for when the collection is passed in as an argument.  In that case, you recurse and call the ProcessRecord method once for each item in the collection.</p>

	<p>I&#8217;m sure some of you will have some improvements you can make, feel free to continue the development on the PowerShell Central <a href="http://powershellcentral.com/scripts/43">scripts page</a> or by sending feedback in the form below, but for now, here&#8217;s <a href="/wordpress/wp-content/uploads/2007/11/testpipelinecmdlet.7z">the Test-Pipeline Cmdlet Binary</a> and the <a href="/wordpress/wp-content/uploads/2007/11/testpipelinecommand2.cs">source code</a>.</p>

	<h4>The Code</h4>

	<div class="csharp code csharp" style="font-family:monospace;"><br />
<span style="color: #008080; font-style: italic;">// An improvement! Now we accept a single object (like Select-Object does)</span><br />
<span style="color: #008080; font-style: italic;">// But, unlike Select-Object, if an array is passed into the argument -InputObject </span><br />
<span style="color: #008080; font-style: italic;">// we still manage to process each item in the array, as we would in the pipeline</span><br />
<span style="color: #008080; font-style: italic;">//</span><br />
<span style="color: #008080; font-style: italic;">// Try it out: &nbsp; &quot;a&quot;,&quot;b&quot;,&quot;c&quot;| Test-Pipeline -verbose</span><br />
<span style="color: #008080; font-style: italic;">// Versus this: &nbsp;Test-Pipeline -verbose -input @(&quot;a&quot;,&quot;b&quot;,&quot;c&quot;)</span><br />
<span style="color: #008080; font-style: italic;">//</span><br />
<span style="color: #008080; font-style: italic;">// If you don't set the -verbose flag, you shouldn't be able to tell them apart</span><br />
<span style="color: #008080; font-style: italic;">// The first way, the &quot;1&quot; invocation hits ProcessRecord for &quot;a&quot; </span><br />
<span style="color: #008080; font-style: italic;">// ... before the &quot;2&quot; invocation hits BeginProcessing()</span><br />
<span style="color: #008080; font-style: italic;">//</span><br />
<span style="color: #008080; font-style: italic;">// Version History</span><br />
<span style="color: #008080; font-style: italic;">// &nbsp; &nbsp;1.0 Just throws an exception</span><br />
<span style="color: #008080; font-style: italic;">// &nbsp; &nbsp;2.0 Finds a way to enumerate ProcessRecord from BeginProcessing</span><br />
<span style="color: #008080; font-style: italic;">// &nbsp; &nbsp; &nbsp; &nbsp;There is still a slight difference, which you can see if you test these:</span><br />
<span style="color: #008080; font-style: italic;">// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Test-Pipeline 1 -input @(&quot;a&quot;,&quot;b&quot;,&quot;c&quot;) -verbose | Test-Pipeline 2 -verbose</span><br />
<span style="color: #008080; font-style: italic;">// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;a&quot;,&quot;b&quot;,&quot;c&quot; | Test-Pipeline 1 -verbose | Test-Pipeline 2 -verbose</span><br />
<span style="color: #008080; font-style: italic;">// &nbsp; &nbsp;2.3 Recursed from inside ProcessRecord instead of BeginProcessing</span><br />
<span style="color: #008080; font-style: italic;">// &nbsp; &nbsp; &nbsp; &nbsp;Makes the execution look identical in the test case from 2.0</span><br />
<span style="color: #008080; font-style: italic;">////////////////////////////////////////////////////////////////////////////////</span><br />
<span style="color: #0600FF;">using</span> <span style="color: #008080;">System</span><span style="color: #008000;">;</span><br />
<span style="color: #0600FF;">using</span> <span style="color: #008080;">System.Collections.Generic</span><span style="color: #008000;">;</span><br />
<span style="color: #0600FF;">using</span> <span style="color: #008080;">System.Text</span><span style="color: #008000;">;</span><br />
<span style="color: #0600FF;">using</span> <span style="color: #008080;">System.Management.Automation</span><span style="color: #008000;">;</span><br />
<span style="color: #0600FF;">using</span> <span style="color: #008080;">System.Collections</span><span style="color: #008000;">;</span><br />
<br />
<span style="color: #0600FF;">namespace</span> Huddled.<span style="color: #0000FF;">TestSnapin</span><br />
<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Cmdlet<span style="color: #000000;">&#40;</span>VerbsDiagnostic.<span style="color: #0000FF;">Test</span>, <span style="color: #666666;">&quot;Pipeline&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> TestPipelineCommand <span style="color: #008000;">:</span> Cmdlet<br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">#region Parameters</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">/// &lt;summary&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">/// This is just a name parameter for decorating test cases :)</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">/// &lt;/summary&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Parameter<span style="color: #000000;">&#40;</span>Position <span style="color: #008000;">=</span> <span style="color: #FF0000;">0</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Mandatory <span style="color: #008000;">=</span> <span style="color: #0600FF;">false</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ValueFromPipelineByPropertyName <span style="color: #008000;">=</span> <span style="color: #0600FF;">false</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HelpMessage <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;A Name for Verbose output&quot;</span><span style="color: #000000;">&#41;</span>, ValidateNotNullOrEmpty<span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> Name<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> _name<span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; set <span style="color: #000000;">&#123;</span> _name <span style="color: #008000;">=</span> value<span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #FF0000;">string</span> _name <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;TestPipeline&quot;</span><span style="color: #008000;">;</span><br />
<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Parameter<span style="color: #000000;">&#40;</span>Position <span style="color: #008000;">=</span> <span style="color: #FF0000;">1</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Mandatory <span style="color: #008000;">=</span> <span style="color: #0600FF;">true</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ValueFromPipeline <span style="color: #008000;">=</span> <span style="color: #0600FF;">true</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HelpMessage <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;Help Text&quot;</span><span style="color: #000000;">&#41;</span>, ValidateNotNullOrEmpty<span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">object</span> InputObject<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> _input<span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; set <span style="color: #000000;">&#123;</span> _input <span style="color: #008000;">=</span> value<span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #FF0000;">object</span> _input<span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #FF0000;">bool</span> _isArgument <span style="color: #008000;">=</span> false<span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080;">#endregion</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">override</span> <span style="color: #0600FF;">void</span> BeginProcessing<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WriteVerbose<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">String</span>.<span style="color: #0000FF;">Format</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;Begin Processing {0}&quot;</span>, Name<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>_input <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span> <span style="color: #008000;">&amp;&amp;</span> _input <a href="http://www.google.com/search?q=is+msdn.microsoft.com"><span style="color: #008000;">is</span></a> ICollection<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _isArgument <span style="color: #008000;">=</span> true<span style="color: #008000;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; StringBuilder output <span style="color: #008000;">=</span> <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> StringBuilder<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;There's input: &quot;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">object</span> _in <span style="color: #0600FF;">in</span> <span style="color: #000000;">&#40;</span>ICollection<span style="color: #000000;">&#41;</span>_input<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; output.<span style="color: #0000FF;">AppendFormat</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;{0}, &quot;</span>, _in<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WriteVerbose<span style="color: #000000;">&#40;</span>output.<span style="color: #0000FF;">ToString</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">BeginProcessing</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">override</span> <span style="color: #0600FF;">void</span> ProcessRecord<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #008000;">!</span>_isArgument<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// This is the normal ProcessRecord code</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WriteVerbose<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">String</span>.<span style="color: #0000FF;">Format</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;Process: {0}&quot;</span>, _input<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WriteObject<span style="color: #000000;">&#40;</span>_input<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// This is what we have to do unwrap -InputObject as Arg</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ICollection _collection <span style="color: #008000;">=</span> _input<span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _isArgument <span style="color: #008000;">=</span> false<span style="color: #008000;">;</span> <span style="color: #008080; font-style: italic;">// unset isCollection before recursing</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">object</span> _in <span style="color: #0600FF;">in</span> <span style="color: #000000;">&#40;</span>ICollection<span style="color: #000000;">&#41;</span>_collection<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; InputObject <span style="color: #008000;">=</span> _in<span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ProcessRecord<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">override</span> <span style="color: #0600FF;">void</span> EndProcessing<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WriteVerbose<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">String</span>.<span style="color: #0000FF;">Format</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;End Processing {0}&quot;</span>, Name<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">EndProcessing</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<span style="color: #000000;">&#125;</span></div>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/writing-cmdlets-for-the-powershell-pipeline/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>XamlReader and Resource Library fonts in WPF</title>
		<link>http://huddledmasses.org/xamlreader-and-resource-library-fonts-in-wpf/</link>
		<comments>http://huddledmasses.org/xamlreader-and-resource-library-fonts-in-wpf/#comments</comments>
		<pubDate>Thu, 30 Aug 2007 05:15:16 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[.Net]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[My Software]]></category>
		<category><![CDATA[PoshConsole]]></category>
		<category><![CDATA[WPF]]></category>

		<guid isPermaLink="false">http://HuddledMasses.org/jaykul/xamlreader-and-resource-library-fonts-in-wpf/</guid>
		<description><![CDATA[Microsoft has provided some very good documentation on how to package fonts with WPF applications, and I&#8217;ve been following it in several different ways in different apps I&#8217;ve written. Recently I provided a feature in Posh Console which allows you to load the startup banner from an external file: StartupBanner.xaml. Loading the banner from an [...]]]></description>
			<content:encoded><![CDATA[	<p>Microsoft has provided some <a href="http://msdn2.microsoft.com/en-us/library/ms753303.aspx">very good documentation</a> on how to package fonts with <span class="caps">WPF</span> applications, and I&#8217;ve been following it in several different ways in different apps I&#8217;ve written.  Recently I provided a feature in <a href="http://CodePlex.com/PoshConsole">Posh Console</a> which allows you to  load the startup banner from an external file: StartupBanner.xaml.  </p>

	<p>Loading the banner from an external <span class="caps">XAML</span> file means that users can configure their own startup banner and make it look however they like, but it broke our default banner.  The startup banner we&#8217;ve been using has a logo and some text which are all defined in pure <span class="caps">XAML</span> and uses several fonts which we had embedded in a FontLibrary.dll resource assembly. It worked great as long as the <span class="caps">XAML</span> was defined in the application, but as soon as we removed it to an external file and loaded it in using the <a href="http://msdn2.microsoft.com/en-us/library/ms590398.aspx" title=" XmlReader ">XamlReader.Load</a> method, the fonts all went to the fallback default fonts instead of our embedded ones. </p>

	<p>Normally this might not be a big deal, but since our logo is based on the &#8220;Q&#8221; in a Quake-like font &#8230; it looks really lame without fonts.  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=':D' class='wp-smiley' />  Apparently, when you load external <span class="caps">XAML</span>, it can&#8217;t use the <a href="http://msdn2.microsoft.com/en-us/library/ms753303.aspx#creating_a_font_resource_library">Font Resource Library</a> resources.  At this point, I can&#8217;t seem to find anything to indicate why this is the case, but I suspect it has to do with the fact that the external, loaded <span class="caps">XAML</span> <a href="http://msdn2.microsoft.com/en-us/library/aa970910.aspx">only has partial trust</a>, and since the font is in an external assembly instead of embedded in the partial trust content, it can&#8217;t get to it.  However, it might be simpler than that: it might just be that the base <span class="caps">URI</span> for the externally loaded <span class="caps">XAML</span> is an actual file location rather than one of the <code>pack://,,,application/</code> type URIs, so the slightly odd font path doesn&#8217;t resolve.</p>

	<p>In any case, I found a way around it, which is of course, why I&#8217;m writing all of this down.  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=':)' class='wp-smiley' />  <span id="more-428"></span> If you declare <span class="caps">WPF</span> <em>resources</em> in your project, you can inject them into the <span class="caps">WPF</span> objects loaded from the <span class="caps">XAML</span> to make them available to them. So for instance, I have a font called &#8220;Quake&#8221; in the FontLibrary assembly.  I can declare it as a resource in my application&#8217;s <span class="caps">XAML</span> (at the app level, window level, or wherever).</p>

	<div class="xml code xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Style</span> <span style="color: #000066;">x:Key</span>=<span style="color: #ff0000;">&quot;POSHFont&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Setter</span> <span style="color: #000066;">Property</span>=<span style="color: #ff0000;">&quot;TextElement.FontFamily&quot;</span> <span style="color: #000066;">Value</span>=<span style="color: #ff0000;">&quot;/FontLibrary;Component/#QUAKE&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Style<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div>

	<p>The font in that style gets resolved in full trust with the <em>pack</em> <span class="caps">URI</span>, and it works fine when used from my application. Having created that, I can do the same thing in the external <span class="caps">XAML</span> files, and apply the style to the text as a <a href="http://msdn2.microsoft.com/en-us/library/ms748942.aspx">DynamicResource</a> &#8230;
 and even feel free to override parts of the style if I want to.  For instance, even though the style might specify a FontSize, if I refer to the style on this text block and specify my own FontSize, the one that&#8217;s on the TextBlock (or Paragraph, or Run, or whatever) will be used.  Now, we&#8217;re not quite done yet, because although they look the same in source, the fonts won&#8217;t resolve properly in the externally loaded <span class="caps">XAML</span>.</p>

	<div class="xml code xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;TextBlock</span> <span style="color: #000066;">TextAlignment</span>=<span style="color: #ff0000;">&quot;Center&quot;</span> <span style="color: #000066;">Width</span>=<span style="color: #ff0000;">&quot;180&quot;</span> <span style="color: #000066;">Style</span>=<span style="color: #ff0000;">&quot;{DynamicResource POSHFont}&quot;</span> <span style="color: #000066;">FontSize</span>=<span style="color: #ff0000;">&quot;145&quot;</span> <span style="color: #000066;">Foreground</span>=<span style="color: #ff0000;">&quot;#FF3275B9&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;TextBlock.BitmapEffect<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;BevelBitmapEffect</span> <span style="color: #000066;">BevelWidth</span>=<span style="color: #ff0000;">&quot;1&quot;</span> <span style="color: #000066;">EdgeProfile</span>=<span style="color: #ff0000;">&quot;CurvedOut&quot;</span> <span style="color: #000066;">LightAngle</span>=<span style="color: #ff0000;">&quot;258&quot;</span> <span style="color: #000066;">Relief</span>=<span style="color: #ff0000;">&quot;0.03&quot;</span> <span style="color: #000066;">Smoothness</span>=<span style="color: #ff0000;">&quot;0.565&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/TextBlock.BitmapEffect<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Q<br />
&nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/TextBlock<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div>

	<p>However, because the style is specified as a dynamic resource rather than a static one, I don&#8217;t have to define that resource at all in that <span class="caps">XAML</span> file, but even if I do, when I load the <span class="caps">XAML</span> into my application, I can simply set it&#8217;s resources from the resources that I&#8217;ve loaded in full trust and with the <em>pack://</em> base <span class="caps">URI</span>...  In my case, I have actually defined several fonts as resources on a Document element, so I just copy them all into the element I read in from the <span class="caps">XAML</span> file:</p>

	<div class="csharp code csharp" style="font-family:monospace;">Paragraph banner <span style="color: #008000;">=</span> <span style="color: #000000;">&#40;</span>Paragraph<span style="color: #000000;">&#41;</span>XamlReader.<span style="color: #0000FF;">Load</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">System.<span style="color: #0000FF;">Xml</span></span>.<span style="color: #0000FF;">XmlReader</span>.<span style="color: #0000FF;">Create</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;StartupBanner.xaml&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>banner <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><br />
<span style="color: #000000;">&#123;</span><br />
&nbsp; <span style="color: #008080; font-style: italic;">// Copy over resources from my DOCUMENT to the BANNER</span><br />
&nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> key <span style="color: #0600FF;">in</span> Document.<span style="color: #0000FF;">Resources</span>.<span style="color: #0000FF;">Keys</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <br />
&nbsp; &nbsp; &nbsp; banner.<span style="color: #0000FF;">Resources</span><span style="color: #000000;">&#91;</span>key<span style="color: #000000;">&#93;</span> <span style="color: #008000;">=</span> Document.<span style="color: #0000FF;">Resources</span><span style="color: #000000;">&#91;</span>key<span style="color: #000000;">&#93;</span><span style="color: #008000;">;</span> <br />
&nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; Document.<span style="color: #0000FF;">Blocks</span>.<span style="color: #0000FF;">Add</span><span style="color: #000000;">&#40;</span>_currentParagraph<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
<span style="color: #000000;">&#125;</span></div>

	<p>And that&#8217;s it: <a href="/images/PoshConsole/StartupBanner.png"><img src="/images/PoshConsole/StartupBannerLogo.png" width="182" height="182" alt="PoshConsole Banner" style="padding: 4px; text-align:center; vertical-align:top" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/xamlreader-and-resource-library-fonts-in-wpf/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>PowerShell Host and Custom Formatting</title>
		<link>http://huddledmasses.org/powershell-host-and-custom-formatting/</link>
		<comments>http://huddledmasses.org/powershell-host-and-custom-formatting/#comments</comments>
		<pubDate>Thu, 30 Aug 2007 00:01:09 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[.Net]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[My Software]]></category>
		<category><![CDATA[PoshConsole]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://HuddledMasses.org/jaykul/powershell-host-and-custom-formatting/</guid>
		<description><![CDATA[So, I&#8217;ve been working on PoshConsole for awhile now, and with the help of some of the guys in #PowerShell@irc.freenode.net have been playing with trying to find ways to enhance output, like using ANSI escape sequences, and even creating an Out-WPF cmdlet which can output objects as databound WPF controls which look really good. We [...]]]></description>
			<content:encoded><![CDATA[	<p>So, I&#8217;ve been working on PoshConsole for awhile now, and with the help of some of the guys in #PowerShell@irc.freenode.net have been playing with trying to find ways to enhance output, like using <a href="http://poshconsole.org/images/PoshConsole/AnsiEscapeSequences.jpg"><span class="caps">ANSI</span> escape sequences</a>, and even creating an <a href="http://poshconsole.org/images/PoshConsole/Out-WPF2.png">Out-<span class="caps">WPF</span> cmdlet</a> which can output objects as databound <span class="caps">WPF</span> controls which look really good.</p>

	<p>We have been trying to find a way to incorporate the colored and even bold/italic formatting in a way that would be compatible with the existing format-* cmdlets, and we&#8217;ve even looked at replacing out-default with a cmdlet that would be compatible with the default PowerShell host.  But today I finally locked in on <a href="http://blogs.msdn.com/powershell/archive/2006/04/25/583269.aspx">the import of this post on the PowerShell blog.</a>  It&#8217;s just not possible.</p>

	<p>The format cmdlets (Format-List, Format-Custom, Format-Table, Format-Wide) output data in the form of undocumented .Net objects which are &#8220;subject to change without notice,&#8221; and are therefore basically useless.  Of course, that means that if you want to replace Out-Default you have to not only replace the output, but you have to replace the formatting cmdlets, and of course the Update-FormatData cmdlet too &#8212; in fact, you have to <strong>either</strong> parse the largely undocumented format data files, or create some replacement for them to allow users to specify formatting for types you haven&#8217;t thought of&#8230; </p>

	<p>All of this amounts to what many of you probably already knew: it&#8217;s a lot of work to create a complete PowerShell host, but it&#8217;s at least as much work to create a replacement PowerShell formatter.</p>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/powershell-host-and-custom-formatting/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PoshConsole &#8211; a Smart, Fashionable PowerShell Console</title>
		<link>http://huddledmasses.org/poshconsole-a-smart-fashionable-powershell-console/</link>
		<comments>http://huddledmasses.org/poshconsole-a-smart-fashionable-powershell-console/#comments</comments>
		<pubDate>Thu, 05 Jul 2007 14:31:14 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[My Software]]></category>
		<category><![CDATA[PoshConsole]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://HuddledMasses.org/jaykul/poshconsole-a-smart-fashionable-powershell-console/</guid>
		<description><![CDATA[So, I&#8217;ve been practically invisible for a few weeks here, and liable to be invisible for at least one more week &#8230; this is my vacation time, so it&#8217;s hard to motivate myself to blog about anything. However, I have been spending some time working on a side project: a PowerShell Host. Now, there are [...]]]></description>
			<content:encoded><![CDATA[	<p>So, I&#8217;ve been practically invisible for a few weeks here, and liable to be invisible for at least one more week &#8230; this is my vacation time, so it&#8217;s hard to motivate myself to blog about anything.  However, I have been spending some time working on a side project: a PowerShell Host.</p>

	<p>Now, there are a few other hosts out there, but with <a href="http://www.powershellanalyzer.com/">PowerShell Analyzer</a> seemingly swallowing up <a href="http://powershell.com/">PowerShell IDE</a> and going the <a href="http://www.powershell.com/store/">fifty dollar route</a> &#8230; as an open sourcer and contributor to the <a href="http://CodePlex.com/PowerShellCX">PowerShell Community Extensions</a> it seemed to me that this couldn&#8217;t be that hard, so I started looking for an open source implementation of PSHostRawUserInterface and couldn&#8217;t find one.  I mean, there are a couple of implementations out there, but essentially they are the PowerShell Remoting interface (which actually runs inside PowerShell.exe, and thus doesn&#8217;t seem to implement anything itself) and a half-implemented console block from a Japanese file manager called <a href="http://cvs.sourceforge.jp/cgi-bin/viewcvs.cgi/kuon/kuon/">kuon</a> &#8230; </p>

	<p>So, being myself, I stepped in an implemented it in the weirdest way I could think of: on top of a <span class="caps">WPF</span> RichTextBox.  Yep, that&#8217;s right.  I&#8217;ve made myself a ConsoleTextBox which subclasses the RichTextBox and handles keyboard input etc to behave &#8230; roughly &#8230; the way a Console should.</p>

	<p>It&#8217;s <a href="http://www.codeplex.com/PoshConsole/WorkItem/List.aspx">far from finished</a>, but it <strong>is</strong> working, so this is by way of announcing the first public alpha release of <a href="http://www.codeplex.com/PoshConsole/">PoshConsole</a>! The vast majority of PowerShell scripts will run without a hitch &#8212; the only time you&#8217;ll have problems is with secure string input (eg: passwords), with direct raw buffer interaction, and with running &#8220;legacy&#8221; console applications &#8212; it does not yet redirect standard input/output/error.</p>

	<p>One small tip: if you have the PowerShell Community Extensions installed, you&#8217;ll want to remove the alias they set up to pipe help through &#8220;less&#8221; ... because less is a legacy console app &#8212; you won&#8217;t get any help at all.</p>

	<p>Technorati Tags: <a class="performancingtags" href="http://technorati.com/tag/PowerShell" rel="tag">PowerShell</a>, <a class="performancingtags" href="http://technorati.com/tag/Scripting" rel="tag">Scripting</a>, <a class="performancingtags" href="http://technorati.com/tag/Windows" rel="tag">Windows</a>, <a class="performancingtags" href="http://technorati.com/tag/Command Line" rel="tag">Command Line</a></p>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/poshconsole-a-smart-fashionable-powershell-console/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>PowerShell speaks</title>
		<link>http://huddledmasses.org/powershell-speaks/</link>
		<comments>http://huddledmasses.org/powershell-speaks/#comments</comments>
		<pubDate>Thu, 03 May 2007 03:34:00 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[My Software]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://HuddledMasses.org/jaykul/powershell-speaks/</guid>
		<description><![CDATA[So, a buddy was showing off the &#8220;say&#8221; command in the Mac OS X terminal the other day (my 3 year old daughter was vastly entertained) and I wondered what it would take to do the same thing in Windows PowerShell &#8230; it turns out the answer is, not much. You just type this into [...]]]></description>
			<content:encoded><![CDATA[	<p>So, a buddy was showing off the &#8220;say&#8221; command in the Mac OS X terminal the other day (my 3 year old daughter was vastly entertained) and I wondered what it would take to do the same thing in Windows PowerShell &#8230; it turns out the answer is, not much.  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=':)' class='wp-smiley' />  You just type this into the console:</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #660033; font-weight: bold;">$Voice</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">new-<span style="font-style: normal;">object</span></span> <span style="color: #000066;">-com</span> SAPI.<span style="color: #003366;">SpVoice</span><br />
<span style="color: #660033; font-weight: bold;">$Voice</span>.<span style="color: #003366;">Speak</span><span style="color: #333;">&#40;</span> <span style="color: #009900;">&quot;Hello World!&quot;</span>, <span style="color: #cc66cc;">1</span> <span style="color: #333;">&#41;</span><br />
&nbsp;</div>

	<p>The cool thing about this is that it&#8217;s async, unlike the Mac &#8220;say&#8221; command, so you can go on typing the next command while it&#8217;s speaking. On top of that, you can have it read a text file by just changing that 1 to a 5:</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #660033; font-weight: bold;">$Voice</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">new-<span style="font-style: normal;">object</span></span> <span style="color: #000066;">-com</span> SAPI.<span style="color: #003366;">SpVoice</span><br />
<span style="color: #660033; font-weight: bold;">$Voice</span>.<span style="color: #003366;">Speak</span><span style="color: #333;">&#40;</span> <span style="color: #009900;">&quot;C:\Text\HolyGrail.txt&quot;</span>, <span style="color: #cc66cc;">5</span> <span style="color: #333;">&#41;</span><br />
&nbsp;</div>

	<p>Now, being who I am, and what I am, I wasn&#8217;t content with that, so I wrote myself up a script, <code>Out-Speech</code>, that will speak whatever it&#8217;s given (an array of objects as an argument, or the pipeline objects &#8230; ) and exposes most of the options of the underlying Speech <span class="caps">API</span>.</p>

	<p><span id="more-413"></span></p>

	<p>I&#8217;ll post the code here, but I thought I&#8217;d just mention &#8230; I&#8217;m not really using this in very many places, but it&#8217;s really fun with the <a href="http://huddledmasses.org/jaykul/what-i-learned-today-about-powershell/">Select-Random script</a> I posted earlier. I alias that to &#8220;rand&#8221; and this to &#8220;say&#8221; ... so I can do: <code>cat quotes.txt | rand | say</code> How fun is that?  Yeah, well, or you could use it to report on the progress of long-running scripts, or something else more useful. :-|</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #666666; font-style: italic;"># Out-Speech</span><br />
<span style="color: #666699; font-weight: bold;">param</span><span style="color: #333;">&#40;</span><span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">array</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$Collection</span>, <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #666699; font-weight: bold;">switch</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$wait</span>, <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #666699; font-weight: bold;">switch</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$purge</span>, <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #666699; font-weight: bold;">switch</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$readfiles</span>, <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #666699; font-weight: bold;">switch</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$readxml</span>, <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #666699; font-weight: bold;">switch</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$notxml</span><span style="color: #333;">&#41;</span><br />
<br />
<span style="color: #666699; font-weight: bold;">begin</span><br />
<span style="color: #333;">&#123;</span> &nbsp;<br />
&nbsp; <span style="color: #666699; font-weight: bold;">if</span> <span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$args</span> <span style="color: #000066;">-eq</span> <span style="color: #009900;">'-?'</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
<span style="color: #009900;">''</span><br />
<span style="color: #009900;">'Usage: Out-Speech [[-Collection] &lt;array&gt;]'</span><br />
<span style="color: #009900;">''</span><br />
<span style="color: #009900;">'Parameters:'</span><br />
<span style="color: #009900;">' &nbsp; &nbsp;-Collection : A collection of items to speak.'</span><br />
<span style="color: #009900;">' &nbsp; &nbsp;-? &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: Display this usage information'</span><br />
<span style="color: #009900;">' &nbsp;Switches:'</span><br />
<span style="color: #009900;">' &nbsp; &nbsp;-wait &nbsp; &nbsp; &nbsp; : Wait for the machine to read each item (NOT asynchronous).'</span><br />
<span style="color: #009900;">' &nbsp; &nbsp;-purge &nbsp; &nbsp; &nbsp;: Purge all other speech requests before making this call.'</span><br />
<span style="color: #009900;">' &nbsp; &nbsp;-readfiles &nbsp;: Read the contents of the text files indicated.'</span><br />
<span style="color: #009900;">' &nbsp; &nbsp;-readxml &nbsp; &nbsp;: Treat input as speech XML markup.'</span><br />
<span style="color: #009900;">' &nbsp; &nbsp;-notxml &nbsp; &nbsp; : Do NOT parse XML (if text starts with &quot;&lt;&quot; but is not XML).'</span><br />
<span style="color: #009900;">''</span><br />
<span style="color: #009900;">'Examples:'</span><br />
<span style="color: #009900;">' &nbsp; &nbsp;PS&gt; Out-Speech &quot;Hello World&quot;'</span><br />
<span style="color: #009900;">' &nbsp; &nbsp;PS&gt; Select-RandomLine quotes.txt | Out-Speech -wait'</span><br />
<span style="color: #009900;">' &nbsp; &nbsp;PS&gt; Out-Speech -readfiles &quot;Hitchhiker'</span><span style="color: #009900;">'s Guide To The Galaxy.txt&quot;'</span><br />
<span style="color: #009900;">''</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">exit</span><br />
&nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; <span style="color: #666666; font-style: italic;"># To override this default, use the other flag values given below.</span><br />
&nbsp; <span style="color: #660033; font-weight: bold;">$SPF_DEFAULT</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">0</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;"># Specifies that the default settings should be used. &nbsp;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">## The defaults are:</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">#~ * Speak the given text string synchronously</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">#~ * Not purge pending speak requests</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">#~ * Parse the text as XML only if the first character is a left-angle-bracket (&lt;)</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">#~ * Not persist global XML state changes across speak calls</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">#~ * Not expand punctuation characters into words.</span><br />
&nbsp; <span style="color: #660033; font-weight: bold;">$SPF_ASYNC</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;"># Specifies that the Speak call should be asynchronous.</span><br />
&nbsp; <span style="color: #660033; font-weight: bold;">$SPF_PURGEBEFORESPEAK</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">2</span> <span style="color: #666666; font-style: italic;"># Purges all pending speak requests prior to this speak call.</span><br />
&nbsp; <span style="color: #660033; font-weight: bold;">$SPF_IS_FILENAME</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">4</span> &nbsp; &nbsp; &nbsp;<span style="color: #666666; font-style: italic;"># The string passed is a file name, and the file text should be spoken.</span><br />
&nbsp; <span style="color: #660033; font-weight: bold;">$SPF_IS_XML</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">8</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># The input text will be parsed for XML markup. </span><br />
&nbsp; <span style="color: #660033; font-weight: bold;">$SPF_IS_NOT_XML</span><span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">16</span> &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># The input text will not be parsed for XML markup.</span><br />
&nbsp; <br />
&nbsp; <br />
&nbsp; <span style="color: #660033; font-weight: bold;">$SPF</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$SPF_DEFAULT</span><br />
&nbsp; <span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span><span style="color: #66cc66;">!</span><span style="color: #660033; font-weight: bold;">$wait</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$SPF</span> <span style="color: #66cc66;">+=</span> <span style="color: #660033; font-weight: bold;">$SPF_ASYNC</span> <span style="color: #333;">&#125;</span><br />
&nbsp; <span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$purge</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$SPF</span> <span style="color: #66cc66;">+=</span> <span style="color: #660033; font-weight: bold;">$SPF_PURGEBEFORESPEAK</span> <span style="color: #333;">&#125;</span><br />
&nbsp; <span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$readfiles</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$SPF</span> <span style="color: #66cc66;">+=</span> <span style="color: #660033; font-weight: bold;">$SPF_IS_FILENAME</span> <span style="color: #333;">&#125;</span><br />
&nbsp; <span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$readxml</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$SPF</span> <span style="color: #66cc66;">+=</span> <span style="color: #660033; font-weight: bold;">$SPF_IS_XML</span> <span style="color: #333;">&#125;</span><br />
&nbsp; <span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$notxml</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$SPF</span> <span style="color: #66cc66;">+=</span> <span style="color: #660033; font-weight: bold;">$SPF_IS_NOT_XML</span> <span style="color: #333;">&#125;</span><br />
&nbsp; <br />
&nbsp; <span style="color: #660033; font-weight: bold;">$Voice</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">new-<span style="font-style: normal;">object</span></span> <span style="color: #000066;">-com</span> SAPI.<span style="color: #003366;">SpVoice</span><br />
&nbsp; <br />
&nbsp; <span style="color: #666699; font-weight: bold;">if</span> <span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$collection</span>.<span style="color: #003366;">count</span> <span style="color: #000066;">-gt</span> <span style="color: #cc66cc;">0</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">foreach</span><span style="color: #333;">&#40;</span> <span style="color: #660033; font-weight: bold;">$item</span> <span style="color: #666699; font-weight: bold;">in</span> <span style="color: #660033; font-weight: bold;">$collection</span> <span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$exit</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$Voice</span>.<span style="color: #003366;">Speak</span><span style="color: #333;">&#40;</span> <span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$item</span> <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">out-<span style="font-style: normal;">string</span></span><span style="color: #333;">&#41;</span>, <span style="color: #660033; font-weight: bold;">$SPF</span> <span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; <span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span><br />
<br />
<span style="color: #666699; font-weight: bold;">process</span><br />
<span style="color: #333;">&#123;</span><br />
&nbsp; <span style="color: #666699; font-weight: bold;">if</span> <span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$_</span><span style="color: #333;">&#41;</span><br />
&nbsp; <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$exit</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$Voice</span>.<span style="color: #003366;">Speak</span><span style="color: #333;">&#40;</span> <span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$_</span> <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">out-<span style="font-style: normal;">string</span></span><span style="color: #333;">&#41;</span>, <span style="color: #660033; font-weight: bold;">$SPF</span> <span style="color: #333;">&#41;</span><br />
&nbsp; <span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span><br />
<br />
&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/powershell-speaks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Vista Thumbnailer</title>
		<link>http://huddledmasses.org/vista-thumbnailer/</link>
		<comments>http://huddledmasses.org/vista-thumbnailer/#comments</comments>
		<pubDate>Thu, 01 Mar 2007 05:47:55 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[My Software]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[UserInterface]]></category>

		<guid isPermaLink="false">http://HuddledMasses.org/jaykul/vista-thumbnailer/</guid>
		<description><![CDATA[I&#8217;ve been crazy busy the last few weeks, but I&#8217;ve been really rather distracted from my main project and it&#8217;s past time I got back to it. To really feel like I&#8217;ve moved on, I need to write a bunch of articles here and publish a couple of cool apps and some source code so [...]]]></description>
			<content:encoded><![CDATA[	<p>I&#8217;ve been crazy busy the last few weeks, but I&#8217;ve been really rather distracted from <a href="/category/development/recommender/">my main project</a> and it&#8217;s past time I got back to it.  To really feel like I&#8217;ve moved on, I need to write a bunch of articles here and publish a couple of cool apps and some source code so that I can feel like I&#8217;ve reached a <em>release</em> point.  What I&#8217;ve been playing with in all this coding is the new technology that&#8217;s been coming out of Microsoft in the last couple months: <a href="http://www.microsoft.com/windowsserver2003/technologies/management/powershell/default.mspx">PowerShell</a>, .<span class="caps">NET</span> 3 and <a href="http://wpf.netfx3.com/">WPF</a>, and <a href="http://WindowsVista.com">Windows Vista</a> so you may or may not actually be able to use these apps &#8230;</p>

	<p>The Vista Thumbnailer is a really slick little app that shows off some of what Vista can do &#8230; and some of what <span class="caps">WPF</span> can do.  I&#8217;ll write more about it in the morning, because there&#8217;s some interesting things I learned in the coding of it, but in the meantime, you can <a href="/downloads/VistaThumbnailer.7z">download Vista Thumbnailer</a> (7-Zip file with a config file). The only thing you really need to know is that there&#8217;s a hotkey: Win+X which will bring Thumbnailer back to the foreground even if it&#8217;s minimized in the tray.  I&#8217;ll make the hotkey configurable in version 2, but for now you&#8217;re stuck with Win+X.  The rest you can figure out from the screenshots (<a href="/images/WindowsVista/DWM_Thumbnailer.jpg">0</a> <a href="/images/WindowsVista/DWM_Thumbnailer1.jpg">1</a> <a href="/images/WindowsVista/DWM_Thumbnailer2.jpg">2</a>) and by reading the tooltips on the buttons.  </p>

	<p>Play around.  Let me know what you think.</p>

	<p>(Oh, <a href="/downloads/VistaThumbnailer_Source.7z">source code is here</a> with your usual choice of BSD/Ms-PL/<span class="caps">GPL</span>)</p>

	<p>[New] <strong>Edit:</strong> Continuing</p>

	<p>So &#8230; I&#8217;ve had a lot of questions about this app during it&#8217;s development (from a few friends in our <span class="caps">IRC</span> channel) so it&#8217;s clear that I should try to at least give the highlights of how it works.</p>

	<h3>Thumbnails </h3>

	<p>By now you&#8217;ve probably seen more than your fill of <a href="http://blogs.msdn.com/greg_schechter/archive/2006/03/05/544314.aspx">screenshots</a> of Windows Vista&#8217;s semi-transparent windows, and maybe you&#8217;ve had a chance to try Vista and seen these live-updating thumbnails on the Alt+Tab window, the Flip3D Win+Tab task switcher, and even the task-bar&#8217;s mouse-over (or Win+T) popups.  All of this is possible because of the way Windows does desktop compositing using a new <a href="http://msdn2.microsoft.com/en-us/library/aa969540.aspx" title="DWM">Desktop Window Manager</a>.  This <span class="caps">DWM</span> is actually a process which runs all the time when you have the &#8220;Aero&#8221; interface turned on, but it&#8217;s also an <span class="caps">API</span> exposed through dwmapi.dll &#8230; and one of the deepest fundamental changes to the way Windows work in Vista.  Let me quote from &#8220;one of the developers&#8221; blogs:</p>

	<blockquote>
		<p>... The way an application gets pixels on the screen has fundamentally changed. [In the past] applications were asked by Windows to paint their <em>visible</em> region, and they would paint directly to the buffer that was to be displayed by the video card.  With Windows Vista, applications are asked by Windows to paint their <em>entire surface</em> to an offscreen surface (alternatively known as a bitmap, buffer, or texture), and it&#8217;s up to the <span class="caps">DWM</span> to take all of these offscreen surfaces, and &#8220;compose&#8221; them together to the onscreen buffer.</p>
	</blockquote>

	<p>Because the windows are rendered &#8220;offscreen&#8221; and without regard to what part of the window might actually be visible &#8230; the visual representation can be reused in many places very cheaply &#8212; that is, since the visual representation is just a cached picture, there&#8217;s very little <span class="caps">CPU</span> cost involved in repainting it in many places &#8230; and the caching and repainting are easily handled by the <span class="caps">DWM</span>. Now, the <span class="caps">DWM</span> also does lots of other cool things, like using DirectX and hardware accelleration to do all this extra rendering of these cached surfaces, but despite appearances, this isn&#8217;t really an article about the <span class="caps">DWM</span> &#8212; we&#8217;re here to talk about <span class="caps">JUST</span> the thumbnails. Greg Schechter again:</p>

	<blockquote>
		<p>Thumbnails in the <span class="caps">DWM</span> are not static snapshots of a window.  They&#8217;re dynamic, constant connections between a thumbnail source window, and a place on a target window that that source window will get a &#8220;thumbnail rendering&#8221;. </p>
	</blockquote>

	<p>Basically, the <a href="http://blogs.msdn.com/greg_schechter/archive/2006/09/14/753605.aspx">APIs in the Desktop Window Manager</a> allow you to ask for a certain portion of one Window&#8217;s screen to be painted over (at some specified level of opacity) with all or part of the contents of another Window&#8217;s screen.  In every sense, the thumbnail is just as live and up-to-date as the actual window (since it is, in fact, being painted by the same process).</p>

	<p>So anyway, what I did is I took a &#8220;Thumbnail&#8221; class from <a href="http://11011.net/archives/000653.html">Douglas Stockwell</a> and enhanced it a bit &#8230; it&#8217;s still not quite perfect, but it&#8217;s trivially easy to use now: just pass it a Window handle and it hooks itself up and renders within it&#8217;s available bounds &#8212; mostly.</p>

	<h3>Glass Effect </h3>

	<p>The Vista Thumbnailer app also showcases a couple of other slick <span class="caps">API</span> features.  First, I added a couple of simple wrappers to <a href="http://msdn2.microsoft.com/en-us/library/aa969512.aspx">DwmExtendFrameIntoClientArea</a> and <a href="http://msdn2.microsoft.com/en-us/library/aa969518.aspx">DwmIsCompositionEnabled</a> so that you can easily get the translucent &#8220;glass&#8221; effect on your whole window, or write, for instance: <code>if( !NativeMethods.IsCompositionEnabled ) { MessageBox.Show( &#34;Sorry you can&#39;t use this feature!&#34; ); }</code> &#8230; </p>

	<h3>Hotkeys</h3>

	<p>I also wrote a global hotkey manager class which can be easily added to <span class="caps">WPF</span> applications that want to register global hotkeys.  VistaThumbnailer only has one, to focus it (you can change it by editing the .config file).</p>

	<p>These are global hotkeys, not like the &#8220;Ctrl+O&#8221; for opening a file, but like the Win+R to bring up a run dialog.  They&#8217;re registered through Window&#8217;s RegisterHotkey and UnregisterHotkey APIs, and you get notified of them via window messages (but my HotkeyManager class will handle the WM_HOTKEY message for you).  Here&#8217;s the short-form for how to use them (you can grab the source if you&#8217;d like to borrow the class, but I&#8217;ll be re-releasing this in a few days with some enhancements I&#8217;ll detail below).</p>

	<div class="csharp code csharp" style="font-family:monospace;"><span style="color: #0600FF;">using</span> <span style="color: #008080;">GeoCore.Win32</span><span style="color: #008000;">;</span><br />
<br />
<span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> Window1 <span style="color: #008000;">:</span> <span style="color: #000000;">System</span>.<span style="color: #0000FF;">Windows</span>.<span style="color: #0000FF;">Window</span> <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #0600FF;">private</span> WPFHotkeyManager hkManager<span style="color: #008000;">;</span><br />
&nbsp; &nbsp;<span style="color: #008080; font-style: italic;">// You need to keep a reference to the hotkey around</span><br />
&nbsp; &nbsp;<span style="color: #008080; font-style: italic;">// Otherwise you won't know *which* hotkey was pressed!</span><br />
&nbsp; &nbsp;<span style="color: #0600FF;">private</span> Hotkey focusHotkey<span style="color: #008000;">;</span> &nbsp;<br />
<br />
&nbsp; &nbsp;<span style="color: #0600FF;">public</span> Window1<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// ... somewhere ... hook SourceInitialized (you can do it in the XAML)</span><br />
&nbsp; &nbsp; &nbsp; SourceInitialized <span style="color: #008000;">+=</span><a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> EventHandler<span style="color: #000000;">&#40;</span>Window1_SourceInitialized<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp;<span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span style="color: #0600FF;">void</span> Window_SourceInitialized<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">object</span> sender, EventArgs e<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// make the whole window glassy, preserving the border</span><br />
&nbsp; &nbsp; &nbsp; NativeMethods.<span style="color: #0000FF;">TryExtendFrameIntoClientArea</span><span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>, BorderThickness<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// create the hotkey manager in &quot;SourceInitialized&quot; because</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// it doesn't accept hotkeys anyway until the window is Initialized</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// -- this is because it needs a window handle.</span><br />
&nbsp; &nbsp; &nbsp; hkManager <span style="color: #008000;">=</span> <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> WPFHotkeyManager<span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// register for the hotkey event, otherwise ... nothing happens.</span><br />
&nbsp; &nbsp; &nbsp; hkManager.<span style="color: #0000FF;">HotkeyPressed</span> <span style="color: #008000;">+=</span> <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> WPFHotkeyManager.<span style="color: #0000FF;">HotkeyPressedEvent</span><span style="color: #000000;">&#40;</span>Hotkey_Pressed<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// create a hotkey -- remember, this is global (and be careful of the types here)</span><br />
&nbsp; &nbsp; &nbsp; focusKey <span style="color: #008000;">=</span> <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> Hotkey<span style="color: #000000;">&#40;</span>ModifierKeys.<span style="color: #0000FF;">Win</span>, Keys.<span style="color: #0000FF;">X</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// register the hotkey</span><br />
&nbsp; &nbsp; &nbsp; hkManager.<span style="color: #0000FF;">Register</span><span style="color: #000000;">&#40;</span>FocusKey<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp;<span style="color: #000000;">&#125;</span><br />
<br />
<br />
&nbsp; &nbsp;<span style="color: #0600FF;">void</span> Hotkey_Pressed<span style="color: #000000;">&#40;</span><span style="color: #000000;">System</span>.<span style="color: #0000FF;">Windows</span>.<span style="color: #0000FF;">Window</span> window, Hotkey hotkey<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #008080; font-style: italic;">// an action for each hotkey ....</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>hotkey.<span style="color: #0000FF;">Equals</span><span style="color: #000000;">&#40;</span>FocusKey<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Show<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span> Activate<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #000000;">&#125;</span><br />
<span style="color: #000000;">&#125;</span></div>

	<p>I want you to notice that I had to create my own Keys enumeration in this, because the <span class="caps">WPF</span> developers unbelievably <em>chose</em> to use an ordering for their Key enumeration which is <em>inconsistent with the Windows API</em> ordering. You <strong>could</strong> use the System.Windows.Forms enumeration, but that would require adding a reference to the Forms assembly in your <span class="caps">WPF</span> application just to get a silly enum!  I have to say that this seems to be  absolutely the <span class="caps">WORST</span> design decision I&#8217;ve seen in the .<span class="caps">NET</span> Framework &#8212; not only are they duplicating enumerations which exist elsewhere, but they couldn&#8217;t even copy-and-paste it in order?</p>

	<h3>Chrome Free Windows!</h3>

	<p>I thought I&#8217;d mention this, just in case you haven&#8217;t seen it before.  Irregular shaped windows are trivially easy to do in <span class="caps">WPF</span>. All you have to do is add the following attributes to your Window tag: WindowStyle=&#8220;None&#8221; AllowsTransparency=&#8220;True&#8221; Background=&#8220;Transparent&#8221;</p>

	<h2>Further Development</h2>

	<h3><span class="caps">DWM</span> <span class="caps">API</span> Thumbnails </h3>

	<p>There are still a few tweaks that need to be made to the Thumbnail Image control.  It doesn&#8217;t adjust when the source window is changed until you resize the window (because it doesn&#8217;t check the size except when <span class="caps">WPF</span> asks it to) and I&#8217;m not sure if it&#8217;s possible apart from re-checking the source window shape on a timer.  I&#8217;m a little afraid that I&#8217;m leaking the thumbnail window so I need to wrap them in a Safe Handle, and override OnUnloaded to clean up.</p>

	<p>I&#8217;m also curious if there&#8217;s a way, in the <span class="caps">DWM</span> api, to get these thumbnails batched into a video or saved to an image handle so you can use them for screenshots &#8230; I&#8217;ll have to take some additional time to research that.</p>

	<h3>Hotkeys</h3>

	<p>There&#8217;s also some changes I want to make to the way my hotkeys class works.  Right now you have to hang on to your Hotkey objects in order to be able to process the hotkey events correctly (unless you only have a single Hotkey) ... and it&#8217;s not possible to use a switch statement on the event, so if you have a lot of hotkeys, it gets a bit ridiculous.  I initially did this because I didn&#8217;t like trusting the user to come up with unique Hotkey Id&#8217;s, but now I&#8217;m thinking that it might be better if you could use just the Ids and create yourself an enumeration for them.  I need to play with this, because one of my key use scenarios is having windowless plugins be able to register and process their own hotkeys &#8212; which makes enums not completely safe, because different pieces of code are dynamically creating hotkeys.</p>

	<p>I also don&#8217;t like not being able to register the hotkeys during construction.  My first attempt to fix that is a version of this HotkeyManager (which I&#8217;ll release shortly) that creates it&#8217;s own window &#8212; this means you don&#8217;t have to worry about calling it in SourceInitialized, but it&#8217;s a pretty expensive fix if you&#8217;ve already got a window.  I&#8217;m going to try doing it another way &#8212; where hotkeys registered before the handle is initialized will be queued for registration later, and this should be a better solution in most cases.  I do have a System.Windows.Forms version  (which I will release with all the other versions) that doesn&#8217;t have this problem (because with Windows.Forms you get a window handle on construction), but again, I don&#8217;t like including that whole assembly for something fairly trivial.</p>

	<p>Hopefully I&#8217;m going to get better at these writeups as time goes on, because I feel like this one is a bit rambling. Questions and comments are welcome!</p>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/vista-thumbnailer/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>ShotGlass Release</title>
		<link>http://huddledmasses.org/shotglass-release/</link>
		<comments>http://huddledmasses.org/shotglass-release/#comments</comments>
		<pubDate>Wed, 07 Sep 2005 04:34:44 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[My Software]]></category>
		<category><![CDATA[Screen Capture]]></category>
		<category><![CDATA[ScreenShot]]></category>
		<category><![CDATA[ShotGlass]]></category>

		<guid isPermaLink="false">http://www.huddledmasses.org/2005/09/06/shotglass-release/</guid>
		<description><![CDATA[Shotglass is an application for taking screenshots and doing stuff with them ... there's a simple API for developing plugins, and a few sample plugins for watermarking and uploading to FTP or Gallery2 ...]]></description>
			<content:encoded><![CDATA[	<p><a href="/shotglass-why/">I wrote ShotGlass, for various reasons</a> &#8230;<br />
<a href="/shotglass-features/">It does lots of things</a> &#8230;<br />
<a href="/shotglass-license/">It&#8217;s licensed for free</a>...</p>

	<p>And there&#8217;s a new version &#8230; make sure you have <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=7ABD8C8F-287E-4C7E-9A4A-A4ECFF40FC8E&#38;displaylang=en">beta 2 of the .<span class="caps">NET</span> Framework Version 2.0</a>  then, <a href="/ShotGlass/ShotGlass.zip">download ShotGlass build 1.1</a> and unzip it wherever you want it.</p>

	<p>The changes from the last version are mostly minor, they relate to the way the form and the thumbnail window behave when you&#8217;re resizing them or moving them.  The big news, however, is that I&#8217;ve included a new plugin for uploading images to Gallery2 using their <span class="caps">HTTP</span> <span class="caps">POST</span> <span class="caps">API</span> (the one that their Gallery Remote uses) .  It won&#8217;t work with the old Gallery 1.x galleries, but it works a treat with RC2 for Gallery 2, which is what the GeoShell site uses for our screenshots gallery &#8230; which was half the reason I wrote this whole application anyway.  I also added a <span class="caps">JPEG</span> output plugin, so you don&#8217;t have to upload those huge uncompressed PNG&#8217;s to your webserver&#8217;s gallery&#8230;</p>

	<p>I&#8217;ll publish the simple <span class="caps">API</span> tommorrow, but for now, <a href="/ShotGlass/ShotGlassSource.7z">the source is here</a> under the <a href="/shotglass-license/"><span class="caps">MIT</span> License</a>... if you make improvements, please be kind enough to send them back to me  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=':D' class='wp-smiley' /> </p>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/shotglass-release/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ShotGlass &#8211; License</title>
		<link>http://huddledmasses.org/shotglass-license/</link>
		<comments>http://huddledmasses.org/shotglass-license/#comments</comments>
		<pubDate>Tue, 30 Aug 2005 04:21:15 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[licensing]]></category>
		<category><![CDATA[My Software]]></category>
		<category><![CDATA[Screen Capture]]></category>
		<category><![CDATA[ScreenShot]]></category>
		<category><![CDATA[ShotGlass]]></category>

		<guid isPermaLink="false">http://www.huddledmasses.org/2005/09/06/shotglass-license/</guid>
		<description><![CDATA[Shotglass is an application for taking screenshots and doing stuff with them ... there's a simple API for developing plugins, and a few sample plugins for watermarking and uploading to FTP or Gallery2 ...]]></description>
			<content:encoded><![CDATA[	<p>I wrote  <a href="/shotglass-why/">my own screenshot app</a> called ShotGlass, <a href="/shotglass-features/">which does all sorts of things</a>  and is released for free under the <a href="http://opensource.org/licenses/mit-license.php"><span class="caps">MIT</span> License</a>, which basically means that ShotGlass is free for you to do pretty much whatever you like, as long as you don&#8217;t expect me to guarantee it or provide service, or in any way be responsible for what might go wrong.</p>

	<p>The official license is as follows:</p>

	<blockquote>
		<p>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the &#8220;Software&#8221;), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</p>
	</blockquote>

	<blockquote>
		<p>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</p>
	</blockquote>

	<blockquote>
		<p><span class="caps">THE</span> <span class="caps">SOFTWARE</span> IS <span class="caps">PROVIDED</span> &#8220;AS IS&#8221;, <span class="caps">WITHOUT</span> <span class="caps">WARRANTY</span> OF <span class="caps">ANY</span> <span class="caps">KIND</span>, <span class="caps">EXPRESS</span> OR <span class="caps">IMPLIED</span>, <span class="caps">INCLUDING</span> <span class="caps">BUT</span> <span class="caps">NOT</span> <span class="caps">LIMITED</span> TO <span class="caps">THE</span> <span class="caps">WARRANTIES</span> OF <span class="caps">MERCHANTABILITY</span>, <span class="caps">FITNESS</span> <span class="caps">FOR</span> A <span class="caps">PARTICULAR</span> <span class="caps">PURPOSE</span> <span class="caps">AND</span> <span class="caps">NONINFRINGEMENT</span>. IN NO <span class="caps">EVENT</span> <span class="caps">SHALL</span> <span class="caps">THE</span> <span class="caps">AUTHORS</span> OR <span class="caps">COPYRIGHT</span> <span class="caps">HOLDERS</span> BE <span class="caps">LIABLE</span> <span class="caps">FOR</span> <span class="caps">ANY</span> <span class="caps">CLAIM</span>, <span class="caps">DAMAGES</span> OR <span class="caps">OTHER</span> <span class="caps">LIABILITY</span>, <span class="caps">WHETHER</span> IN AN <span class="caps">ACTION</span> OF <span class="caps">CONTRACT</span>, <span class="caps">TORT</span> OR <span class="caps">OTHERWISE</span>, <span class="caps">ARISING</span> <span class="caps">FROM</span>, <span class="caps">OUT</span> OF OR IN <span class="caps">CONNECTION</span> <span class="caps">WITH</span> <span class="caps">THE</span> <span class="caps">SOFTWARE</span> OR <span class="caps">THE</span> <span class="caps">USE</span> OR <span class="caps">OTHER</span> <span class="caps">DEALINGS</span> IN <span class="caps">THE</span> <span class="caps">SOFTWARE</span>.</p>
	</blockquote>

	<p><a href="/shotglass-release/">Here&#8217;s the download</a> &#8230;</p>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/shotglass-license/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ShotGlass &#8211; Features</title>
		<link>http://huddledmasses.org/shotglass-features/</link>
		<comments>http://huddledmasses.org/shotglass-features/#comments</comments>
		<pubDate>Mon, 22 Aug 2005 03:31:23 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[My Software]]></category>
		<category><![CDATA[Screen Capture]]></category>
		<category><![CDATA[ScreenShot]]></category>
		<category><![CDATA[ShotGlass]]></category>

		<guid isPermaLink="false">http://www.huddledmasses.org/?p=223</guid>
		<description><![CDATA[Shotglass is an application for taking screenshots and doing stuff with them ... there's a simple API for developing plugins, and a few sample plugins for watermarking and uploading to FTP or Gallery2 ...]]></description>
			<content:encoded><![CDATA[	<p>I wrote about <a href="/shotglass-why/">why I wrote my own screenshot app</a> called ShotGlass, here&#8217;s what it does:</p>

	<p>ShotGlass takes screenshots!
	<ul>
		<li>Crops screenshots!
	<ul>
		<li>Optionally, it crops the screenshot to the ShotGlass Window.
		<li>Optionally creates thumbnails
	<ul>
		<li>When taking a &#8220;cropped&#8221; shot of just the area covered by the ShotGlass window, the thumnail is created from a positionable sub-window.</li>
	</ul></li>
	</ul></li>
	<ul>
		<li>When taking an uncropped screenshot of the full screen, uses the main window as the thumbnail cropper.</li>
	</ul></li>
	</ul>
	<ul>
		<li>Can automatically resize the screenshot crop area to match the size and shape of the window you want to take a screenshot of.  Just put the top left corner of the ShotGlass window over the window&#8217;s title bar.</li>
	</ul></p>

	<p><img src="/ShotGlass/ShotGlass.png" class="alignright" alt="" /></p>

	<p>It also uses plugins to enhance functionality:
	<ol>
		<li>Image processing &#8220;Mixer&#8221; plugins.  I&#8217;ve provided a watermark plugin which does images and text, and a highlight plugin which uses the thumbnail area to highlight a portion of the screen in the shot. But anything you can imagine in image processing can be done with an extremely simple interface.</li>
		<li>Image output &#8220;Glass&#8221; plugins which control the file output.  The default one is to output to the clipboard, but I&#8217;ve already included ones for Png and Bmp output, and I&#8217;ll put one in later for Jpg with compression.</li>
	</ol>
	<ol>
		<li>File handling &#8220;Drinker&#8221; plugins which can upload the file, or basically do whatever you want to do with the screenshot files once they&#8217;re saved.  I&#8217;ve already included one for <span class="caps">FTP</span> uploading, and I&#8217;m working on Gallery uploads for my original geoShell purposes.</li>
	</ol></p>

	<p>And finally, it has command-line features:
	<ul>
		<li><em>Named</em> configs, so you can specify a config (which is saved on-exit) using <code>/config:configname</code> This allows you to set up different types of shots which you can take later, because &#8230;</li>
		<li>Take a cropped screenshot &#8220;instantly&#8221; (without ever showing the UI) if you pass the parameter: <code>/instant</code></li>
	</ul>
	<ul>
		<li>Take a full screen shot instantly using: <code>/fullscreen</code></li>
	</ul></p>

	<p>I&#8217;ll put up more information here later, including screenshots of the very nice configuration panel and the right-click menu (which includes documentation of the hotkeys), but for now I want to get on with getting this beta release out so I can get some feedback.</p>

	<p><a href="/shotglass-license/">Here&#8217;s it&#8217;s release license</a>...<br />
<a href="/shotglass-release/">Here&#8217;s the download</a> &#8230;</p>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/shotglass-features/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ShotGlass &#8211; Why?</title>
		<link>http://huddledmasses.org/shotglass-why/</link>
		<comments>http://huddledmasses.org/shotglass-why/#comments</comments>
		<pubDate>Sun, 21 Aug 2005 19:13:06 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[My Software]]></category>
		<category><![CDATA[Screen Capture]]></category>
		<category><![CDATA[ScreenShot]]></category>
		<category><![CDATA[ShotGlass]]></category>

		<guid isPermaLink="false">http://www.huddledmasses.org/?p=214</guid>
		<description><![CDATA[I've been using Cropper, but it just doesn't quite cut it, and the plugin architecture is a little too much for me.]]></description>
			<content:encoded><![CDATA[	<p>I&#8217;ve been using <a href="http://blogs.geekdojo.net/brian/articles/Cropper.aspx">Cropper</a> for a while to take simple cropped screenshots, but when I want to take a screenshot of my whole screen, I keep having to go back to my old screenshot script which uses <a href="http://www.imagemagick.org/">ImageMagick</a> and commandline ftp, because I need to upload the screenshot.  Recently I realized I want to upload the images to Menalto <a href="http://www.geoshell.org/component/option,com_gallery2/Itemid,21/">gallery on the geoShell site</a> and I wanted to share that ability with other people, but my script requires ImageMagick and Perl to be installed and properly configured, which seems a bit to ask of your average Windows user  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=';)' class='wp-smiley' /> </p>

	<p>I started out to write a plugin for Cropper but ended up deciding there were just too many things I didn&#8217;t like: 
	<ul>
		<li>The plugins are rather more complicated to write than they need to be, partly because they have to handle <span class="caps">ALL</span> the output&#8230;</li>
		<li>The thumbnail window is locked at the center of the screenshot window</li>
		<li>There&#8217;s not really any way to take a shot of the full screen</li>
	</ul>
	<ul>
		<li>There&#8217;s no command-line ability (you have to bring up the cropper window to take a screenshot)</li>
	</ul></p>

	<p>The end result is that I&#8217;ve written myself a screenshot application.  Now, I wrote it mostly for myself, at first, so I wrote it in C#, using Beta 2 of Visual Studio.  Eventually I decided to &#8220;fix&#8221; the shortcomings I saw in other implemenations, but I don&#8217;t really want to back-port it to .<span class="caps">NET</span> 1.1, so in order to use it, you need to have <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=7ABD8C8F-287E-4C7E-9A4A-A4ECFF40FC8E&#38;displaylang=en">beta 2 of the .<span class="caps">NET</span> Framework Version 2.0</a> installed.</p>

	<p><a href="/shotglass-license/">Here&#8217;s it&#8217;s release license</a>...<br />
<a href="/shotglass-features/">Here&#8217;s what it does</a> &#8230;<br />
<a href="/shotglass-release/">Here&#8217;s the download</a> &#8230;</p>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/shotglass-why/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

