<?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; Scripting</title>
	<atom:link href="http://huddledmasses.org/tag/scripting/feed/" rel="self" type="application/rss+xml" />
	<link>http://huddledmasses.org</link>
	<description>You can do more than breathe for free...</description>
	<lastBuildDate>Fri, 27 Apr 2012 05:42:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
<cloud domain='huddledmasses.org' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
		<item>
		<title>Arrange &#8211; Act &#8211; Assert: Intuitive Testing</title>
		<link>http://huddledmasses.org/arrange-act-assert-intuitive-testing/</link>
		<comments>http://huddledmasses.org/arrange-act-assert-intuitive-testing/#comments</comments>
		<pubDate>Wed, 05 Oct 2011 03:31:56 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[3As]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http://huddledmasses.org/?p=1757</guid>
		<description><![CDATA[Today I have a new module to introduce you to. It&#8217;s a relatively simple module for testing, and you can pick it up in short order and start testing your scripts, modules, and even compiled .Net code. If you put it together with WASP you can pretty much test anything The basis for the module [...]]]></description>
			<content:encoded><![CDATA[	<p>Today I have a new module to introduce you to. It&#8217;s a relatively simple module for testing, and you can pick it up in short order and start testing your scripts, modules, and even compiled .Net code. If you put it together with <a href="http://poshcode.org/2483" title="my UI Automation module">WASP</a> you can pretty much test anything  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=';-)' class='wp-smiley' /> </p>

	<p>The basis for the module is the arrange-act-assert model of testing. First we <strong>arrange</strong> the things we&#8217;re going to test: set up data structures or whatever you need for testing. Then we <strong>act</strong> on them: we perform the actual test steps. Finally, we <strong>assert</strong> the expected output of the test. Normally, the expectation is that during the assert step we&#8217;ll return <code>$false</code> if the test failed, and that&#8217;s all there is to it. Of course, there&#8217;s plenty more to testing, but lets move on to my new module.</p>

	<p>The module is called <a href="/downloads/PSaint.7z">PSaint</a> (pronounced &#8220;saint&#8221;), and it stands, loosely, for PowerShell Arrange-Act-Assert in testing. Of course, what it stands for isn&#8217;t important, just remember the name is PSaint  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=':)' class='wp-smiley' /> </p>

	<p>PSaint is really a very simple module, with only a few functions. There are two major functions which we&#8217;ll discuss in detail: Test-Code and New-RhinoMock, and then a few helpers which you may or may not even use:</p>

	<h3>Set-TestFilter </h3>

	<p>Sets filters (include and/or exclude) for the tests by name or category.</p>

	<h3>Set-TestSetup (alias &#8220;Setup&#8221;)</h3>

	<p>Sets the test setup ScriptBlock which will be run before each test.</p>

	<h3>Set-TestTeardown (alias &#8220;Teardown&#8221;)</h3>

	<p>Sets the test teardown ScriptBlock which will be run after each test.</p>

	<h3>Assert-That</h3>

	<p>Assserts something about an object (or the output of a scriptblock) and throws if that assertion is false.  This function supports asserting that an exception should be thrown, or that a test is false &#8230; and supports customizing the error message as well.</p>

	<h3>Assert-PropertyEqual</h3>

	<p>This is a wrapper around Compare-Object to compare the properties of two objects.</p>

	<h2>How to test with PSaint: Test-Code</h2>

	<p>Test-Code (alias &#8220;Test&#8221;) is the main driver of functionality in PSaint, and you use it to define the tests that you want to run.  Let&#8217;s jump to an example or two so you can see the usefulness of this module.</p>

	<p>Let&#8217;s start with an extremely simple function that we want to write: New-Guid.  We want a function that generates a valid random <span class="caps">GUID</span> as a string. We&#8217;ll start by writing a couple of tests. First we&#8217;ll test that the output of the function is a valid <span class="caps">GUID</span>.</p>

	<div class="posh code posh" style="font-family:monospace;">test <span style="color: #009900;">&quot;New-Guid outputs a Guid&quot;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;act <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$guid</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Guid</span></span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;assert <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$guid</span> <span style="color: #000066;">-is</span> <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">string</span><span style="color: #333;">&#93;</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Object</span></span> Guid <span style="color: #660033; font-weight: bold;">$guid</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span><br />
&nbsp;</div>

	<p>Now, to verify that the test works, you should define this function (the GUID-looking thing is one letter short) and then run that test:</p>

	<div class="posh code posh" style="font-family:monospace;"><span style="color: #666699; font-weight: bold;">function</span> <span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Guid</span></span> <span style="color: #333;">&#123;</span> <span style="color: #009900;">&quot;aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa&quot;</span> <span style="color: #333;">&#125;</span><br />
&nbsp;</div>

	<p>Another proof that it works would be that it should fail on this function too, because &#8220;x&#8221; is not a valid character in a Guid:</p>

	<div class="posh code posh" style="font-family:monospace;"><span style="color: #666699; font-weight: bold;">function</span> <span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Guid</span></span> <span style="color: #333;">&#123;</span> <span style="color: #009900;">&quot;xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx&quot;</span> <span style="color: #333;">&#125;</span><br />
&nbsp;</div>

	<p>So, let&#8217;s write a minimal New-Guid that actually generates a valid Guid:</p>

	<div class="posh code posh" style="font-family:monospace;"><span style="color: #666699; font-weight: bold;">function</span> <span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Guid</span></span> <span style="color: #333;">&#123;</span> <span style="color: #009900;">&quot;aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa&quot;</span> <span style="color: #333;">&#125;</span><br />
&nbsp;</div>

	<p>If you run our test on that, you will see:</p>

	<div class="text code text" style="font-family:monospace;">&nbsp; &nbsp;Result: Pass<br />
<br />
Result Name &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Category<br />
------ ---- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;--------<br />
Pass &nbsp; New-Guid outputs a Guid<br />
&nbsp;</div>

	<p>If you don&#8217;t like the fact that the Category is empty, you could add a category or two to the end of our test.  We should also switch to using Assert-That if we want to know which test in the assert failed. Finally, we want to write another test which would test that New-Guid doesn&#8217;t just return the same Guid every time, the way ours does right now:</p>

	<div class="posh code posh" style="font-family:monospace;">test <span style="color: #009900;">&quot;New-Guid outputs a Guid&quot;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;act <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$guid</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Guid</span></span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;assert <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">Assert-<span style="font-style: normal;">That</span></span> <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$guid</span> <span style="color: #000066;">-is</span> <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">string</span><span style="color: #333;">&#93;</span></span> <span style="color: #333;">&#125;</span> <span style="color: #000066;">-FailMessage</span> <span style="color: #009900;">&quot;New-Guid returned a $($guid.GetType().FullName)&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Object</span></span> Guid <span style="color: #660033; font-weight: bold;">$guid</span> &nbsp;<span style="color: #666666; font-style: italic;"># Throws relevant errors already</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span> <span style="color: #000066;">-Category</span> Output, ValidGuid<br />
<br />
test <span style="color: #009900;">&quot;New-Guid outputs different Guids&quot;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;arrange <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$guids</span> <span style="color: #66cc66;">=</span> @<span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$count</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">100</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;act <span style="color: #333;">&#123;</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># generate a bunch of Guids</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">for</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$i</span><span style="color: #66cc66;">=</span><span style="color: #cc66cc;">0</span>; <span style="color: #660033; font-weight: bold;">$i</span> <span style="color: #000066;">-lt</span> <span style="color: #660033; font-weight: bold;">$count</span>; <span style="color: #660033; font-weight: bold;">$i</span><span style="color: #66cc66;">++</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$guids</span> <span style="color: #66cc66;">+=</span> <span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Guid</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;assert <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># compare each guid to all the ones after it</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">for</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$i</span><span style="color: #66cc66;">=</span><span style="color: #cc66cc;">0</span>; <span style="color: #660033; font-weight: bold;">$i</span> <span style="color: #000066;">-lt</span> <span style="color: #660033; font-weight: bold;">$count</span>; <span style="color: #660033; font-weight: bold;">$i</span><span style="color: #66cc66;">++</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">for</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$j</span><span style="color: #66cc66;">=</span><span style="color: #660033; font-weight: bold;">$i</span><span style="color: #66cc66;">+</span><span style="color: #cc66cc;">1</span>; <span style="color: #660033; font-weight: bold;">$j</span> <span style="color: #000066;">-lt</span> <span style="color: #660033; font-weight: bold;">$count</span>; <span style="color: #660033; font-weight: bold;">$j</span><span style="color: #66cc66;">++</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">Assert-<span style="font-style: normal;">That</span></span> <span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$guids</span><span style="color: #333;">&#91;</span><span style="color: #660033; font-weight: bold;">$i</span><span style="color: #333;">&#93;</span> <span style="color: #000066;">-ne</span> <span style="color: #660033; font-weight: bold;">$guids</span><span style="color: #333;">&#91;</span><span style="color: #660033; font-weight: bold;">$j</span><span style="color: #333;">&#93;</span><span style="color: #333;">&#41;</span> <span style="color: #000066;">-FailMessage</span> <span style="color: #009900;">&quot;There were equal Guids: $($guids[$i])&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span> <span style="color: #000066;">-Category</span> Output, RandomGuids<br />
&nbsp;</div>

	<p>Now, we have to actually fix our New-Guid function to generate real random Guids:</p>

	<div class="posh code posh" style="font-family:monospace;"><span style="color: #666699; font-weight: bold;">function</span> <span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Guid</span></span> <span style="color: #333;">&#123;</span> <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>System.<span style="color: #003366;">Guid</span><span style="color: #333;">&#93;</span></span>::<span style="color: #003366;">NewGuid</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span>.<span style="color: #003366;">ToString</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#125;</span><br />
&nbsp;</div>

	<p>And at that point, we should have a function, and a couple of tests that verify it&#8217;s functionality&#8230;</p>

	<h3>The finer points of assertions</h3>

	<p>One thing you&#8217;ll notice the first time you use Get-Member after loading the PSaint module is a few script properties have been added to everything.  I did this because I found myself writing the same Assert-That calls over and over and decided that it would be slicker to make these extension methods than to write new functions for each one:</p>

	<div class="posh code posh" style="font-family:monospace;">MustBeA<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;">Type</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$Expected</span>,<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">string</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$Message</span><span style="color: #333;">&#41;</span><br />
MustBeFalse<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;">string</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$Message</span><span style="color: #333;">&#41;</span><br />
MustBeTrue<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;">string</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$Message</span><span style="color: #333;">&#41;</span><br />
MustEqual<span style="color: #333;">&#40;</span><span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>Object<span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$Expected</span>,<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">string</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$Message</span><span style="color: #333;">&#41;</span><br />
MustNotEqual<span style="color: #333;">&#40;</span><span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>Object<span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$Expected</span>,<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">string</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$Message</span><span style="color: #333;">&#41;</span><br />
&nbsp;</div>

	<p>There&#8217;s also a <span style="font-family:monospace;">MustThrow<span style="color: #333;">(</span><span style="color: #003366; font-weight: bold;"><span style="color: #333;">[</span><span style="color: #003366; font-weight: bold;">Type</span><span style="color: #333;">]</span></span><span style="color: #660033; font-weight: bold;">$Expected</span>, <span style="color: #003366; font-weight: bold;"><span style="color: #333;">[</span><span style="color: #003366; font-weight: bold;">string</span><span style="color: #333;">]</span></span><span style="color: #660033; font-weight: bold;">$Message</span><span style="color: #333;">)</span></span> which can be used on script blocks (note that this function executes the ScriptBlock immediately, so be careful how you use it).</p>

	<p>We can use these to tidy up our tests quite a bit, while still getting good error messages when tests fail:</p>

	<div class="posh code posh" style="font-family:monospace;">test <span style="color: #009900;">&quot;New-Guid outputs a Guid String&quot;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;act <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$guid</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Guid</span></span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;assert <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$guid</span>.<span style="color: #003366;">MustBeA</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;">string</span><span style="color: #333;">&#93;</span></span> <span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Object</span></span> Guid <span style="color: #660033; font-weight: bold;">$guid</span> <span style="color: #666666; font-style: italic;"># Throws relevant errors already</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span> <span style="color: #000066;">-Category</span> Output, ValidGuid<br />
<br />
test <span style="color: #009900;">&quot;New-Guid outputs different Guids&quot;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;arrange <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$guids</span> <span style="color: #66cc66;">=</span> @<span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$count</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">100</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;act <span style="color: #333;">&#123;</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># generate a bunch of Guids</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">for</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$i</span><span style="color: #66cc66;">=</span><span style="color: #cc66cc;">0</span>; <span style="color: #660033; font-weight: bold;">$i</span> <span style="color: #000066;">-lt</span> <span style="color: #660033; font-weight: bold;">$count</span>; <span style="color: #660033; font-weight: bold;">$i</span><span style="color: #66cc66;">++</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$guids</span> <span style="color: #66cc66;">+=</span> <span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Guid</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;assert <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># compare each guid to all the ones after it</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">for</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$i</span><span style="color: #66cc66;">=</span><span style="color: #cc66cc;">0</span>; <span style="color: #660033; font-weight: bold;">$i</span> <span style="color: #000066;">-lt</span> <span style="color: #660033; font-weight: bold;">$count</span>; <span style="color: #660033; font-weight: bold;">$i</span><span style="color: #66cc66;">++</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">for</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$j</span><span style="color: #66cc66;">=</span><span style="color: #660033; font-weight: bold;">$i</span><span style="color: #66cc66;">+</span><span style="color: #cc66cc;">1</span>; <span style="color: #660033; font-weight: bold;">$j</span> <span style="color: #000066;">-lt</span> <span style="color: #660033; font-weight: bold;">$count</span>; <span style="color: #660033; font-weight: bold;">$j</span><span style="color: #66cc66;">++</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$guids</span><span style="color: #333;">&#91;</span><span style="color: #660033; font-weight: bold;">$i</span><span style="color: #333;">&#93;</span>.<span style="color: #003366;">MustNotEqual</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$guids</span><span style="color: #333;">&#91;</span><span style="color: #660033; font-weight: bold;">$j</span><span style="color: #333;">&#93;</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span> <span style="color: #000066;">-Category</span> Output, RandomGuids<br />
&nbsp;</div>

	<h3><span class="caps">COM</span> Objects </h3>

	<p>PSaint also has a wrapper for <span class="caps">COM</span> objects to help with testing them. It adds GetProperty and SetProperty methods to allow you to access <span class="caps">COM</span> object properties which don&#8217;t show up on boxed <span class="caps">COM</span> objects (a common problem when working with MSOffice, for instance).  It also adds InvokeMethod for <span class="caps">COM</span> objects to invoke methods that don&#8217;t show up for similar reasons.  These, of course, only help you if you&#8217;re already fairly literate with the <span class="caps">COM</span> object in question.</p>

	<h3>Mock Objects</h3>

	<p>PSaint includes New-RhinoMock, a function for generating a new mock object using <a href="http://hibernatingrhinos.com/open-source/rhino-mocks">RhinoMocks</a> (which is included).  Rhino Mocks is a BSD-licensed dynamic mock object framework for the .Net platform. Its purpose is to ease testing by allowing the developer to create mock implementations of custom objects and verify the interactions using unit testing.</p>

	<p>I have to admit that this New-RhinoMock function is incomplete, and exposes only a fraction of the options and power in RhinoMocks, but it&#8217;s been sufficient for the few times when I&#8217;ve wanted to actually mock objects from PowerShell, so I&#8217;m including it here.</p>

	<p>For those of you (developers) who want to know why RhinoMocks instead of your favorite mocking framework, the answer is astonishingly simple: it had the least number of necessary generic methods (which are impossible to call in PowerShell 2).</p>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/arrange-act-assert-intuitive-testing/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Logging Robocopy errors to the Event Log using PowerShell</title>
		<link>http://huddledmasses.org/logging-robocopy-errors-to-the-event-log-using-powershell/</link>
		<comments>http://huddledmasses.org/logging-robocopy-errors-to-the-event-log-using-powershell/#comments</comments>
		<pubDate>Mon, 05 Apr 2010 04:59:22 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[EventLog]]></category>
		<category><![CDATA[Logging]]></category>
		<category><![CDATA[Module]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[RoboCopy]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://huddledmasses.org/?p=1435</guid>
		<description><![CDATA[Someone came into IRC last week asking for help converting a rather large vbscript into PowerShell, and got me interested in turning Robocopy logs into Windows Events&#8230; The original VBScript is about 68 lines of code, and writes one event per log file. We duplicated it&#8217;s functionality with the following 11 lines of code: Param&#40;$LogPath, [...]]]></description>
			<content:encoded><![CDATA[	<p>Someone came into <span class="caps">IRC</span> last week asking for help converting a <a href="http://www.askthemct.com/2009/07/16/circularish-logging-the-event-viewer-and-robocopy/">rather large vbscript</a> into PowerShell, and got me interested in turning Robocopy logs into Windows Events&#8230;</p>

	<p>The original VBScript is about 68 lines of code, and writes one event per log file.  We duplicated it&#8217;s functionality with the following 11 lines of code:<br />
<div class="posh code posh" style="font-family:monospace;"><span style="color: #666699; font-weight: bold;">Param</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$LogPath</span>, <span style="color: #660033; font-weight: bold;">$LogName</span>, <span style="color: #660033; font-weight: bold;">$ArchiveDays</span><span style="color: #333;">&#41;</span><br />
<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">string</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$Log</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">Join-<span style="font-style: normal;">Path</span></span> <span style="color: #660033; font-weight: bold;">$LogPath</span> <span style="color: #660033; font-weight: bold;">$LogName</span><br />
<span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span><span style="color: #0066cc; font-style: italic;">Select-<span style="font-style: normal;">String</span></span> <span style="color: #000066;">-Path</span> <span style="color: #660033; font-weight: bold;">$Log</span> <span style="color: #000066;">-pattern</span> <span style="color: #009900;">&quot;0x0000&quot;</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$logError</span> <span style="color: #66cc66;">=</span> <span style="color: #009900;">&quot;$Log.ERROR.$(get-date -format 'yyyy-MM-dd-hhmmss')&quot;</span><br />
&nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">write-<span style="font-style: normal;">eventlog</span></span> Application <span style="color: #000066;">-Source</span> Robocopy <span style="color: #000066;">-EventId</span> <span style="color: #cc66cc;">12</span> <span style="color: #000066;">-EntryType</span> Error <span style="color: #000066;">-Message</span> <span style="color: #009900;">&quot;Robocopy Job Failed -please check log file $LogError&quot;</span><br />
&nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">move-<span style="font-style: normal;">item</span></span> <span style="color: #660033; font-weight: bold;">$log</span> <span style="color: #660033; font-weight: bold;">$logError</span><br />
<span style="color: #333;">&#125;</span> <span style="color: #666699; font-weight: bold;">else</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #666666; font-style: italic;"># If you do not want to send Success Events to the Application Log, comment out the following line</span><br />
&nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">write-<span style="font-style: normal;">eventlog</span></span> Application <span style="color: #000066;">-Source</span> Robocopy <span style="color: #000066;">-EventId</span> <span style="color: #cc66cc;">1</span> <span style="color: #000066;">-EntryType</span> Information <span style="color: #000066;">-Message</span> <span style="color: #009900;">&quot;Robocopy Job Failed -please check log file $LogError&quot;</span><br />
&nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">move-<span style="font-style: normal;">item</span></span> <span style="color: #660033; font-weight: bold;">$Log</span> <span style="color: #009900;">&quot;$Log.ARCHIVE.$(Get-Date -f 'yyyy-MM-dd-hhmmss')&quot;</span><br />
<span style="color: #333;">&#125;</span><br />
<span style="color: #666666; font-style: italic;">## Remove archive logs older than $archiveDate</span><br />
<span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">ChildItem</span></span> <span style="color: #009900;">&quot;$Log.ARCHIVE.*&quot;</span> <span style="color: #66cc66;">|</span> <span style="color: #660033;">Where</span> <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$_</span>.<span style="color: #003366;">CreationTime</span> <span style="color: #000066;">-lt</span> <span style="color: #333;">&#40;</span><span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Date</span></span><span style="color: #333;">&#41;</span>.<span style="color: #003366;">AddDays</span><span style="color: #333;">&#40;</span><span style="color: #66cc66;">-</span><span style="color: #660033; font-weight: bold;">$archiveDays</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#125;</span> <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Remove-<span style="font-style: normal;">Item</span></span></div>

	<p>Actually, even that first attempt extended the functionality a little, because we potentially make multiple archive copies which we only delete once they pass the archive date. </p>

	<h3>New-EventLog Application Robocopy</h3>

	<p>There are two catches.  First, you need PowerShell 2.0.  Second, before you can run that script <em>the first time</em>, you have to create the &#8220;Robocopy&#8221; event source for the machine by running this command in an elevated PowerShell console (that is, you have to run it &#8220;as Administrator&#8221;):</p>

	<div class="posh code posh" style="font-family:monospace;"><span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">EventLog</span></span> Application Robocopy</div>

	<p>Of course, being a good geek, I couldn&#8217;t leave well enough alone, so we changed the script so that it would log each unique error to the event log (including the line following the error, which has more details), so that there&#8217;s no need to go &#8220;check the log file&#8221; on the machine, since you can retrieve the event logs remotely.  The finished script looks like this:</p>

	<div class="posh code posh" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#requires -Version 2.0</span><br />
<span style="color: #666666; font-style: italic;">## BEFORE you use this the FIRST time (only once per machine)</span><br />
<span style="color: #666666; font-style: italic;">## you must run the following command elevated (as Administrator):</span><br />
<span style="color: #666666; font-style: italic;">## New-EventLog Application Robocopy</span><br />
<br />
<span style="color: #666699; font-weight: bold;">Param</span><span style="color: #333;">&#40;</span> &nbsp;<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">string</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$LogPath</span> &nbsp;<span style="color: #66cc66;">=</span> <span style="color: #009900;">&quot;C:\Logs\&quot;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">string</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$LogName</span> &nbsp;<span style="color: #66cc66;">=</span> <span style="color: #009900;">&quot;Robocopy-log-file.log&quot;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">int</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$ArchiveDays</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">30</span><br />
<span style="color: #333;">&#41;</span><br />
<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">string</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$Log</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">Join-<span style="font-style: normal;">Path</span></span> <span style="color: #660033; font-weight: bold;">$LogPath</span> <span style="color: #660033; font-weight: bold;">$LogName</span><br />
<br />
<span style="color: #660033; font-weight: bold;">$Archive</span> <span style="color: #66cc66;">=</span> <span style="color: #009900;">&quot;ARCHIVE&quot;</span><br />
<span style="color: #666699; font-weight: bold;">foreach</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$errorEvent</span> <span style="color: #666699; font-weight: bold;">in</span> <span style="color: #0066cc; font-style: italic;">Select-<span style="font-style: normal;">String</span></span> <span style="color: #000066;">-Path</span> <span style="color: #660033; font-weight: bold;">$Log</span> <span style="color: #000066;">-Pattern</span> <span style="color: #009900;">'ERROR .*0x0000.*$'</span> <span style="color: #000066;">-context</span> <span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">|</span> <span style="color: #660033;">sort</span> <span style="color: #333;">&#123;</span><span style="color: #660033; font-weight: bold;">$_</span>.<span style="color: #003366;">matches</span><span style="color: #333;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #333;">&#93;</span>.<span style="color: #003366;">value</span><span style="color: #333;">&#125;</span> <span style="color: #000066;">-Unique</span> <span style="color: #333;">&#41;</span> <br />
<span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$Archive</span> <span style="color: #66cc66;">=</span> <span style="color: #009900;">&quot;ERROR&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">write-<span style="font-style: normal;">eventlog</span></span> Application <span style="color: #000066;">-Source</span> Robocopy <span style="color: #000066;">-EventId</span> <span style="color: #cc66cc;">12</span> <span style="color: #000066;">-EntryType</span> Error <span style="color: #000066;">-Message</span> $<span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$errorEvent</span>.<span style="color: #003366;">Line</span> <span style="color: #66cc66;">+</span> <span style="color: #009900;">&quot;<span style="color: #000099; font-weight: bold;">`n</span>&quot;</span> <span style="color: #66cc66;">+</span> <span style="color: #660033; font-weight: bold;">$errorEvent</span>.<span style="color: #003366;">Context</span>.<span style="color: #003366;">PostContext</span><span style="color: #333;">&#41;</span><br />
<span style="color: #333;">&#125;</span><br />
<br />
<span style="color: #666699; font-weight: bold;">switch</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$Archive</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&quot;ERROR&quot;</span> <span style="color: #333;">&#123;</span> <span style="color: #666666; font-style: italic;">## Archive the log file as an ERROR (we never delete these automatically)</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033;">move</span> <span style="color: #660033; font-weight: bold;">$Log</span> <span style="color: #009900;">&quot;$Log.ERROR.$(get-date -format 'yyyy-MM-dd-hhmmss')&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&quot;ARCHIVE&quot;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">write-<span style="font-style: normal;">eventlog</span></span> Application <span style="color: #000066;">-Source</span> Robocopy <span style="color: #000066;">-EventId</span> <span style="color: #cc66cc;">1</span> <span style="color: #000066;">-EntryType</span> Information &nbsp;<span style="color: #000066;">-Message</span> <span style="color: #009900;">&quot;Robocopy successful&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">## Archive the log file</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">move-<span style="font-style: normal;">item</span></span> <span style="color: #660033; font-weight: bold;">$Log</span> <span style="color: #009900;">&quot;$Log.ARCHIVE.$(Get-Date -f 'yyyy-MM-dd-hhmmss')&quot;</span> <span style="color: #000066;">-Force</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span><br />
<br />
<span style="color: #666666; font-style: italic;">## Remove archive logs older than $archiveDate</span><br />
<span style="color: #660033; font-weight: bold;">$archiveDate</span> <span style="color: #66cc66;">=</span> <span style="color: #333;">&#40;</span><span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Date</span></span><span style="color: #333;">&#41;</span>.<span style="color: #003366;">AddDays</span><span style="color: #333;">&#40;</span><span style="color: #66cc66;">-</span><span style="color: #660033; font-weight: bold;">$archiveDays</span><span style="color: #333;">&#41;</span><br />
<span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">ChildItem</span></span> <span style="color: #009900;">&quot;$Log.ARCHIVE.*&quot;</span> <span style="color: #66cc66;">|</span> <span style="color: #660033;">Where</span> <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$_</span>.<span style="color: #003366;">CreationTime</span> <span style="color: #000066;">-lt</span> <span style="color: #660033; font-weight: bold;">$archiveDate</span> <span style="color: #333;">&#125;</span> <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Remove-<span style="font-style: normal;">Item</span></span></div>

	<p>Notice that we cleaned up the parameters a little bit, and put some defaults in, but we still haven&#8217;t written &#8220;help&#8221; ... that&#8217;s partly because I still am not sure that&#8217;s the best option for logging  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=':)' class='wp-smiley' />   Another way would be to just write one log event, but with details about the errors like:</p>

	<div class="posh code posh" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#requires -Version 2.0</span><br />
<span style="color: #666666; font-style: italic;">## BEFORE you use this the FIRST time (only once per machine)</span><br />
<span style="color: #666666; font-style: italic;">## you must run the following command elevated (as Administrator):</span><br />
<span style="color: #666666; font-style: italic;">## New-EventLog Application Robocopy</span><br />
<br />
<span style="color: #666699; font-weight: bold;">Param</span><span style="color: #333;">&#40;</span> &nbsp;<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">string</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$LogPath</span> &nbsp;<span style="color: #66cc66;">=</span> <span style="color: #009900;">&quot;C:\Logs\&quot;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">string</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$LogName</span> &nbsp;<span style="color: #66cc66;">=</span> <span style="color: #009900;">&quot;Robocopy-log-file.log&quot;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">int</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$ArchiveDays</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">30</span><br />
<span style="color: #333;">&#41;</span><br />
<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">string</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$Log</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">Join-<span style="font-style: normal;">Path</span></span> <span style="color: #660033; font-weight: bold;">$LogPath</span> <span style="color: #660033; font-weight: bold;">$LogName</span><br />
<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">string</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$LogError</span> <span style="color: #66cc66;">=</span> <span style="color: #009900;">&quot;$Log.ERROR.$(get-date -format 'yyyy-MM-dd-hhmmss')&quot;</span><br />
<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">string</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$LogArchive</span> <span style="color: #66cc66;">=</span> <span style="color: #009900;">&quot;$Log.ARCHIVE.$(get-date -format 'yyyy-MM-dd-hhmmss')&quot;</span><br />
<br />
<span style="color: #660033; font-weight: bold;">$Errors</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">Select-<span style="font-style: normal;">String</span></span> <span style="color: #000066;">-Path</span> <span style="color: #660033; font-weight: bold;">$Log</span> <span style="color: #000066;">-Pattern</span> <span style="color: #009900;">'ERROR .*0x0000.*$'</span> <span style="color: #000066;">-context</span> <span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">|</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">Group-<span style="font-style: normal;">Object</span></span> <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$_</span>.<span style="color: #003366;">Context</span>.<span style="color: #003366;">PostContext</span> <span style="color: #333;">&#125;</span> <span style="color: #66cc66;">|</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">Format-<span style="font-style: normal;">Table</span></span> Count, Name <span style="color: #000066;">-HideTableHeaders</span> <span style="color: #000066;">-AutoSize</span> <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Out-<span style="font-style: normal;">String</span></span><br />
<span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$Errors</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">write-<span style="font-style: normal;">eventlog</span></span> Application <span style="color: #000066;">-Source</span> Robocopy <span style="color: #000066;">-EventId</span> <span style="color: #cc66cc;">12</span> <span style="color: #000066;">-EntryType</span> Error <span style="color: #000066;">-Message</span> <span style="color: #009900;">&quot;$errors<span style="color: #000099; font-weight: bold;">`n</span><span style="color: #000099; font-weight: bold;">`n</span>Please check: $LogError&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033;">move</span> <span style="color: #660033; font-weight: bold;">$Log</span> <span style="color: #660033; font-weight: bold;">$LogError</span><br />
<span style="color: #333;">&#125;</span> <span style="color: #666699; font-weight: bold;">else</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">write-<span style="font-style: normal;">eventlog</span></span> Application <span style="color: #000066;">-Source</span> Robocopy <span style="color: #000066;">-EventId</span> <span style="color: #cc66cc;">1</span> <span style="color: #000066;">-EntryType</span> Information &nbsp;<span style="color: #000066;">-Message</span> <span style="color: #009900;">&quot;Robocopy successful. Log archived: $LogArchive&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">move-<span style="font-style: normal;">item</span></span> <span style="color: #660033; font-weight: bold;">$Log</span> <span style="color: #660033; font-weight: bold;">$LogArchive</span><br />
<span style="color: #333;">&#125;</span><br />
<br />
<span style="color: #666666; font-style: italic;">## Remove archive logs older than $archiveDate</span><br />
<span style="color: #660033; font-weight: bold;">$archiveDate</span> <span style="color: #66cc66;">=</span> <span style="color: #333;">&#40;</span><span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Date</span></span><span style="color: #333;">&#41;</span>.<span style="color: #003366;">AddDays</span><span style="color: #333;">&#40;</span><span style="color: #66cc66;">-</span><span style="color: #660033; font-weight: bold;">$archiveDays</span><span style="color: #333;">&#41;</span><br />
<span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">ChildItem</span></span> <span style="color: #009900;">&quot;$Log.ARCHIVE.*&quot;</span> <span style="color: #66cc66;">|</span> <span style="color: #660033;">Where</span> <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$_</span>.<span style="color: #003366;">CreationTime</span> <span style="color: #000066;">-lt</span> <span style="color: #660033; font-weight: bold;">$archiveDate</span> <span style="color: #333;">&#125;</span> <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Remove-<span style="font-style: normal;">Item</span></span></div>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/logging-robocopy-errors-to-the-event-log-using-powershell/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>A DSL for XML in PowerShell: New-XDocument</title>
		<link>http://huddledmasses.org/a-dsl-for-xml-in-powershell-new-xdocument/</link>
		<comments>http://huddledmasses.org/a-dsl-for-xml-in-powershell-new-xdocument/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 05:52:12 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Atom]]></category>
		<category><![CDATA[DSL]]></category>
		<category><![CDATA[Generator]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Xml]]></category>

		<guid isPermaLink="false">http://huddledmasses.org/?p=1406</guid>
		<description><![CDATA[In July of last year I wrote a PowerShell script with the goal of allowing me to generate XML from PowerShell with a simple markup that would look a little like the resulting XML ... this week I was using that script again, and had a couple of issues that made me go back and [...]]]></description>
			<content:encoded><![CDATA[	<p>In July of last year <a href="http://poshcode.org/1233">I wrote a PowerShell script</a> with the goal of allowing me to generate <span class="caps">XML</span> from PowerShell with a simple markup that would look a little like the resulting <span class="caps">XML</span> ... this week I was using that script again, and had a couple of issues that made me go back and look at the source.</p>

	<p>While I was playing with the source and tweaking things a little bit to improve the way it handles namespaces, I started playing with the idea that I could improve the syntax. At the very least, I thought, I ought to be able to do away with all those &#8220;xe&#8221; aliases&#8230;</p>

	<p>Well, <a href="http://poshcode.org/1682">I was able to</a>.  ( <img src='http://huddledmasses.org/wordpress/wp-includes/' alt='[new]' class='wp-smiley' />  <a href="http://poshcode.org/1888">new version</a>) And what&#8217;s more, I managed to dramatically clean up the way namespaces work, and make it so that really, the only ugly part of the syntax is the initial declaration of namespaces! I&#8217;m going to start with two examples, and use them to walk you through the features  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=':)' class='wp-smiley' /> </p>

	<h3>Example 1</h3>

	<p>The simplest example I could think of is to list all the files in a folder, with the file size and last modified stamp:</p>

	<div class="posh code posh" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">string</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$xml</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">XDocument</span></span> folder <span style="color: #000066;">-path</span> <span style="color: #660033; font-weight: bold;">$pwd</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;">$file</span> <span style="color: #666699; font-weight: bold;">in</span> <span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">ChildItem</span></span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; file <span style="color: #000066;">-Modified</span> <span style="color: #660033; font-weight: bold;">$file</span>.<span style="color: #003366;">LastWriteTimeUtc</span> <span style="color: #000066;">-Size</span> <span style="color: #660033; font-weight: bold;">$file</span>.<span style="color: #003366;">Length</span> <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$file</span>.<span style="color: #003366;">Name</span> <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span></div>

	<p>The output of that, when run on my formats folder, looks like this:</p>

	<div class="xml code xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;folder</span> <span style="color: #000066;">path</span>=<span style="color: #ff0000;">&quot;C:\Users\Jaykul\Documents\WindowsPowerShell\formats&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;file</span> <span style="color: #000066;">modified</span>=<span style="color: #ff0000;">&quot;2009-11-07T07:27:00Z&quot;</span> <span style="color: #000066;">size</span>=<span style="color: #ff0000;">&quot;30474&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>CliXml.xsd<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;file</span> <span style="color: #000066;">modified</span>=<span style="color: #ff0000;">&quot;2009-11-07T07:27:40.48001Z&quot;</span> <span style="color: #000066;">size</span>=<span style="color: #ff0000;">&quot;14314&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>format.xsd<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;file</span> <span style="color: #000066;">modified</span>=<span style="color: #ff0000;">&quot;2010-01-16T21:30:06.0562796Z&quot;</span> <span style="color: #000066;">size</span>=<span style="color: #ff0000;">&quot;18275&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>NppExternalLexers.xml<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;file</span> <span style="color: #000066;">modified</span>=<span style="color: #ff0000;">&quot;2009-03-18T21:28:51.6579351Z&quot;</span> <span style="color: #000066;">size</span>=<span style="color: #ff0000;">&quot;5802&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Recommender.Types.Format.ps1xml<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;file</span> <span style="color: #000066;">modified</span>=<span style="color: #ff0000;">&quot;2009-11-07T07:27:40.518029Z&quot;</span> <span style="color: #000066;">size</span>=<span style="color: #ff0000;">&quot;5107&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>types.xsd<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/folder<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div>

	<p>You can immediately see what the script does: New-XDocument (which is aliased as &#8216;xml&#8217;) actually generates the root xml node, so the first argument to it is the name of that node, and any other arguments become attributes &#8230; except for the script block. That script block turns into the <em>contents</em> of the node.</p>

	<p>Inside the script block, PowerShell code is parsed as usual, but whenever a command that doesn&#8217;t exist is encountered, it is turned into an xml node! Pretty simple, right?  Of course, if you wanted to create a node with a name that&#8217;s already taken by a PowerShell command, you can just replace <code>file</code> with <code>New-XElement file</code>, or (using aliases) <code>xe &#39;file&#39;</code>, which explicitly creates an xml node with the given name.</p>

	<p>That&#8217;s pretty much it for our first example, so let&#8217;s look at a more complicated example, with multiple namespaces, and deeper nesting.</p>

	<h3>Example 2</h3>

	<p>This time, we&#8217;ll create an Atom document, and we&#8217;ll include some namespace extensions (including a made up one for listing my files as we did above):</p>

	<div class="posh code posh" style="font-family:monospace;"><span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">XDocument</span></span> <span style="color: #333;">&#40;</span><span style="color: #333;">&#40;</span><span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>XNamespace<span style="color: #333;">&#93;</span></span><span style="color: #009900;">&quot;http://www.w3.org/2005/Atom&quot;</span><span style="color: #333;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #009900;">&quot;feed&quot;</span><span style="color: #333;">&#41;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;`<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">-fi</span> <span style="color: #333;">&#40;</span><span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>XNamespace<span style="color: #333;">&#93;</span></span><span style="color: #009900;">&quot;http://huddledmasses.org/schemas/FileInfo&quot;</span><span style="color: #333;">&#41;</span> &nbsp; `<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">-dc</span> <span style="color: #333;">&#40;</span><span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>XNamespace<span style="color: #333;">&#93;</span></span><span style="color: #009900;">&quot;http://purl.org/dc/elements/1.1&quot;</span><span style="color: #333;">&#41;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; `<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">-</span>$<span style="color: #333;">&#40;</span><span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>XNamespace<span style="color: #333;">&#93;</span></span>::<span style="color: #003366; font-weight: bold;">Xml</span> <span style="color: #66cc66;">+</span><span style="color: #009900;">'lang'</span><span style="color: #333;">&#41;</span> <span style="color: #009900;">&quot;en-US&quot;</span> <span style="color: #000066;">-Encoding</span> <span style="color: #009900;">&quot;UTF-16&quot;</span> &nbsp; &nbsp; &nbsp; &nbsp;`<br />
<span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;title <span style="color: #333;">&#123;</span><span style="color: #009900;">&quot;Huddled Masses: You can do more than breathe for free...&quot;</span><span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;link <span style="color: #333;">&#123;</span><span style="color: #009900;">&quot;http://HuddledMasses.org/&quot;</span><span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;updated <span style="color: #333;">&#123;</span><span style="color: #333;">&#40;</span><span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Date</span></span> <span style="color: #000066;">-f</span> u<span style="color: #333;">&#41;</span> <span style="color: #000066;">-replace</span> <span style="color: #009900;">&quot; &quot;</span>,<span style="color: #009900;">&quot;T&quot;</span><span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;author <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; name <span style="color: #333;">&#123;</span><span style="color: #009900;">&quot;Joel Bennett&quot;</span><span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; uri <span style="color: #333;">&#123;</span><span style="color: #009900;">&quot;http://HuddledMasses.org/&quot;</span><span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;id <span style="color: #333;">&#123;</span><span style="color: #009900;">&quot;http://HuddledMasses.org/&quot;</span> <span style="color: #333;">&#125;</span><br />
<br />
&nbsp; &nbsp;entry <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; title <span style="color: #333;">&#123;</span><span style="color: #009900;">&quot;A DSL for XML in PowerShell: New-XDocument&quot;</span><span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; link <span style="color: #333;">&#123;</span><span style="color: #009900;">&quot;http://HuddledMasses.org/A-DSL-for-XML-in-PowerShell-New-XDocument/&quot;</span> <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; id <span style="color: #333;">&#123;</span><span style="color: #009900;">&quot;http://HuddledMasses.org/A-DSL-for-XML-in-PowerShell-New-XDocument/&quot;</span> <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; updated <span style="color: #333;">&#123;</span><span style="color: #333;">&#40;</span><span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Date</span></span> <span style="color: #cc66cc;">2010</span><span style="color: #66cc66;">/</span>03<span style="color: #66cc66;">/</span>03 <span style="color: #000066;">-f</span> u<span style="color: #333;">&#41;</span> <span style="color: #000066;">-replace</span> <span style="color: #009900;">&quot; &quot;</span>,<span style="color: #009900;">&quot;T&quot;</span><span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; summary <span style="color: #333;">&#123;</span><span style="color: #009900;">&quot;A while back, I posted a simple mini language for generating XML from PowerShell script. However, I was using it the other day, and I really just felt that the markup was ugly, since it was littered with 'xe' marks and such.&quot;</span><span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; link <span style="color: #000066;">-rel</span> license <span style="color: #000066;">-href</span> <span style="color: #009900;">&quot;http://creativecommons.org/licenses/by/3.0/&quot;</span> <span style="color: #000066;">-title</span> <span style="color: #009900;">&quot;CC By-Attribution&quot;</span><br />
&nbsp; &nbsp; &nbsp; dc:rights <span style="color: #333;">&#123;</span> <span style="color: #009900;">&quot;Copyright 2010, Some rights reserved (licensed under the Creative Commons Attribution 3.0 Unported license)&quot;</span> <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; category <span style="color: #000066;">-scheme</span> <span style="color: #009900;">&quot;http://huddledmasses.org/tag/&quot;</span> <span style="color: #000066;">-term</span> <span style="color: #009900;">&quot;xml&quot;</span><br />
&nbsp; &nbsp; &nbsp; category <span style="color: #000066;">-scheme</span> <span style="color: #009900;">&quot;http://huddledmasses.org/tag/&quot;</span> <span style="color: #000066;">-term</span> <span style="color: #009900;">&quot;PowerShell&quot;</span><br />
&nbsp; &nbsp; &nbsp; category <span style="color: #000066;">-scheme</span> <span style="color: #009900;">&quot;http://huddledmasses.org/tag/&quot;</span> <span style="color: #000066;">-term</span> <span style="color: #009900;">&quot;DSL&quot;</span><br />
&nbsp; &nbsp; &nbsp; fi:folder <span style="color: #000066;">-Path</span> <span style="color: #009900;">&quot;~\Formats&quot;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">foreach</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$file</span> <span style="color: #666699; font-weight: bold;">in</span> <span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">ChildItem</span></span> <span style="color: #333;">&#40;</span><span style="color: #0066cc; font-style: italic;">Join-<span style="font-style: normal;">Path</span></span> <span style="color: #333;">&#40;</span><span style="color: #0066cc; font-style: italic;">Split-<span style="font-style: normal;">Path</span></span> <span style="color: #660033; font-weight: bold;">$profile</span><span style="color: #333;">&#41;</span> Formats<span style="color: #333;">&#41;</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fi:file <span style="color: #000066;">-Created</span> <span style="color: #660033; font-weight: bold;">$file</span>.<span style="color: #003366;">CreationTimeUtc</span> <span style="color: #000066;">-Modified</span> <span style="color: #660033; font-weight: bold;">$file</span>.<span style="color: #003366;">LastWriteTimeUtc</span> <span style="color: #000066;">-Size</span> <span style="color: #660033; font-weight: bold;">$file</span>.<span style="color: #003366;">Length</span> <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$file</span>.<span style="color: #003366;">Name</span> <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span> <span style="color: #66cc66;">|</span> <span style="color: #66cc66;">%</span> <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$_</span>.<span style="color: #003366;">Declaration</span>.<span style="color: #003366;">ToString</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span>; <span style="color: #660033; font-weight: bold;">$_</span>.<span style="color: #003366;">ToString</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#125;</span></div>

	<p>There are four things you should notice, in particular:</p>

	<p>First: the initial tag has a [XNamespace] added to it. You can specify a tag name that has a namespace by adding them together this way, or by embedding the namespace in the string like <code>&#34;{http://www.w3.org/2005/Atom}feed&#34;</code> instead.  Either way works. This initial namespace becomes the <strong>default</strong> namespace for the document. If you don&#8217;t specify a namespace on tags later, they automatically belong to that one.</p>

	<p>Second: when you want to add additional namespaces, you can do so with a custom prefix like: <code>-dc ([XNamespace]&#34;http://purl.org/dc/elements/1.1&#34;)</code>, and that prefix (dc) takes on a special meaning. When you want to have a tag later on that is part of that namespace, you just prefix the tag, like <code>dc:rights</code> &#8212;the same way you would in <span class="caps">XML</span>.</p>

	<p>Third: any number of attributes can be specified using the <code>-name value</code> syntax, but anything in a <code>{scriptblock}</code> becomes the content &#8212; and is subject to the same rules as the outer sections.</p>

	<p>Fourth: This generates an XDocument. When you cast an XDocument to string, the xml declaration is left off, so if you want it, you need to manually add it via <code>$XDocument.Declaration</code>.  Incidentally, XDocuments are <strong>not</strong> XMLDocuments, but they <strong>are</strong> trivially castable to them.</p>

	<p>The output of that particular section of New-XDocument is this:</p>

	<div class="xml code xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;feed</span> <span style="color: #000066;">xmlns:dc</span>=<span style="color: #ff0000;">&quot;http://purl.org/dc/elements/1.1&quot;</span> <span style="color: #000066;">xmlns:fi</span>=<span style="color: #ff0000;">&quot;http://huddledmasses.org/schemas/FileInfo&quot;</span> <span style="color: #000066;">xml:lang</span>=<span style="color: #ff0000;">&quot;en-US&quot;</span> <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">&quot;http://www.w3.org/2005/Atom&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; <br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;link</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>http://HuddledMasses.org/<br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;updated<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2010-03-04T00:44:31Z<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/updated<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;author<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;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Joel Bennett<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<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;uri<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>http://HuddledMasses.org/<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/uri<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/author<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>http://HuddledMasses.org/<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;entry<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;link</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>http://HuddledMasses.org/A-DSL-for-XML-in-PowerShell-New-XDocument/<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>http://HuddledMasses.org/A-DSL-for-XML-in-PowerShell-New-XDocument/<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/id<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;updated<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2010-03-03T00:00:00Z<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/updated<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;summary<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>A while back, I posted a simple mini language for generating XML from PowerShell script. However, I was using it the other day, and I really just felt that the markup was ugly, since it was littered with 'xe' marks and such.<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/summary<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;link</span> <span style="color: #000066;">rel</span>=<span style="color: #ff0000;">&quot;license&quot;</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;http://creativecommons.org/licenses/by/3.0/&quot;</span> <span style="color: #000066;">title</span>=<span style="color: #ff0000;">&quot;CC By-Attribution&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dc:rights<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Copyright 2010, Some rights reserved (licensed under the Creative Commons Attribution 3.0 Unported license)<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dc:rights<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;category</span> <span style="color: #000066;">scheme</span>=<span style="color: #ff0000;">&quot;http://huddledmasses.org/tag/&quot;</span> <span style="color: #000066;">term</span>=<span style="color: #ff0000;">&quot;xml&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;category</span> <span style="color: #000066;">scheme</span>=<span style="color: #ff0000;">&quot;http://huddledmasses.org/tag/&quot;</span> <span style="color: #000066;">term</span>=<span style="color: #ff0000;">&quot;PowerShell&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;category</span> <span style="color: #000066;">scheme</span>=<span style="color: #ff0000;">&quot;http://huddledmasses.org/tag/&quot;</span> <span style="color: #000066;">term</span>=<span style="color: #ff0000;">&quot;DSL&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;fi:folder</span> <span style="color: #000066;">path</span>=<span style="color: #ff0000;">&quot;~\Formats&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;fi:file</span> <span style="color: #000066;">created</span>=<span style="color: #ff0000;">&quot;2009-11-07T07:27:00Z&quot;</span> <span style="color: #000066;">modified</span>=<span style="color: #ff0000;">&quot;2009-11-07T07:27:00Z&quot;</span> <span style="color: #000066;">size</span>=<span style="color: #ff0000;">&quot;30474&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>CliXml.xsd<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/fi:file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;fi:file</span> <span style="color: #000066;">created</span>=<span style="color: #ff0000;">&quot;2009-11-07T07:27:40.4529965Z&quot;</span> <span style="color: #000066;">modified</span>=<span style="color: #ff0000;">&quot;2009-11-07T07:27:40.48001Z&quot;</span> <span style="color: #000066;">size</span>=<span style="color: #ff0000;">&quot;14314&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>format.xsd<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/fi:file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;fi:file</span> <span style="color: #000066;">created</span>=<span style="color: #ff0000;">&quot;2009-02-07T13:56:12Z&quot;</span> <span style="color: #000066;">modified</span>=<span style="color: #ff0000;">&quot;2010-01-16T21:30:06.0562796Z&quot;</span> <span style="color: #000066;">size</span>=<span style="color: #ff0000;">&quot;18275&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>NppExternalLexers.xml<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/fi:file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;fi:file</span> <span style="color: #000066;">created</span>=<span style="color: #ff0000;">&quot;2009-08-09T19:10:06.3647094Z&quot;</span> <span style="color: #000066;">modified</span>=<span style="color: #ff0000;">&quot;2009-03-18T21:28:51.6579351Z&quot;</span> <span style="color: #000066;">size</span>=<span style="color: #ff0000;">&quot;5802&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Recommender.Types.Format.ps1xml<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/fi:file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;fi:file</span> <span style="color: #000066;">created</span>=<span style="color: #ff0000;">&quot;2009-11-07T07:27:40.4970185Z&quot;</span> <span style="color: #000066;">modified</span>=<span style="color: #ff0000;">&quot;2009-11-07T07:27:40.518029Z&quot;</span> <span style="color: #000066;">size</span>=<span style="color: #ff0000;">&quot;5107&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>types.xsd<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/fi:file<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;/fi:folder<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/category<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/category<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/category<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/entry<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/feed<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div>

	<p>The New-XDocument script itself is on PoshCode in the <a href="http://poshcode.org/1682">Xml Module 4</a> along with a few interesting functions like Select-<span class="caps">XML</span> (which improves over the built-in by being able to ignore namespaces when you write XPath) and Remove-XmlNamespace (which was instrumental in removing namespaces for Select-Xml). There&#8217;s also a  Format-Xml for pretty-printing, and a Convert-Xml for processing <span class="caps">XSL</span> transformations.</p>

	<p>I&#8217;ll probably post some more examples of this in the next week or two, and I really should write some commentary about the function itself, which uses the tokenizer to discover which &#8220;commands&#8221; are really xml nodes &#8230; but for now, I&#8217;ll leave you to enjoy.<h6 class="zemanta-related-title">Related articles by Zemanta</h6><ul class="zemanta-article-ul"><li class="zemanta-article-ul-li"><a href="http://huddledmasses.org/json-from-powershell-but-why/"><span class="caps">JSON</span> from PowerShell (but why?)</a> (huddledmasses.org)</li><li class="zemanta-article-ul-li"><a href="http://apache.sys-con.com/node/1211348">What&#8217;s in a Namespace</a> (apache.sys-con.com)</li><li class="zemanta-article-ul-li"><a href="http://huddledmasses.org/ignoring-namespaces-in-xpath/">Ignoring Namespaces in XPath</a> (huddledmasses.org)</li></ul></p>

<div class="zemanta-pixie"><a class="zemanta-pixie-a" href="http://reblog.zemanta.com/zemified/c26e9d24-6176-4c07-a3f7-9eb438404e7e/" title="Reblog this post [with Zemanta]"><img class="zemanta-pixie-img" src="http://img.zemanta.com/reblog_e.png?x-id=c26e9d24-6176-4c07-a3f7-9eb438404e7e" alt="Reblog this post [with Zemanta]" /></a><span class="zem-script more-related pretty-attribution"><script type="text/javascript" src="http://static.zemanta.com/readside/loader.js" defer="defer"></script></span></div>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/a-dsl-for-xml-in-powershell-new-xdocument/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Are you interested in a virtual PowerShell brown-bag event?</title>
		<link>http://huddledmasses.org/are-you-interested-in-a-virtual-powershell-brown-bag-event/</link>
		<comments>http://huddledmasses.org/are-you-interested-in-a-virtual-powershell-brown-bag-event/#comments</comments>
		<pubDate>Wed, 24 Feb 2010 18:30:00 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Brown Bag]]></category>
		<category><![CDATA[Poll]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[User Group]]></category>
		<category><![CDATA[Virtual Group]]></category>

		<guid isPermaLink="false">http://huddledmasses.org/are-you-interested-in-a-virtual-powershell-brown-bag-event/</guid>
		<description><![CDATA[I just put up a poll on the PowerShell Virtual Group to see if people are interested in a low-planning brown-bag event. The initial question is: would you attend a weekly (or monthly) virtual brown-bag lunch if I put one together. The idea is that we would start each session with a short collection of [...]]]></description>
			<content:encoded><![CDATA[	<p>I just <a href="http://powershellgroup.org/virtual/brown-bag-poll-1">put up a poll</a> on the <a href="http://powershellgroup.org/virtual">PowerShell Virtual Group</a> to see if people are interested in a low-planning brown-bag event.</p>

	<p>The initial question is: would you attend a weekly (or monthly) virtual brown-bag lunch if I put one together.</p>

	<p>The idea is that we would start each session with a short collection of interesting links, tips and tricks, or <a href="http://connect.microsoft.com/PowerShell">connect</a> issues, and then have a presentation or discussion or script club or open-mic session, depending on interest.</p>

	<p>Basically, this is meant to flow, on a week-to-week basis, from script-club to formal user group presentations. </p>

	<p>Some weeks we would have presenters from various local user groups share content they had prepared for their local groups. We would encourage you to take ownership of this time, request topics, and prepare presentations (no matter how short).</p>

	<p>Some weeks we would have an open-format script club using our private pastebin, <span class="caps">IRC</span> channel, and LiveMeeting voice chat.  This time could vary from real-world problem solving to scripting games and &#8220;project Euler&#8221;-style challenges.</p>

	<p>Some weeks we would have open-mic time and solicit feedback for the PowerShell team from anyone who cared to give it. I would make an effort to make sure I wasn&#8217;t the only <span class="caps">MVP</span> there, so you could feel that even if there wasn&#8217;t a Microsoft employee present on a given day, your voice could be heard when you make suggestions or vent frustrations &#8230; </p>

	<p>The point is: the format would vary a bit, and we would adjust it over time to fit whatever works the best within our virtual meeting and time constraints.</p>

	<p>So, what do you think? <a href="http://powershellgroup.org/virtual/brown-bag-poll-1">Are you interested?</a></p>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/are-you-interested-in-a-virtual-powershell-brown-bag-event/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Fun with PInvoke and Aero Peek</title>
		<link>http://huddledmasses.org/fun-with-pinvoke-and-aero-peek/</link>
		<comments>http://huddledmasses.org/fun-with-pinvoke-and-aero-peek/#comments</comments>
		<pubDate>Sun, 23 Aug 2009 05:07:16 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Aero Peek]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[DwmSetWindowAttribute]]></category>
		<category><![CDATA[DWMWA_EXCLUDED_FROM_PEEK]]></category>
		<category><![CDATA[PInvoke]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Win32]]></category>
		<category><![CDATA[Windows 7]]></category>

		<guid isPermaLink="false">http://huddledmasses.org/?p=1247</guid>
		<description><![CDATA[There are so many fun things you can do in Windows when your scripting language allows you to make PInvoke calls to Win32 APIs &#8230; but I have to say it&#8217;s amazing how many things have been added to Windows recently and still left out of the .Net framework &#8230; Anyway, on to the Aero [...]]]></description>
			<content:encoded><![CDATA[	<p>There are so many fun things you can do in Windows when your scripting language allows you to make PInvoke calls to Win32 APIs &#8230; but I have to say it&#8217;s amazing how many things have been added to Windows recently and still left out of the .Net framework &#8230;</p>

	<p>Anyway, on to the <a href="http://windows.microsoft.com/en-us/windows7/products/features/aero-peek">Aero Peek</a> stuff.  If you haven&#8217;t seen it, Aero Peek is a feature of Windows 7, which lets you get a peek at your desktop, or at a single window for a moment.  Basically, you can press Win+Space (the Windows logo key and the space bar) and all of your open windows instantly turn transparent, revealing &#8230; whatever was on your desktop: wallpaper, icons, and gadgets.   You can also use it by hovering your mouse on the right corner of the taskbar, or you can peek at a single window by hovering over it&#8217;s taskbar button and then over it&#8217;s thumbnail.</p>

	<p>In any case, I have a couple of windows which I would like to have stay visible on the desktop when I hit the aero peek hotkey: Rainlendar and Miranda.  It turns out there&#8217;s a simple <span class="caps">API</span> call for this: <code>DwmSetWindowAttribute</code> which lets you set the <code>DWMWA_EXCLUDED_FROM_PEEK</code> attribute to <code>ENABLED</code> &#8230; causing a window to no longer hide when you press that hotkey. Of course, that <span class="caps">API</span> call should be made by those apps, in response to a user setting (so I&#8217;ve told their authors about it), but it doesn&#8217;t <em>have</em> to be (so I wrote a script to do it myself).</p>

	<p>In the old days, I would have written a little systray app which would give you a popup list of all windows, or perhaps added a menu item to a window&#8217;s right-click menu &#8230; and I would have had to deal with creating some way to persist which apps you wanted to apply this to, and then I could have applied the setting to them whenever you opened them. </p>

	<p>But now, I have PowerShell. I don&#8217;t need to give you menus and store settings, because I can just let you edit a little script instead.</p>

	<p>So here&#8217;s a script which will let you turn off Aero Peek transparency for windows by window title and/or process name &#8230; Once you have this function available, you can keep Rainlendar&#8217;s calendar, tasks, and event windows all visible by just running <code>Remove-AeroPeek -Process Rainlendar2</code> or you can keep your <a class="zem_slink" href="http://www.miranda-im.org/" title="Miranda IM" rel="homepage">Miranda</a> contact list visible by running <code>Remove-AeroPeek &#34;Miranda IM&#34;</code> (although you should not that depends on the window title matching just that one window &#8212; and Miranda lets you change what your title is, so you may have to adjust it).</p>

<script type="text/javascript" src="http://PoshCode.org/embed/1288"></script>

	<p>Of course, that script really deserves explanation, because it&#8217;s showing off quite a few advanced things&#8230;</p>

	<p>The first thing is that I&#8217;m using a Try/Catch block in the <span class="caps">BEGIN</span> block to make sure I only execute that code once. You can&#8217;t call Add-Type with the same code multiple times in a single PowerShell session, because the type will already exist when you call it the second time.  So the code in the <code>try</code> block will throw an exception if the type doesn&#8217;t already exist, and in the catch handler, we&#8217;ll create the type, and define the other function we need.</p>

	<p>Add-Type is a super-powerful cmdlet which compiles code on the fly (or imports types from pre-compiled assemblies). In this case we&#8217;re using it to import a little class called Dwm which I started writing myself from PInvoke.net and the <span class="caps">MSDN</span> documentation, but then eventually copied most of from a NeoWin forum thread&#8230;  All this class really does is define the <span class="caps">API</span> function and the flags we need to pass to it, and then provides a wrapper for the DwmSetWindowAttribute call. We could have written that call in PowerShell, but at the end of the day, once you start compiling C# code in PowerShell, it&#8217;s hard to know when to stop  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=';)' class='wp-smiley' /> </p>

	<p>The Select-Window function is (yet another customized version of) a function I wrote awhile back on PoshCode as part of my (still in progress) rewrite of <a href="http://WASP.CodePlex.com">WASP</a> to use the <a href="http://msdn.microsoft.com/en-us/library/aa348551.aspx#Testing_with_UI_Automation">UIAutomationClient</a> &#8230; I&#8217;ve just modified it to add only the three properties of the window that I&#8217;m interested in: Title and ProcessId (for identifying the correct windows) and Handle (for passing to the <code>DwmSetWindowAttribute</code> call).  It uses the <code>RootElement</code> property of <a href="http://msdn.microsoft.com/en-us/library/system.windows.automation.automationelement.aspx">System.Windows.Automation.AutomationElement</a> to do a search, and then a series of GetCurrentPropertyValue calls to determine the Name, ProcessId, and NativeWindowHandle of the windows it finds.</p>

	<p>That&#8217;s pretty much all there is to it, other than filtering out the window(s) that we want and actually calling the <span class="caps">API</span>. I think I&#8217;m going to have to play a little bit more with this to see what else we can do &#8212; I&#8217;ve already realized that this means we can make little widgets with PowerBoots and set them to stick around just like regular desktop gadgets &#8230;</p>

<div class="zemanta-pixie"><a class="zemanta-pixie-a" href="http://reblog.zemanta.com/zemified/9d449ee5-040d-4fc6-8cf0-9791b23f0898/" title="Reblog this post [with Zemanta]"><img class="zemanta-pixie-img" src="http://img.zemanta.com/reblog_e.png?x-id=9d449ee5-040d-4fc6-8cf0-9791b23f0898" alt="Reblog this post [with Zemanta]" /></a><span class="zem-script more-related pretty-attribution"><script type="text/javascript" src="http://static.zemanta.com/readside/loader.js" defer="defer"></script></span></div>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/fun-with-pinvoke-and-aero-peek/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>More Growl for Windows from PowerShell</title>
		<link>http://huddledmasses.org/more-growl-for-windows-from-powershell/</link>
		<comments>http://huddledmasses.org/more-growl-for-windows-from-powershell/#comments</comments>
		<pubDate>Mon, 17 Aug 2009 05:45:05 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Growl]]></category>
		<category><![CDATA[Growl for Windows]]></category>
		<category><![CDATA[Notifications]]></category>
		<category><![CDATA[Popup]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://huddledmasses.org/?p=1237</guid>
		<description><![CDATA[Well, I&#8217;m back already with an update for the Growl module I posted yesterday &#8230; This new version is a true PowerShell 2.0 only module, because I found that the Growl callbacks can only be handled in PowerShell 2.0 anyway, so in order to add support for that, I went ahead and upgraded the rest. [...]]]></description>
			<content:encoded><![CDATA[	<p>Well, I&#8217;m back already with an update for the Growl module <a href="http://huddledmasses.org/growl-for-windows-from-powershell/">I posted yesterday</a> &#8230;</p>

	<p>This new version is a true PowerShell 2.0 only module, because I found that the Growl callbacks can only be handled in PowerShell 2.0 anyway, so in order to add support for that, I went ahead and upgraded the rest.</p>

	<p>The Growl module is now designed to be used BY your PowerShell scripts and modules.  The idea is that if you wrote, say, a script/module to check for email and called it PoshMail &#8230; you could start up Growl like this:</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #0066cc; font-style: italic;">Import-<span style="font-style: normal;">Module</span></span> Growl<br />
<br />
<span style="color: #666666; font-style: italic;">## At least once (e.g.: on the first Type you register) you should include an AppIcon :)</span><br />
<span style="color: #0066cc; font-style: italic;">Register-<span style="font-style: normal;">GrowlType</span></span> PoshMail NewMail <span style="color: #000066;">-AppIcon</span> <span style="color: #660033; font-weight: bold;">$PoshMailFolder</span>\Email<span style="color: #66cc66;">-</span>48.<span style="color: #003366;">png</span> <br />
<span style="color: #666666; font-style: italic;">## If you want to, you can still override the icon per notice type</span><br />
<span style="color: #0066cc; font-style: italic;">Register-<span style="font-style: normal;">GrowlType</span></span> PoshMail Hotmail <span style="color: #000066;">-Icon</span> <span style="color: #660033; font-weight: bold;">$PoshMailFolder</span>\Hotmail<span style="color: #66cc66;">-</span>48.<span style="color: #003366;">png</span><br />
<span style="color: #0066cc; font-style: italic;">Register-<span style="font-style: normal;">GrowlType</span></span> PoshMail GMail <span style="color: #000066;">-Icon</span> <span style="color: #660033; font-weight: bold;">$PoshMailFolder</span>\GMail<span style="color: #66cc66;">-</span>48.<span style="color: #003366;">png</span> <br />
&nbsp;</div>

	<p>Now, technically that&#8217;s all we have to do. At that point, we could pop up Growl notices for either Hotmail or GMail &#8230; let&#8217;s say our fictitious script (which is running in the background on an event timer) discovers a new message &#8230;  you could notify the user with a Url callback.  Let&#8217;s assume that you have a few variables set after checking for email:
	<ul>
		<li>$Number is the number of email messages</li>
		<li>$Subjects is an array of email subject lines</li>
	</ul>
	<ul>
		<li>$Urls is an array of links to the emails</li>
	</ul></p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #0066cc; font-style: italic;">Send-<span style="font-style: normal;">Growl</span></span> PoshMail GMail <span style="color: #009900;">&quot;You have $number new messages&quot;</span> <span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$Summary</span><span style="color: #333;">&#91;</span>0..2<span style="color: #333;">&#93;</span> <span style="color: #000066;">-join</span> <span style="color: #009900;">&quot;<span style="color: #000099; font-weight: bold;">`n</span>&quot;</span><span style="color: #333;">&#41;</span> <span style="color: #000066;">-Url</span> <span style="color: #660033; font-weight: bold;">$Urls</span><span style="color: #333;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #333;">&#93;</span><br />
<span style="color: #666666; font-style: italic;"># OR ...</span><br />
<span style="color: #0066cc; font-style: italic;">Send-<span style="font-style: normal;">Growl</span></span> PoshMail Hotmail <span style="color: #009900;">&quot;You have $number new messages&quot;</span> <span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$Summary</span><span style="color: #333;">&#91;</span>0..2<span style="color: #333;">&#93;</span> <span style="color: #000066;">-join</span> <span style="color: #009900;">&quot;<span style="color: #000099; font-weight: bold;">`n</span>&quot;</span><span style="color: #333;">&#41;</span> <span style="color: #000066;">-Url</span> <span style="color: #660033; font-weight: bold;">$Urls</span><span style="color: #333;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #333;">&#93;</span><br />
&nbsp;</div>

	<p>Of course, if you wanted to launch your Outlook 2010 preview because you discovered new <span class="caps">POP</span> or <span class="caps">IMAP</span> mail &#8230; or because you want to use Outlook to read your Hotmail/GMail &#8230; then a callback <span class="caps">URL</span> isn&#8217;t going to cut it.  In that case, you want to handle the click event yourself:</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<br />
<span style="color: #666666; font-style: italic;">## We would need it to launch something appropriate on receipt of new POP3 email, for instance.</span><br />
<span style="color: #0066cc; font-style: italic;">Register-<span style="font-style: normal;">GrowlCallback</span></span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">PARAM</span><span style="color: #333;">&#40;</span> <span style="color: #660033; font-weight: bold;">$response</span>, <span style="color: #660033; font-weight: bold;">$context</span> <span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #666666; font-style: italic;"># This is just here for your sake, because I know you want to know what else is in there:</span><br />
&nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> $<span style="color: #333;">&#40;</span><span style="color: #009900;">&quot;Response Type: {0}<span style="color: #000099; font-weight: bold;">`n</span>Notification ID: {1}<span style="color: #000099; font-weight: bold;">`n</span>Callback Data: {2}<span style="color: #000099; font-weight: bold;">`n</span>Callback Data Type: {3}&quot;</span> <span style="color: #000066;">-f</span> <span style="color: #660033; font-weight: bold;">$context</span>.<span style="color: #003366;">Result</span>, <span style="color: #660033; font-weight: bold;">$context</span>.<span style="color: #003366;">NotificationID</span>, <span style="color: #660033; font-weight: bold;">$context</span>.<span style="color: #666699; font-weight: bold;">Data</span>, <span style="color: #660033; font-weight: bold;">$context</span>.<span style="color: #003366; font-weight: bold;">Type</span><span style="color: #333;">&#41;</span> <span style="color: #000066;">-fore</span> Yellow<br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$context</span>.<span style="color: #003366;">Result</span> <span style="color: #000066;">-eq</span> <span style="color: #009900;">&quot;Click&quot;</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">## Start the default email client</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">Start-<span style="font-style: normal;">Process</span></span> $<span style="color: #333;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$MailTo</span> <span style="color: #66cc66;">=</span> <span style="color: #333;">&#40;</span><span style="color: #660033;">gp</span> Registry::<span style="color: #003366;">HKEY_CLASSES_ROOT</span>\mailto\shell\open\command<span style="color: #333;">&#41;</span>.<span style="color: #009900;">&quot;(default)&quot;</span> <span style="color: #000066;">-split</span> <span style="color: #009900;">&quot; &quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">for</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$i</span><span style="color: #66cc66;">=</span><span style="color: #cc66cc;">0</span>;<span style="color: #660033; font-weight: bold;">$i</span><span style="color: #66cc66;">-</span><span style="color: #333399; font-weight: bold; font-style: italic;">lt</span><span style="color: #660033; font-weight: bold;">$mailto</span>.<span style="color: #003366;">Count</span>;<span style="color: #660033; font-weight: bold;">$i</span><span style="color: #66cc66;">++</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$email</span> <span style="color: #66cc66;">=</span> <span style="color: #009900;">&quot;$($mailto[0..$i])&quot;</span>.<span style="color: #003366;">Trim</span><span style="color: #333;">&#40;</span><span style="color: #009900;">'&quot;'</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span><span style="color: #0066cc; font-style: italic;">Resolve-<span style="font-style: normal;">Path</span></span> <span style="color: #660033; font-weight: bold;">$email</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#123;</span> <span style="color: #666699; font-weight: bold;">return</span> <span style="color: #660033; font-weight: bold;">$email</span> <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#41;</span><br />
<br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span><br />
&nbsp;</div>

	<p>Something like that should work regardless of your actual email client, and then you just have to pass a callback value to make sure your function gets called:</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #666666; font-style: italic;"># This would trigger the callback REGARDLESS of whether it was clicked.</span><br />
<span style="color: #0066cc; font-style: italic;">Send-<span style="font-style: normal;">Growl</span></span> PoshMail NewMail <span style="color: #009900;">&quot;You have $number new messages&quot;</span> <span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$Summary</span><span style="color: #333;">&#91;</span>0..2<span style="color: #333;">&#93;</span> <span style="color: #000066;">-join</span> <span style="color: #009900;">&quot;<span style="color: #000099; font-weight: bold;">`n</span>&quot;</span><span style="color: #333;">&#41;</span> <span style="color: #000066;">-CallbackData</span> <span style="color: #009900;">&quot;Data&quot;</span> <span style="color: #009900;">&quot;POP3 Callback&quot;</span><br />
&nbsp;</div>

	<p>There are a lot of other possibilities here, from alerting when long running commands finish (think PSJobs, or even remote jobs) to &#8230; writing popup-based PowerShell instant messengers, or even &#8230; using Growl as a ghetto inter-process communication medium which works on multiple PCs.  Ok, that&#8217;s maybe a bit much, but the point is: sky&#8217;s the limit. Have a little fun.  Note that the machine <span class="caps">SENDING</span> the popups doesn&#8217;t necessarily have to have Growl installed &#8212; you could just copy the libraries over and then send remote growls&#8230;.</p>

	<p><script type="text/javascript" src="http://poshcode.org/embed/1276"></script></p>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/more-growl-for-windows-from-powershell/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Growl for Windows &#8211; From PowerShell</title>
		<link>http://huddledmasses.org/growl-for-windows-from-powershell/</link>
		<comments>http://huddledmasses.org/growl-for-windows-from-powershell/#comments</comments>
		<pubDate>Fri, 14 Aug 2009 06:10:35 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Growl]]></category>
		<category><![CDATA[Growl for Windows]]></category>
		<category><![CDATA[Notifications]]></category>
		<category><![CDATA[Popup]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://huddledmasses.org/?p=1231</guid>
		<description><![CDATA[This is just a quick post (as I promised, recently) to let you all know that I&#8217;ve published the first release of my Growl for Windows module for PowerShell over on PoshCode. I haven&#8217;t been able to get callbacks to work, and I spent way too much time playing with them instead of publishing this, [...]]]></description>
			<content:encoded><![CDATA[<div class="zemanta-img"><div><dl class="wp-caption alignright"><a href="http://GrowlForWindows.com"><img src="http://www.GrowlForWindows.com/gfw/images/growl4windows.jpg" alt="Growl" title="Growl" /></a></dl></div></div>

	<p>This is just a quick post (as I promised, recently) to let you all know that I&#8217;ve published the first release of my <a href="http://GrowlForWindows.com">Growl for Windows</a> module for PowerShell over on PoshCode.</p>

	<p>I haven&#8217;t been able to get callbacks to work, and I spent way too much time playing with them instead of publishing this, or working on remote growls &#8230; but nonetheless, it&#8217;s sufficient to let you pop up growl notifications from scripts, which you can, of course, customize in Growl itself. </p>

	<p>You can add a few additional notice types very simply (you just hard code them in the script, copying lines 19 and 21 &#8212; remember you need to use the same notice names each time anyway) ... and then tweak them in Growl to have different display types, or to make some of your notice types sticky, or have them forwarded to your iPhone or whatever. </p>

	<h3>Here&#8217;s the first version of the script:</h3>

<script type="text/javascript" src="http://PoshCode.org/embed/1274"></script>

	<p>Note: if you want to use this on PowerShell 1.0, just comment out the <code>[Parameter(</code> lines, and dot-source it, it <em>should</em> work fine.  In PowerShell 2.0 you&#8217;ll want to load it as a module, because doing so will hide some of those ugly script variables.</p>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/growl-for-windows-from-powershell/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Control your PC with your voice &#8230; and PowerShell</title>
		<link>http://huddledmasses.org/control-your-pc-with-your-voice-and-powershell/</link>
		<comments>http://huddledmasses.org/control-your-pc-with-your-voice-and-powershell/#comments</comments>
		<pubDate>Thu, 25 Jun 2009 06:57:54 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Home automation]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Remote Control]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Speech recognition]]></category>

		<guid isPermaLink="false">http://huddledmasses.org/?p=1188</guid>
		<description><![CDATA[Have you ever wanted to be able to ask your computer questions and have it answer you out loud? Have you ever wondered if your computer could be more like the ones running the Star Trek Enterprise, responding to voice queries and commands? Have you played with ZWave or X10 home automation and thought that [...]]]></description>
			<content:encoded><![CDATA[	<ul>
		<li>Have you ever wanted to be able to ask your computer questions and have it answer you out loud? </li>
		<li>Have you ever wondered if your computer could be more like the ones running the Star Trek Enterprise, responding to voice queries and commands?</li>
	</ul>
	<ul>
		<li>Have you played with <a href="http://www.z-wave.com/">ZWave</a> or X10 home automation and thought that voice control of your devices would be an obvious next step?</li>
	</ul>

	<p>Well, ok &#8230; I&#8217;m not going to show you how to turn on lights or work with home automation &#8212; but that&#8217;s the main thing that keeps me thinking about this voice-recognition stuff. What geek doesn&#8217;t want to walk into the living room and say &#8220;Computer: Lights On&#8221; and have it work?</p>

	<p>Instead, as a first step to all of that, let me show you how to use PowerShell to do simple voice command recognition scripts &#8230; which can fire off any PowerShell script you care to write! <span id="more-1188"></span> The code which follows is really a module, although you can just dot-source it as a script, and it really requires PowerShell 2.0 for the events, although it would be trivial to refactor it to work on PowerShell 1.0 using Oisin&#8217;s <a href="http://pseventing.codeplex.com/">PSEventing library</a>.</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #660033; font-weight: bold;">$null</span> <span style="color: #66cc66;">=</span> <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>Reflection.<span style="color: #003366;">Assembly</span><span style="color: #333;">&#93;</span></span>::<span style="color: #003366;">LoadWithPartialName</span><span style="color: #333;">&#40;</span><span style="color: #009900;">&quot;System.Speech&quot;</span><span style="color: #333;">&#41;</span><br />
<br />
<span style="color: #666666; font-style: italic;">## Create the two main objects we need for speech recognition and synthesis</span><br />
<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;">$Global</span>:SpeechModuleListener<span style="color: #333;">&#41;</span><span style="color: #333;">&#123;</span> <span style="color: #666666; font-style: italic;">## For XP's sake, don't create them twice...</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$Global</span>:SpeechModuleSpeaker <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">new-<span style="font-style: normal;">object</span></span> System.<span style="color: #003366;">Speech</span>.<span style="color: #003366;">Synthesis</span>.<span style="color: #003366;">SpeechSynthesizer</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$Global</span>:SpeechModuleListener <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">new-<span style="font-style: normal;">object</span></span> System.<span style="color: #003366;">Speech</span>.<span style="color: #003366;">Recognition</span>.<span style="color: #003366;">SpeechRecognizer</span><br />
<span style="color: #333;">&#125;</span><br />
<br />
<span style="color: #660033; font-weight: bold;">$Script</span>:SpeechModuleMacros <span style="color: #66cc66;">=</span> @<span style="color: #333;">&#123;</span><span style="color: #333;">&#125;</span><br />
<span style="color: #666666; font-style: italic;">## Add a way to turn it off</span><br />
<span style="color: #660033; font-weight: bold;">$Script</span>:SpeechModuleMacros.<span style="color: #003366;">Add</span><span style="color: #333;">&#40;</span><span style="color: #009900;">&quot;Stop Listening&quot;</span>, <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$script</span>:listen <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$false</span>; <span style="color: #0066cc; font-style: italic;">Suspend-<span style="font-style: normal;">Listening</span></span> <span style="color: #333;">&#125;</span><span style="color: #333;">&#41;</span><br />
<span style="color: #660033; font-weight: bold;">$Script</span>:SpeechModuleComputerName <span style="color: #66cc66;">=</span> $<span style="color: #333;">&#123;</span>Env:ComputerName<span style="color: #333;">&#125;</span><br />
<br />
<span style="color: #666699; font-weight: bold;">function</span> <span style="color: #0066cc; font-style: italic;">Update-<span style="font-style: normal;">SpeechCommands</span></span> <span style="color: #333;">&#123;</span><br />
<span style="color: #666666; font-style: italic;">#.Synopsis </span><br />
<span style="color: #666666; font-style: italic;"># &nbsp;Recreate the speech recognition grammar</span><br />
<span style="color: #666666; font-style: italic;">#.Description</span><br />
<span style="color: #666666; font-style: italic;"># &nbsp;This parses out the speech module macros, </span><br />
<span style="color: #666666; font-style: italic;"># &nbsp;and recreates the speech recognition grammar and semantic results, </span><br />
<span style="color: #666666; font-style: italic;"># &nbsp;and then updates the SpeechRecognizer with the new grammar, </span><br />
<span style="color: #666666; font-style: italic;"># &nbsp;and makes sure that the ObjectEvent is registered.</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$choices</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">new-<span style="font-style: normal;">object</span></span> System.<span style="color: #003366;">Speech</span>.<span style="color: #003366;">Recognition</span>.<span style="color: #003366;">Choices</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;">$choice</span> <span style="color: #666699; font-weight: bold;">in</span> <span style="color: #660033; font-weight: bold;">$Script</span>:SpeechModuleMacros.<span style="color: #003366;">GetEnumerator</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Object</span></span> System.<span style="color: #003366;">Speech</span>.<span style="color: #003366;">Recognition</span>.<span style="color: #003366;">SemanticResultValue</span> <span style="color: #660033; font-weight: bold;">$choice</span>.<span style="color: #003366;">Key</span>, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$choice</span>.<span style="color: #003366;">Value</span>.<span style="color: #003366;">ToString</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span> <span style="color: #66cc66;">|</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ForEach<span style="color: #66cc66;">-</span>Object<span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$choices</span>.<span style="color: #003366;">Add</span><span style="color: #333;">&#40;</span> <span style="color: #660033; font-weight: bold;">$_</span>.<span style="color: #003366;">ToGrammarBuilder</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#41;</span> <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
<br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">if</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$VerbosePreference</span> <span style="color: #000066;">-ne</span> <span style="color: #009900;">&quot;SilentlyContinue&quot;</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$Script</span>:SpeechModuleMacros.<span style="color: #003366;">Keys</span> <span style="color: #66cc66;">|</span> <br />
&nbsp; &nbsp; &nbsp; ForEach<span style="color: #66cc66;">-</span>Object <span style="color: #333;">&#123;</span> <span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;$Computer, $_&quot;</span> <span style="color: #000066;">-Fore</span> Cyan <span style="color: #333;">&#125;</span> <span style="color: #333;">&#125;</span><br />
<br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$builder</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Object</span></span> System.<span style="color: #003366;">Speech</span>.<span style="color: #003366;">Recognition</span>.<span style="color: #003366;">GrammarBuilder</span> <span style="color: #009900;">&quot;$Computer, &quot;</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$builder</span>.<span style="color: #003366;">Append</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#40;</span><span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Object</span></span> System.<span style="color: #003366;">Speech</span>.<span style="color: #003366;">Recognition</span>.<span style="color: #003366;">SemanticResultKey</span> <span style="color: #009900;">&quot;Commands&quot;</span>, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$choices</span>.<span style="color: #003366;">ToGrammarBuilder</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$grammar</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">new-<span style="font-style: normal;">object</span></span> System.<span style="color: #003366;">Speech</span>.<span style="color: #003366;">Recognition</span>.<span style="color: #003366;">Grammar</span> <span style="color: #660033; font-weight: bold;">$builder</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$grammar</span>.<span style="color: #003366;">Name</span> <span style="color: #66cc66;">=</span> <span style="color: #009900;">&quot;Power VoiceMacros&quot;</span><br />
<br />
&nbsp; &nbsp;<span style="color: #666666; font-style: italic;">## Take note of the events, but only once (make sure to remove the old one)</span><br />
&nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Unregister-<span style="font-style: normal;">Event</span></span> <span style="color: #009900;">&quot;SpeechModuleCommandRecognized&quot;</span> <span style="color: #000066;">-ErrorAction</span> SilentlyContinue<br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$null</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">Register-<span style="font-style: normal;">ObjectEvent</span></span> <span style="color: #660033; font-weight: bold;">$grammar</span> SpeechRecognized `<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">-SourceIdentifier</span> <span style="color: #009900;">&quot;SpeechModuleCommandRecognized&quot;</span> `<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">-Action</span> <span style="color: #333;">&#123;</span> <span style="color: #660033;">iex</span> <span style="color: #660033; font-weight: bold;">$event</span>.<span style="color: #003366;">SourceEventArgs</span>.<span style="color: #003366;">Result</span>.<span style="color: #003366;">Semantics</span>.<span style="color: #003366;">Item</span><span style="color: #333;">&#40;</span><span style="color: #009900;">&quot;Commands&quot;</span><span style="color: #333;">&#41;</span>.<span style="color: #003366;">Value</span> <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$Global</span>:SpeechModuleListener.<span style="color: #003366;">UnloadAllGrammars</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$Global</span>:SpeechModuleListener.<span style="color: #003366;">LoadGrammarAsync</span><span style="color: #333;">&#40;</span> <span style="color: #660033; font-weight: bold;">$grammar</span> <span style="color: #333;">&#41;</span><br />
<span style="color: #333;">&#125;</span><br />
<br />
<span style="color: #666699; font-weight: bold;">function</span> <span style="color: #0066cc; font-style: italic;">Add-<span style="font-style: normal;">SpeechCommands</span></span> <span style="color: #333;">&#123;</span><br />
<span style="color: #666666; font-style: italic;">#.Synopsis</span><br />
<span style="color: #666666; font-style: italic;"># &nbsp;Add one or more commands to the speech-recognition macros, and update the recognition</span><br />
<span style="color: #666666; font-style: italic;">#.Parameter CommandText</span><br />
<span style="color: #666666; font-style: italic;"># &nbsp;The string key for the command to remove</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#91;</span>CmdletBinding<span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#93;</span><br />
&nbsp; &nbsp;<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;">hashtable</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$VoiceMacros</span>,<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span><span style="color: #003366; font-weight: bold;">string</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$Computer</span><span style="color: #66cc66;">=</span><span style="color: #660033; font-weight: bold;">$Script</span>:SpeechModuleComputerName<span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span style="color: #666666; font-style: italic;">## Add the new macros</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$Script</span>:SpeechModuleMacros <span style="color: #66cc66;">+=</span> <span style="color: #660033; font-weight: bold;">$VoiceMacros</span> <br />
&nbsp; &nbsp;<span style="color: #666666; font-style: italic;">## Update the default if they change it, so they only have to do that once.</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$Script</span>:SpeechModuleComputerName <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$Computer</span> <br />
&nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Update-<span style="font-style: normal;">SpeechCommands</span></span><br />
<span style="color: #333;">&#125;</span><br />
<br />
<span style="color: #666699; font-weight: bold;">function</span> <span style="color: #0066cc; font-style: italic;">Remove-<span style="font-style: normal;">SpeechCommands</span></span> <span style="color: #333;">&#123;</span><br />
<span style="color: #666666; font-style: italic;">#.Synopsis</span><br />
<span style="color: #666666; font-style: italic;"># &nbsp;Remove one or more command from the speech-recognition macros, and update the recognition</span><br />
<span style="color: #666666; font-style: italic;">#.Parameter CommandText</span><br />
<span style="color: #666666; font-style: italic;"># &nbsp;The string key for the command to remove</span><br />
&nbsp; &nbsp;<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;">string</span><span style="color: #333;">&#91;</span><span style="color: #333;">&#93;</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$CommandText</span><span style="color: #333;">&#41;</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;">$command</span> <span style="color: #666699; font-weight: bold;">in</span> <span style="color: #660033; font-weight: bold;">$CommandText</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$Script</span>:SpeechModuleMacros.<span style="color: #003366;">Remove</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$Command</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Update-<span style="font-style: normal;">SpeechCommands</span></span><br />
<span style="color: #333;">&#125;</span><br />
<br />
<span style="color: #666699; font-weight: bold;">function</span> <span style="color: #0066cc; font-style: italic;">Clear-<span style="font-style: normal;">SpeechCommands</span></span> <span style="color: #333;">&#123;</span><br />
<span style="color: #666666; font-style: italic;">#.Synopsis</span><br />
<span style="color: #666666; font-style: italic;"># &nbsp;Removes all commands from the speech-recognition macros, and update the recognition</span><br />
<span style="color: #666666; font-style: italic;">#.Parameter CommandText</span><br />
<span style="color: #666666; font-style: italic;"># &nbsp;The string key for the command to remove</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$Script</span>:SpeechModuleMacros <span style="color: #66cc66;">=</span> @<span style="color: #333;">&#123;</span><span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #666666; font-style: italic;">## Default value: A way to turn it off</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$Script</span>:SpeechModuleMacros.<span style="color: #003366;">Add</span><span style="color: #333;">&#40;</span><span style="color: #009900;">&quot;Stop Listening&quot;</span>, <span style="color: #333;">&#123;</span> <span style="color: #0066cc; font-style: italic;">Suspend-<span style="font-style: normal;">Listening</span></span> <span style="color: #333;">&#125;</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Update-<span style="font-style: normal;">SpeechCommands</span></span><br />
<span style="color: #333;">&#125;</span><br />
<br />
<br />
<span style="color: #666699; font-weight: bold;">function</span> <span style="color: #0066cc; font-style: italic;">Start-<span style="font-style: normal;">Listening</span></span> <span style="color: #333;">&#123;</span><br />
<span style="color: #666666; font-style: italic;">#.Synopsis</span><br />
<span style="color: #666666; font-style: italic;"># &nbsp;Sets the SpeechRecognizer to Enabled</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$Global</span>:SpeechModuleListener.<span style="color: #003366;">Enabled</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$true</span><br />
&nbsp; &nbsp;Say <span style="color: #009900;">&quot;Speech Macros are $($Global:SpeechModuleListener.State)&quot;</span><br />
&nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;Speech Macros are $($Global:SpeechModuleListener.State)&quot;</span><br />
<span style="color: #333;">&#125;</span><br />
<span style="color: #666699; font-weight: bold;">function</span> <span style="color: #0066cc; font-style: italic;">Suspend-<span style="font-style: normal;">Listening</span></span> <span style="color: #333;">&#123;</span><br />
<span style="color: #666666; font-style: italic;">#.Synopsis</span><br />
<span style="color: #666666; font-style: italic;"># &nbsp;Sets the SpeechRecognizer to Disabled</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$Global</span>:SpeechModuleListener.<span style="color: #003366;">Enabled</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$false</span><br />
&nbsp; &nbsp;Say <span style="color: #009900;">&quot;Speech Macros are disabled&quot;</span><br />
&nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">Write-<span style="font-style: normal;">Host</span></span> <span style="color: #009900;">&quot;Speech Macros are disabled&quot;</span><br />
<span style="color: #333;">&#125;</span><br />
<br />
<span style="color: #666699; font-weight: bold;">function</span> <span style="color: #0066cc; font-style: italic;">Out-<span style="font-style: normal;">Speech</span></span> <span style="color: #333;">&#123;</span><br />
<span style="color: #666666; font-style: italic;">#.Synopsis</span><br />
<span style="color: #666666; font-style: italic;"># &nbsp;Speaks the input object</span><br />
<span style="color: #666666; font-style: italic;">#.Description</span><br />
<span style="color: #666666; font-style: italic;"># &nbsp;Uses the default SpeechSynthesizer settings to speak the string representation of the InputObject</span><br />
<span style="color: #666666; font-style: italic;">#.Parameter InputObject</span><br />
<span style="color: #666666; font-style: italic;"># &nbsp;The object to speak </span><br />
<span style="color: #666666; font-style: italic;"># &nbsp;NOTE: this should almost always be a pre-formatted string,</span><br />
<span style="color: #666666; font-style: italic;"># &nbsp; &nbsp; &nbsp; &nbsp;most objects don't render to very speakable text.</span><br />
&nbsp; &nbsp;<span style="color: #666699; font-weight: bold;">Param</span><span style="color: #333;">&#40;</span> <span style="color: #333;">&#91;</span>Parameter<span style="color: #333;">&#40;</span>ValueFromPipeline<span style="color: #66cc66;">=</span><span style="color: #660033; font-weight: bold;">$true</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#93;</span><span style="color: #333;">&#91;</span>Alias<span style="color: #333;">&#40;</span><span style="color: #009900;">&quot;IO&quot;</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#93;</span><span style="color: #660033; font-weight: bold;">$InputObject</span> <span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$null</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$Global</span>:SpeechModuleSpeaker.<span style="color: #003366;">SpeakAsync</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$InputObject</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: #333;">&#41;</span><br />
<span style="color: #333;">&#125;</span><br />
<br />
<span style="color: #666699; font-weight: bold;">function</span> <span style="color: #0066cc; font-style: italic;">Remove-<span style="font-style: normal;">SpeechXP</span></span> <span style="color: #333;">&#123;</span><br />
<span style="color: #666666; font-style: italic;">#.Synopis</span><br />
<span style="color: #666666; font-style: italic;"># &nbsp;Dispose of the SpeechModuleListener and SpeechModuleSpeaker</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$Global</span>:SpeechModuleListener.<span style="color: #003366;">Dispose</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span>; <span style="color: #660033; font-weight: bold;">$Global</span>:SpeechModuleListener <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$null</span><br />
&nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$Global</span>:SpeechModuleSpeaker.<span style="color: #003366;">Dispose</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span>; <span style="color: #660033; font-weight: bold;">$Global</span>:SpeechModuleSpeaker <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$null</span><br />
<span style="color: #333;">&#125;</span><br />
<br />
<span style="color: #0066cc; font-style: italic;">set-<span style="font-style: normal;">alias</span></span> asc <span style="color: #0066cc; font-style: italic;">Add-<span style="font-style: normal;">SpeechCommands</span></span><br />
<span style="color: #0066cc; font-style: italic;">set-<span style="font-style: normal;">alias</span></span> rsc <span style="color: #0066cc; font-style: italic;">Remove-<span style="font-style: normal;">SpeechCommands</span></span><br />
<span style="color: #0066cc; font-style: italic;">set-<span style="font-style: normal;">alias</span></span> csc <span style="color: #0066cc; font-style: italic;">Clear-<span style="font-style: normal;">SpeechCommands</span></span><br />
<span style="color: #0066cc; font-style: italic;">set-<span style="font-style: normal;">alias</span></span> say <span style="color: #0066cc; font-style: italic;">Out-<span style="font-style: normal;">Speech</span></span><br />
<span style="color: #0066cc; font-style: italic;">set-<span style="font-style: normal;">alias</span></span> listen <span style="color: #0066cc; font-style: italic;">Start-<span style="font-style: normal;">Listener</span></span><br />
<span style="color: #0066cc; font-style: italic;">Export-<span style="font-style: normal;">ModuleMember</span></span> <span style="color: #000066;">-Function</span> <span style="color: #66cc66;">*</span> <span style="color: #000066;">-Alias</span> <span style="color: #66cc66;">*</span> <span style="color: #000066;">-Variable</span> SpeechModuleListener, SpeechModuleSpeaker</div>

	<p>There&#8217;s basically just one function you need to worry about here: <code>New-VoiceCommands</code>.  You pass it a hashtable which maps strings to scriptblocks, and if you use the <code>-Listen</code> switch that&#8217;s all there is to it.  You can also call <code>Start-Listening</code> manually, and of course, I&#8217;ve provided the <code>Say</code> function to make it easier to have the computer speak&#8230;</p>

	<p>Once the computer is &#8220;listening&#8221; ... you just say it&#8217;s name, followed by one of your commands. I like that because it ensures that I don&#8217;t run the scripts by accident, but you can remove the <code>&#34;${Env:ComputerName}, &#34;</code> string from the beginning of the GrammarBuilder if you think it&#8217;s not necessary, or you can hard code it to something other than your computer&#8217;s name, like say &#8220;Hal, please, I beg you &#8230; &#8220; or &#8220;Computer, please &#8220; or whatever.  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=':-)' class='wp-smiley' /> </p>

	<p>You can do a lot of things with this &#8230; anything, really &#8230; but to give you an example that you can easily understand, I&#8217;m going to do something very simple, and have my computer just answer a few basic questions by talking back to me, and then add a few commands to have it start an app or a web page.</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #0066cc; font-style: italic;">Add-<span style="font-style: normal;">SpeechCommands</span></span> @<span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&quot;What time is it?&quot;</span> <span style="color: #66cc66;">=</span> <span style="color: #333;">&#123;</span> Say <span style="color: #009900;">&quot;It is $(Get-Date -f &quot;</span><span style="color: #660033;">h</span>:mm tt<span style="color: #009900;">&quot;)&quot;</span> <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&quot;What day is it?&quot;</span> &nbsp;<span style="color: #66cc66;">=</span> <span style="color: #333;">&#123;</span> Say $<span style="color: #333;">&#40;</span><span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Date</span></span> <span style="color: #000066;">-f</span> <span style="color: #009900;">&quot;dddd, MMMM dd&quot;</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&quot;What's running?&quot;</span> &nbsp;<span style="color: #66cc66;">=</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #660033; font-weight: bold;">$proc</span> <span style="color: #66cc66;">=</span> <span style="color: #660033;">ps</span> <span style="color: #66cc66;">|</span> <span style="color: #660033;">sort</span> ws <span style="color: #000066;">-desc</span><br />
&nbsp; &nbsp; &nbsp; Say $<span style="color: #333;">&#40;</span><span style="color: #009900;">&quot;$($proc.Count) processes, including $($proc[0].name), which is using &quot;</span> <span style="color: #66cc66;">+</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&quot;$([int]($proc[0].ws/1mb)) megabytes of memory&quot;</span><span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span> <span style="color: #000066;">-Computer</span> <span style="color: #009900;">&quot;Laptop&quot;</span> <span style="color: #000066;">-Verbose</span> <br />
<br />
<span style="color: #0066cc; font-style: italic;">Add-<span style="font-style: normal;">SpeechCommands</span></span> @<span style="color: #333;">&#123;</span> <span style="color: #009900;">&quot;Run Notepad&quot;</span> <span style="color: #66cc66;">=</span> <span style="color: #333;">&#123;</span> <span style="color: #66cc66;">&amp;</span>amp; <span style="color: #009900;">&quot;C:\Programs\DevTools\Notepad++\notepad++.exe&quot;</span> <span style="color: #333;">&#125;</span> <span style="color: #333;">&#125;</span><br />
<span style="color: #0066cc; font-style: italic;">Add-<span style="font-style: normal;">SpeechCommands</span></span> @<span style="color: #333;">&#123;</span> <span style="color: #009900;">&quot;Check Gee Mail&quot;</span> <span style="color: #66cc66;">=</span> <span style="color: #333;">&#123;</span> <span style="color: #0066cc; font-style: italic;">Start-<span style="font-style: normal;">Process</span></span> <span style="color: #009900;">&quot;https://mail.google.com&quot;</span> <span style="color: #333;">&#125;</span> <span style="color: #333;">&#125;</span><br />
&nbsp;</div>

	<p>You see how easy that is? You can use &#8220;Say&#8221; to speak any text (although sometext will get better results than others), and you can invoke any other powershell commands, including HttpRest commands to fetch web data, or <span class="caps">WASP</span> commands for windows automation, or PowerBoots commands to display output in large text, or cmdlets to control X10 or ZWave devices &#8230; you know, anything  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=';-)' class='wp-smiley' /> </p>

<div class="zemanta-pixie"><a class="zemanta-pixie-a" href="http://reblog.zemanta.com/zemified/d6e29bc6-dd76-464f-8040-7c8d8e90b08f/" title="Reblog this post [with Zemanta]"><img class="zemanta-pixie-img" src="http://img.zemanta.com/reblog_e.png?x-id=d6e29bc6-dd76-464f-8040-7c8d8e90b08f" alt="Reblog this post [with Zemanta]" /></a><span class="zem-script more-related pretty-attribution"><script type="text/javascript" src="http://static.zemanta.com/readside/loader.js" defer="defer"></script></span></div>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/control-your-pc-with-your-voice-and-powershell/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Convert Twitter users into FriendFeed Imaginary Friends!</title>
		<link>http://huddledmasses.org/convert-twitter-users-into-friendfeed-imaginary-friends/</link>
		<comments>http://huddledmasses.org/convert-twitter-users-into-friendfeed-imaginary-friends/#comments</comments>
		<pubDate>Sat, 16 May 2009 20:15:47 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Application programming interface]]></category>
		<category><![CDATA[Automation]]></category>
		<category><![CDATA[FriendFeed]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[WatiN]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://joelbennett.net/?p=1170</guid>
		<description><![CDATA[So a lot of people seem to be taking the latest missteps by Twitter&#8217;s management (and the accompanying admission of bad design) as an opportunity to try out some alternatives. Many of them seem to be coming over to FriendFeed (which has been better than Twitter for a long time, but nevermind that) ... so [...]]]></description>
			<content:encoded><![CDATA[	<p>So a lot of people seem to be taking the <a href="http://blog.twitter.com/2009/05/whoa-feedback.html">latest missteps</a> by Twitter&#8217;s management (and <a href="http://blog.twitter.com/2009/05/replies-kerfuffle.html">the accompanying admission of bad design</a>) as an opportunity to try out some alternatives. Many of them seem to be coming over to FriendFeed (which has been better than Twitter for a long time, but nevermind that) ... so I thought I&#8217;d update and release a PowerShell 2.0 script I wrote to create <a href="http://friendfeed.com/settings/imaginary">imaginary friends</a> out of your friends that stay on Twitter.</p>

	<p>The first part of it is a WatiN script (that automates your browser) called <code>New-ImaginaryFriend</code> which takes three parameters: a name for the imaginary friend, a url for an avatar for the friend, and a HashTable&#8230;  Of course, we sort-of cheat by using the HashTable &#8230; it&#8217;s basically a bunch of key-value pairs of remote services and user names. You can use it to add twitter ID&#8217;s like <code>twitter=&#34;jsnover&#34;</code> or blogs like <code>blog=&#34;http://HuddledMasses.org/&#34;</code> etc.  You can even add multiple sources (eg: twitter + diigo, two blogs, etc) to a single new imaginary friend  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt='8)' class='wp-smiley' /> ...</p>

	<p>This script is done using WatiN because the FriendFeed <span class="caps">API</span> doesn&#8217;t support creating imaginary friends yet, and as a result it&#8217;s slow, and requires IE (and doesn&#8217;t seem to work very well with IE8 &#8212; at least, I couldn&#8217;t get it to set the avatars using IE 8 on Windows 7, so I commented out the avatar part of the next-to-last line).</p>

	<p>The other part of the script is a pair of functions: the first is <code>Get-FriendFeedFriends</code> which retrieves profile information for all your friends in a slick format that includes all their services and such &#8230; you may find other uses for this later  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=';-)' class='wp-smiley' /> , the second is <code>Get-TwitterFriends</code> &#8230; Both have an <code>-Exclude</code> parameter so you can pass it a list of people to ignore.</p>

	<p>When you put these three functions together, you can just import the FriendFeed module, and start creating friends (don&#8217;t forget <em>this</em> version of the scripts only works with IE6 or IE7 for the purpose of avatars, as WatiN can&#8217;t seem to set the file upload value in IE8 yet).</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #0066cc; font-style: italic;">Import-<span style="font-style: normal;">Module</span></span> FriendFeed<br />
<span style="color: #666666; font-style: italic;">## Get any twitter friends who aren't on friendfeed</span><br />
<span style="color: #666666; font-style: italic;">## Make sure you use FriendFeed's built in &quot;add all your twitter friends&quot; first</span><br />
<span style="color: #660033; font-weight: bold;">$twits</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">TwitterFriends</span></span> `<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">-Nickname</span> jaykul<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">-Exclude</span> $<span style="color: #333;">&#40;</span><span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">FriendFeedFriends</span></span> jaykul <span style="color: #66cc66;">|</span> <span style="color: #660033;">select</span> <span style="color: #000066;">-expand</span> twitter<span style="color: #333;">&#41;</span><br />
<br />
<span style="color: #666666; font-style: italic;">## Add them to friend feed</span><br />
<span style="color: #666699; font-weight: bold;">foreach</span><span style="color: #333;">&#40;</span><span style="color: #660033; font-weight: bold;">$twit</span> <span style="color: #666699; font-weight: bold;">in</span> <span style="color: #660033; font-weight: bold;">$twits</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">ImaginaryFriend</span></span> <span style="color: #660033; font-weight: bold;">$twit</span>.<span style="color: #003366;">name</span> @<span style="color: #333;">&#123;</span>twitter<span style="color: #66cc66;">=</span><span style="color: #660033; font-weight: bold;">$twit</span>.<span style="color: #003366;">screen_name</span><span style="color: #333;">&#125;</span> <span style="color: #660033; font-weight: bold;">$twit</span>.<span style="color: #003366;">profile_image_url</span><br />
<span style="color: #333;">&#125;</span></div>

	<p>You can <a href="/downloads/FriendFeedModule+Dependencies.zip">download all of the required modules at once</a> (<a href="/downloads/FriendFeedModule+Dependencies.7z">7z</a>), or grab the latest versions of them from PoshCode: <a href="http://poshcode.org/1110">FriendFeed</a>, <a href="http://poshcode.org/1107">HttpRest</a>, and  <a href="http://poshcode.org/1108">WatiN</a> &#8230; but if you do that, you&#8217;ll still need to get the binaries separately  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=':-/' class='wp-smiley' /> </p>

<div class="zemanta-pixie"><a class="zemanta-pixie-a" href="http://reblog.zemanta.com/zemified/2f4a4fcd-2d3b-4c5e-b812-d1c5f2b5624b/" title="Reblog this post [with Zemanta]"><img class="zemanta-pixie-img" src="http://img.zemanta.com/reblog_e.png?x-id=2f4a4fcd-2d3b-4c5e-b812-d1c5f2b5624b" alt="Reblog this post [with Zemanta]" /></a><span class="zem-script more-related pretty-attribution"><script type="text/javascript" src="http://static.zemanta.com/readside/loader.js" defer="defer"></script></span></div>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/convert-twitter-users-into-friendfeed-imaginary-friends/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Using PowerShell and WatiN (PowerWatin?)</title>
		<link>http://huddledmasses.org/using-powershell-and-watin-powerwatin/</link>
		<comments>http://huddledmasses.org/using-powershell-and-watin-powerwatin/#comments</comments>
		<pubDate>Wed, 11 Mar 2009 06:10:50 +0000</pubDate>
		<dc:creator>Joel 'Jaykul' Bennett</dc:creator>
				<category><![CDATA[Huddled]]></category>
		<category><![CDATA[Automation]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[WatiN]]></category>
		<category><![CDATA[WebDesign]]></category>
		<category><![CDATA[WebDevelopment]]></category>

		<guid isPermaLink="false">http://huddledmasses.org/?p=1111</guid>
		<description><![CDATA[This is an update to a previous article. Someone asked (on Twitter) about using WatiN from PowerShell, and pointed to this old post by Scott Hanselman saying he was having the same problems &#8230; so I wrote this to help them out: WatiN requires -STA mode Note: WatiN requires Single Threaded Apartment mode, so you [...]]]></description>
			<content:encoded><![CDATA[	<h2>This is an update to a previous article.</h2>

	<p>Someone asked (on Twitter) about using <a href="http://watin.sourceforge.net">WatiN</a> from PowerShell, and pointed to <a href="http://www.hanselman.com/blog/WATIRForNETWatiNApproaches08ReleaseAndAutomatingIEFromPowerShell.aspx">this old post by Scott Hanselman</a> saying he was having the same problems &#8230; so I wrote this to help them out:</p>

	<h5>WatiN requires -<span class="caps">STA</span> mode</h5>

	<p>Note: WatiN requires Single Threaded Apartment mode, so you need to be using PowerShell 2.0 (currently in CTP3) in order for any of this to work, and you need to pass the -<span class="caps">STA</span> parameter to PowerShell. Regardless, I thought I&#8217;d throw two tips out here:</p>

	<h3>Don&#8217;t use <code>LoadFile</code>, use <code>LoadFrom</code></h3>

	<p>I&#8217;m not 100% sure when it&#8217;s appropriate to use <strong>LoadFile</strong> in PowerShell, but I can tell you that if your assembly is in a folder with a bunch of other assemblies upon which it depends &#8230; you need to use <code>[Reflection.Assembly]::LoadFrom( $path )</code> instead &#8212; because the .net loader will be able to find the dependencies.</p>

	<h3>Generate some functions to help yourself out</h3>

	<p>It&#8217;s trivial to do code-generation in PowerShell, and WatiN is not friendly to the PowerShell syntax, so you&#8217;re going to want to generate a bunch of them.  To get you started, here&#8217;s a set of Find-* functions to let you find each type of element that WatiN recognizes and automates&#8230; by name, id, class, style &#8230; well, by any attribute, really:</p>

<span id="more-1111"></span>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #666699; font-weight: bold;">Function</span> <span style="color: #0066cc; font-style: italic;">Start-<span style="font-style: normal;">Watin</span></span> <span style="color: #333;">&#123;</span><br />
<span style="color: #666666; font-style: italic;">## CHANGE this to point to your WatiN.Core.dll</span><br />
<span style="color: #660033; font-weight: bold;">$WatinPath</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">Convert-<span style="font-style: normal;">Path</span></span> <span style="color: #333;">&#40;</span><span style="color: #0066cc; font-style: italic;">Resolve-<span style="font-style: normal;">Path</span></span> <span style="color: #009900;">&quot;$(Split-Path $Profile)\Libraries\WatiN.Core.dll&quot;</span><span style="color: #333;">&#41;</span><br />
<span style="color: #666666; font-style: italic;">## Load the assembly</span><br />
<span style="color: #660033; font-weight: bold;">$global</span>:watin <span style="color: #66cc66;">=</span> <span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>Reflection.<span style="color: #003366;">Assembly</span><span style="color: #333;">&#93;</span></span>::<span style="color: #003366;">LoadFrom</span><span style="color: #333;">&#40;</span> <span style="color: #660033; font-weight: bold;">$WatinPath</span> <span style="color: #333;">&#41;</span><br />
<span style="color: #666666; font-style: italic;">## Create an initial window (I'm creating IE, but WatiN handles Firefox too)</span><br />
<span style="color: #660033; font-weight: bold;">$global</span>:ie <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">new-<span style="font-style: normal;">object</span></span> WatiN.<span style="color: #003366;">Core</span>.<span style="color: #003366;">IE</span><span style="color: #333;">&#40;</span><span style="color: #009900;">&quot;http://www.google.com&quot;</span><span style="color: #333;">&#41;</span><br />
<span style="color: #666666; font-style: italic;">## Generate Find-Button, Find-TextField, etc:</span><br />
<span style="color: #660033; font-weight: bold;">$ie</span> <span style="color: #66cc66;">|</span> <span style="color: #0066cc; font-style: italic;">Get-<span style="font-style: normal;">Member</span></span> <span style="color: #000066;">-Type</span> Method <span style="color: #66cc66;">|</span> <br />
&nbsp; &nbsp; &nbsp; Where<span style="color: #66cc66;">-</span>Object <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #660033; font-weight: bold;">$type</span> <span style="color: #66cc66;">=</span> <span style="color: #660033; font-weight: bold;">$_</span>.<span style="color: #003366;">Definition</span>.<span style="color: #333399; font-weight: bold; font-style: italic;">Split</span><span style="color: #333;">&#40;</span><span style="color: #009900;">&quot; &quot;</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #333;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #003366; font-weight: bold;"><span style="color: #333;">&#91;</span>WatiN.<span style="color: #003366;">Core</span>.<span style="color: #003366;">Element</span><span style="color: #333;">&#93;</span></span>.<span style="color: #003366;">IsAssignableFrom</span><span style="color: #333;">&#40;</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;">type</span><span style="color: #333;">&#93;</span></span><span style="color: #660033; font-weight: bold;">$type</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span> <span style="color: #66cc66;">|</span> ForEach<span style="color: #66cc66;">-</span>Object <span style="color: #333;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0066cc; font-style: italic;">New-<span style="font-style: normal;">Item</span></span> <span style="color: #000066;">-Path</span> <span style="color: #009900;">&quot;Function:Find-$($_.Name)&quot;</span> <span style="color: #000066;">-Value</span> $<span style="color: #333;">&#40;</span> <span style="color: #660033;">iex</span> @<span style="color: #009900;">&quot;<br />
{<br />
Param(<span style="color: #000099; font-weight: bold;">`$</span>Attribute, [regex]<span style="color: #000099; font-weight: bold;">`$</span>value)<br />
<span style="color: #000099; font-weight: bold;">`$</span>ie.$($_.Name)( ([Watin.Core.Find]::By( <span style="color: #000099; font-weight: bold;">`$</span>Attribute, <span style="color: #000099; font-weight: bold;">`$</span>value)) )<br />
}<br />
&quot;</span>@ &nbsp; &nbsp; &nbsp;<span style="color: #333;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #333;">&#125;</span><br />
<span style="color: #333;">&#125;</span></div>

	<p>With just that little bit of code, I generated all of these functions:</p>

	<ul>
		<li>Find-Area</li>
		<li>Find-Button</li>
		<li>Find-CheckBox</li>
		<li>Find-Div</li>
		<li>Find-Element</li>
		<li>Find-FileUpload</li>
		<li>Find-Form</li>
		<li>Find-Image</li>
		<li>Find-Label</li>
		<li>Find-Link</li>
		<li>Find-Para</li>
		<li>Find-RadioButton</li>
		<li>Find-SelectList</li>
		<li>Find-Span</li>
		<li>Find-Table</li>
		<li>Find-TableBody</li>
		<li>Find-TableCell</li>
		<li>Find-TableRow</li>
	</ul>
	<ul>
		<li>Find-TextField</li>
	</ul>

	<p>And each function takes the name of an attribute, like say: Alt, Class, For, Id, Index, Name, Src, Style, Text, Title, Url, Value &#8230; or just &#8220;Element&#8221; ... and a regular expression to match against the value of that attribute, and finds the control(s) that match.  So for instance &#8230; since I&#8217;ve got a browser open to Google, I could trigger a search for my name by just doing:</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #0066cc; font-style: italic;">Find-<span style="font-style: normal;">TextField</span></span> Name q <span style="color: #66cc66;">|</span> <span style="color: #66cc66;">%</span> <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$_</span>.<span style="color: #003366;">TypeText</span><span style="color: #333;">&#40;</span> <span style="color: #009900;">&quot;Joel Bennett&quot;</span> <span style="color: #333;">&#41;</span> <span style="color: #333;">&#125;</span><br />
<span style="color: #0066cc; font-style: italic;">Find-<span style="font-style: normal;">Button</span></span> Name btnG <span style="color: #66cc66;">|</span> <span style="color: #66cc66;">%</span> <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$_</span>.<span style="color: #003366;">Click</span><span style="color: #333;">&#40;</span><span style="color: #333;">&#41;</span> <span style="color: #333;">&#125;</span><br />
&nbsp;</div>

	<p>Drat, the lawyer and that pottery guy still beat me out, maybe I should stop using &#8220;Jaykul&#8221; everywhere and start using my real name more &#8230;</p>

	<h2> <img src='http://huddledmasses.org/wordpress/wp-includes/' alt='[new]' class='wp-smiley' />  <em>Edit</em>: Another example</h2>

	<p>Someone asked in the comments about how to parse a table, and I thought I&#8217;d post an example, because it&#8217;s pretty cool how well PowerShell works for stuff like this.  Lets say I wanted to scan down a column in a table, and depending on the values, return a value from another column. For an example, I&#8217;ll take a table off Wikipedia which lists multi-protocol IM clients, and try to return the names of the clients which support <span class="caps">IRC</span>.</p>

	<div class="posh code posh" style="font-family:monospace;"><br />
<span style="color: #666666; font-style: italic;">## Using the function defined earlier ...</span><br />
<span style="color: #0066cc; font-style: italic;">Start-<span style="font-style: normal;">Watin</span></span><br />
<span style="color: #666666; font-style: italic;">## Now navigate to the page</span><br />
<span style="color: #660033; font-weight: bold;">$ie</span>.<span style="color: #003366;">Goto</span><span style="color: #333;">&#40;</span> <span style="color: #009900;">&quot;http://en.wikipedia.org/wiki/Multiprotocol_instant_messaging_application&quot;</span> <span style="color: #333;">&#41;</span><br />
<span style="color: #666666; font-style: italic;">## Find that first table (yeah, you just have to know the ID):</span><br />
<span style="color: #660033; font-weight: bold;">$table</span> <span style="color: #66cc66;">=</span> <span style="color: #0066cc; font-style: italic;">Find-<span style="font-style: normal;">Table</span></span> Id sortable_table_id_0<br />
<br />
<span style="color: #666666; font-style: italic;">## we COULD do this to figure out which column is the IRC column:</span><br />
<span style="color: #666666; font-style: italic;">## It's hard because there's no mapping for TH in WatiN</span><br />
<span style="color: #666666; font-style: italic;">## Personally, I think they should show up in .TableCells</span><br />
<span style="color: #666666; font-style: italic;">## -1 for the &quot;th&quot; element that's missing from TableRow[1..n].TableCells</span><br />
<span style="color: #660033; font-weight: bold;">$column</span><span style="color: #66cc66;">=-</span><span style="color: #cc66cc;">1</span>; <br />
<span style="color: #660033; font-weight: bold;">$table</span>.<span style="color: #003366;">TableRows</span><span style="color: #333;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #333;">&#93;</span>.<span style="color: #003366;">Elements</span> <span style="color: #66cc66;">|</span> Where<span style="color: #66cc66;">-</span>Object <span style="color: #333;">&#123;</span><span style="color: #660033; font-weight: bold;">$_</span>.<span style="color: #003366;">TagName</span> <span style="color: #000066;">-eq</span> <span style="color: #009900;">&quot;th&quot;</span><span style="color: #333;">&#125;</span> <span style="color: #66cc66;">|</span> <br />
&nbsp; &nbsp;ForEach<span style="color: #66cc66;">-</span>Object<span style="color: #333;">&#123;</span> <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: #003366;">Text</span> <span style="color: #000066;">-match</span> <span style="color: #009900;">&quot;IRC&quot;</span><span style="color: #333;">&#41;</span><span style="color: #333;">&#123;</span> <span style="color: #666699; font-weight: bold;">break</span> <span style="color: #333;">&#125;</span> <span style="color: #660033; font-weight: bold;">$column</span><span style="color: #66cc66;">++</span> <span style="color: #333;">&#125;</span><br />
<br />
<span style="color: #666666; font-style: italic;">## Now we loop all rows, and examine that column </span><br />
<span style="color: #666666; font-style: italic;">## If we find a &quot;Yes&quot;, print out the table header for that row:</span><br />
<span style="color: #660033; font-weight: bold;">$table</span>.<span style="color: #003366;">TableRows</span> <span style="color: #66cc66;">|</span> Where<span style="color: #66cc66;">-</span>Object <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$_</span>.<span style="color: #003366;">TableCells</span><span style="color: #333;">&#91;</span><span style="color: #660033; font-weight: bold;">$column</span><span style="color: #333;">&#93;</span> <span style="color: #000066;">-match</span> <span style="color: #009900;">&quot;Yes&quot;</span> <span style="color: #333;">&#125;</span> <span style="color: #66cc66;">|</span> <br />
&nbsp; &nbsp;ForEach<span style="color: #66cc66;">-</span>Object <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$_</span>.<span style="color: #003366;">Elements</span> <span style="color: #333;">&#125;</span> <span style="color: #66cc66;">|</span> <br />
&nbsp; &nbsp;Where<span style="color: #66cc66;">-</span>Object &nbsp; <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$_</span>.<span style="color: #003366;">TagName</span> <span style="color: #000066;">-eq</span> <span style="color: #009900;">&quot;th&quot;</span><span style="color: #333;">&#125;</span> <span style="color: #66cc66;">|</span> <br />
&nbsp; &nbsp;ForEach<span style="color: #66cc66;">-</span>Object <span style="color: #333;">&#123;</span> <span style="color: #660033; font-weight: bold;">$_</span>.<span style="color: #003366;">Text</span> <span style="color: #333;">&#125;</span><br />
&nbsp;</div>

	<p>Clearly WatiN needs to fix the missin <code>&#60;th&#62;</code> TableHeader problem, but other than that, this wasn&#8217;t too painful. Of course, it would be a lot easier if we could cast ScriptBlocks as the generic <code>Predicate&#60;T&#62;</code> that the various .Find methods accept, but if I try this, it just freezes up and never returns:</p>

	<div class="posh code posh" style="font-family:monospace;"><span style="color: #660033; font-weight: bold;">$table</span>.<span style="color: #003366;">TableRows</span><span style="color: #333;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #333;">&#93;</span>.<span style="color: #003366;">Element</span><span style="color: #333;">&#40;</span> <span style="color: #333;">&#123;</span><span style="color: #660033; font-weight: bold;">$arg</span><span style="color: #333;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #333;">&#93;</span>.<span style="color: #003366;">TagName</span> <span style="color: #000066;">-eq</span> <span style="color: #009900;">&quot;th&quot;</span><span style="color: #333;">&#125;</span> <span style="color: #333;">&#41;</span></div>

	<h3>Future Work</h3>

	<p>You could easily take this a lot further: dump those functions into a file for reusing next time (so you don&#8217;t have to regenerate them each time), and in fact, it would be relatively simple to make functions for each of the methods on each of the types we found above, so you would have a <code>Click-Button</code> function, and a <code>TypeText-TextField</code> function which could take those same search parameters (attribute and regular expression) and you could even generate appropriate parameters to take, for example, the text to type.  In fact, you could generate a whole <span class="caps">DSL</span> for yourself &#8230; <a href="http://www.codinginstinct.com/2008/11/browser-automation-dsl-using-mgrammar.html">this guy did it using MGrammar</a> &#8230; but why not PowerShell.  <img src='http://huddledmasses.org/wordpress/wp-includes/' alt=';)' class='wp-smiley' /> </p>]]></content:encoded>
			<wfw:commentRss>http://huddledmasses.org/using-powershell-and-watin-powerwatin/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>

