<?xml version='1.0' encoding='windows-1252'?><rss xmlns:atom='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' version='2.0'><channel><atom:id>tag:blogger.com,1999:blog-9291563</atom:id><lastBuildDate>Mon, 15 Feb 2010 22:23:16 +0000</lastBuildDate><title>Mr Andersson</title><description>"We act as though comfort and luxury were the chief requirements of life, when all that we need to make us happy is something to be enthusiastic about." - Einstein</description><link>http://johan.andersson.net/blog/</link><managingEditor>noreply@blogger.com (Johan Andersson)</managingEditor><generator>Blogger</generator><openSearch:totalResults>55</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-1131961406983275508</guid><pubDate>Wed, 20 Jan 2010 23:28:00 +0000</pubDate><atom:updated>2010-01-21T00:30:35.447+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>windows mobile</category><category domain='http://www.blogger.com/atom/ns#'>netcf</category><category domain='http://www.blogger.com/atom/ns#'>.net</category><category domain='http://www.blogger.com/atom/ns#'>software</category><category domain='http://www.blogger.com/atom/ns#'>ioc</category><category domain='http://www.blogger.com/atom/ns#'>remotex</category><category domain='http://www.blogger.com/atom/ns#'>scripting</category><title>Deploying applications to Windows and Windows Phones which supports dynamic modules</title><description>Many .Net applications being developed today are leveraging the greatness of dependency injection using some sort of inversion of control-container. So do we at RemoteX when we develop the product called RemoteX Applications. The product has two client applications which roughly adresses the same use cases. One is targeting desktop computers and the other one is targeting Windows Phone (you can read more &lt;a href="http://www.microsoft.com/emea/windowsmobileapps/"&gt;here&lt;/a&gt; and &lt;a href="http://www.morkeleb.com/tag/remotex/"&gt;here&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;As you can tell by the name, the product consists of several applications (or rather modules). Using frameworks like Prism or Caliburn we can, in code, easily manage each part of the product. And the deployment is taken care of using ClickOnce technology using mage.exe (the MAnifest GEnerator).&lt;br /&gt;But that's for the desktop client targeting WPF.&lt;br /&gt;&lt;br /&gt;So the big question is, how are we going mobile with this?&lt;br /&gt;&lt;br /&gt;What regards an inversion of control-container we are "almost there". We have a home-grown container in place which have been around for a while now, even though it lacks some basic features you would expect an ioc container of year MMX to have.&lt;br /&gt;Speaking of deployment to the Windows Phone&amp;nbsp;you probably know you are kind of locked to using CABinet files. If you are using the tools Microsoft brought to us, you probably also use their Device Setup projects in Visual Studio.&lt;br /&gt;They are good, but you must use Visual Studio to choose the contents of and create/build your CAB file.&lt;br /&gt;What this basically means is that we need to use devenv.exe to build each customer's customized CAB file.&lt;br /&gt;So up til now we have not had per customer customized CAB files.&lt;br /&gt;&lt;br /&gt;All I wanted was ClickOnce technology and a manifest generator for the Windows Phone. So what's the solution on that?&lt;br /&gt;Say hello to the PowerShell script New-CabWizInf.ps1:&lt;br /&gt;&lt;br /&gt;.\New-CabWizInf.ps1 -path .\myapp.inf -appName "My Application" -manufacturer "RemoteX" -fromDirectory .\MyApplication\bin\Release&lt;br /&gt;&lt;br /&gt;It works like mage.exe with its -fromDirectory switch and creates the necessary .inf-file (like an Visual Studio Device Setup project would). All needed from that point is to call CABWIZ.exe and Set-AuthenticodeSignature in PowerShell to create and sign the CAB file.&lt;br /&gt;The real power is the -fromDirectory switch which allows us to create custom CAB files on the fly.&lt;br /&gt;&lt;br /&gt;So here is a peek of what our setup package scripts now looks like:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Setup Package for Windows using ClickOnce&lt;/b&gt;&lt;br /&gt;mage -new deployment -tofile MyApp.application -fromdirectory bin\Release -name "My App" -publisher "RemoteX"&lt;br /&gt;mage -sign&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Setup Package for Windows Phones using CAB files&lt;/b&gt;&lt;br /&gt;.\New-CabWizInf.ps1 -path MyApp.inf -fromDirectory bin\Release -appName "My App" -manufacturer "RemoteX"&lt;br /&gt;cabwiz MyApp.inf /dest .\&lt;br /&gt;Set-AuthenticodeSignature .\MyApp.CAB&lt;br /&gt;&lt;br /&gt;So right now I'm a very happy camper since our packaging tools for Windows AND Windows Phone have equal capabilities which allows us to use dependency injection with dynamic module selection.&lt;br /&gt;&lt;br /&gt;Next stop, Prism and Silverlight for the Windows Phone?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-1131961406983275508?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2010/01/deploying-applications-to-windows-and.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-4352434074409188992</guid><pubDate>Thu, 19 Nov 2009 14:25:00 +0000</pubDate><atom:updated>2009-11-19T15:43:57.153+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>powershell</category><category domain='http://www.blogger.com/atom/ns#'>winrm</category><title>How to get $VerbosePreference applied on remote commands</title><description>If you use Write-Verbose in a script executed on a remote computer, you may not get the result you expect.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;Example TestRemoteCommand.ps1:&lt;/strong&gt;&lt;/div&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush:powershell"&gt;&lt;![CDATA[&lt;br /&gt;Invoke-Command -ComputerName comp1 -ScriptBlock { &lt;br /&gt;    Write-Host "hello"&lt;br /&gt;    Write-Verbose "there"&lt;br /&gt;}&lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;The above will only output "hello" and not "there" in the host window.&lt;br /&gt;&lt;br /&gt;I thought I was clever by just passing along the $VerbosePreference value:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush:powershell"&gt;&lt;![CDATA[&lt;br /&gt;Invoke-Command -ComputerName comp1 -ArgumentList $VerbosePreference -ScriptBlock { &lt;br /&gt;    param( $VerbosePreference )&lt;br /&gt;    Write-Host "hello"&lt;br /&gt;    Write-Verbose "there"&lt;br /&gt;}&lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;But, still no luck! Only the statement using Write-Host is included in the output when the command is invoked on the remote computer.&lt;br /&gt;What's going on here is that the argument sent to the remotely executed script block is converted to an integer, which is the base integral type of the underlying enum type of $VerbosePreference. &lt;br /&gt;So I figured that typing the argument in the param() clause will bind the parameter to the correct data type, and voila, it now works as expected.&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush:powershell"&gt;&lt;![CDATA[&lt;br /&gt;Invoke-Command -ComputerName comp1 -ArgumentList $VerbosePreference -ScriptBlock { &lt;br /&gt;    param( [System.Management.Automation.ActionPreference] $VerbosePreference )&lt;br /&gt;    Write-Host "hello"&lt;br /&gt;    Write-Verbose "there"&lt;br /&gt;}&lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Now you can toggle the verbose output of your remote script using the switch of your local script:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush:powershell"&gt;&lt;![CDATA[&lt;br /&gt;.\TestRemoteCommand.ps1 # Default, or -Verbose:$false&lt;br /&gt;.\TestRemoteCommand.ps1 -Verbose&lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-4352434074409188992?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/11/how-to-apply-verbosepreference-on.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-4374930585417494049</guid><pubDate>Wed, 18 Nov 2009 07:57:00 +0000</pubDate><atom:updated>2009-11-25T11:34:56.728+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>powershell</category><category domain='http://www.blogger.com/atom/ns#'>troubleshooting</category><category domain='http://www.blogger.com/atom/ns#'>winrm</category><title>Enable-PSRemoting is broken in PowerShell?</title><description>Yesterday I installed the RTM bits of WinRM 2.0 on a Windows Server 2003 machine and it were really no issues at all getting it working.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Today I tried to do the same thing but on a Windows 2008 Server (R1) that is not joined to any domain, and it fail on step 1 of the configuration.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In both cases I started out downloading the patch. Then I run "Enable-PSRemoting" in an elevated PowerShell prompt, which succeeded on the Windows 2003 Server but not on the Windows 2008 Server.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The error I got was "Access denied".&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I thought I followed&lt;a href="anshrak: New blog post: Prerelease of AppEngine SDK 1.2.8 http://www.morkeleb.com/2009/11/25/prerelease-of-appengine-sdk-1-2-8/"&gt; the troubleshooting guide for WinRM&lt;/a&gt;, but apparently there is slight difference of two different ways I found on how you set this up. You can either run "Enable-PSRemoting" or you can run "winrm qc". If I run the quick config tool using the "winrm" command everything works out just fine, but if I use "Enable-PSRemoting" I get "Access denied".&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The most mysterious part of this is that "Enable-PSRemoting" WORKED on Windows Server 2003, but not on Windows Server 2008. Strange!&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you have any clues about this, please leave me a comment!&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-4374930585417494049?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/11/enable-psremoting-is-broken-in.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-8490758263662469901</guid><pubDate>Tue, 17 Nov 2009 07:30:00 +0000</pubDate><atom:updated>2009-11-17T08:39:34.032+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>http</category><category domain='http://www.blogger.com/atom/ns#'>troubleshooting</category><category domain='http://www.blogger.com/atom/ns#'>isaserver</category><title>Note to self: If you get error code 12250 from ISA server 2006...</title><description>"Error Code: 403 Forbidden. ISA Server is configured to block HTTP requests that require authentication. (12250)"&lt;br /&gt;&lt;br /&gt;&lt;div&gt;Everything works from and to the protected networks but traffic from the external network is blocked with the error response above.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Solution: Stop using the darn "Publish web site" wizard and copy already existing stuff :)&lt;/div&gt;&lt;div&gt;-or- make sure that the "Allow client authentication over HTTP" check box is checked.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Found at the HTTP Listener properties - Authentication tab, click Advanced.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://johan.andersson.net/blog/uploaded_images/allow-client-auth-over-http-706464.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 290px; height: 320px;" src="http://johan.andersson.net/blog/uploaded_images/allow-client-auth-over-http-706462.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-8490758263662469901?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/11/note-to-self-if-you-get-error-code.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-1613868283035530042</guid><pubDate>Wed, 11 Nov 2009 23:01:00 +0000</pubDate><atom:updated>2009-11-12T00:27:53.577+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>social</category><category domain='http://www.blogger.com/atom/ns#'>codingdojo</category><category domain='http://www.blogger.com/atom/ns#'>alt.net</category><category domain='http://www.blogger.com/atom/ns#'>testing</category><category domain='http://www.blogger.com/atom/ns#'>programming</category><title>Swedish Alt.Net UG Coding Dojo at Avega, Stockholm</title><description>Yesterday I was at my very first &lt;a href="http://www.codingdojo.org/"&gt;Coding Dojo&lt;/a&gt; with my fellow collegues Morten and Sebastian. I was somewhat nervous before this event. Coding in group is not an every day occasion for me :). But it went very well and I can only concur on what &lt;a href="http://www.morkeleb.com/2009/11/11/alt-net-stockholm-coding-dojo/"&gt;Morten blogged about&lt;/a&gt;.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Adding to that I must say it were so popular that we needed to split up into two conference rooms. Each room was equipped with a projector, a decent table with room enough for about 15 people.&lt;/div&gt;&lt;div&gt;However, even though we split up into two teams (that focused on the same Kata, see link in &lt;a href="http://www.morkeleb.com/2009/11/11/alt-net-stockholm-coding-dojo/"&gt;Morten's post&lt;/a&gt;), we were just too many people around the table. I'm not sure about the exact head count but I guess we ended up with about 9 or 10 people. The most disappointing thing was that one guy was "rolling his own private solution" on his machine during the session. No hard feelings though; I believe this is a sign that we had too many participants in each group.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Worth to say is that each rotation was time limited to 4 minutes with a break of 15 seconds. That means each 4 minutes you rotate around the table and the next person takes the keyboard and continues where the last person left off. The person to the left of the person at the keyboard is the navigator in the pair.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Really nice experience and very nice and bright people in the user group! Thanks &lt;a href="http://www.avega.se"&gt;Avega&lt;/a&gt; (especially &lt;a href="http://www.joakimsunden.com"&gt;Joakim Sundén&lt;/a&gt; and his collegues) for hosting the meeting at their office here in Stockholm.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Today I couldn't resist thinking of how we could do this internally at work (we're 6 persons writing code at &lt;a href="http://www.remotex.se"&gt;RemoteX&lt;/a&gt; so it seems to be just too perfect). Oh, so much cool code to write, so little time. :)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-1613868283035530042?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/11/swedish-altnet-ug-coding-dojo-at-avega.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-885248213400247178</guid><pubDate>Wed, 11 Nov 2009 20:41:00 +0000</pubDate><atom:updated>2009-11-12T12:07:16.907+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>powershell</category><category domain='http://www.blogger.com/atom/ns#'>testing</category><category domain='http://www.blogger.com/atom/ns#'>scripting</category><title>Pimping PsUnit with constraint based assertions</title><description>Using PsUnit one can set up scripted "unit tests" for PowerShell scripts. I have sort of just started using PsUnit at work and right now I feel that a lot of the basic features of other test frameworks are missing.&lt;div&gt;PsUnit has one function for doing constraint based assertions. This may be familar to those who are using NUnit. Basically the syntax for this is:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush:powershell"&gt;&lt;![CDATA[ &lt;br /&gt;$result = DoSomething &lt;br /&gt;Assert-That $result { $ActualValue -eq "expected value" } &lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Using NUnit and this constraint based model, a simple assertion can look like this:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush:c-sharp"&gt;&lt;![CDATA[ &lt;br /&gt;Assert.That( myString, Is.EqualTo("Hello") ); &lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;I quite don't like the "barebone" scriptblock you need to write to use Assert-That in PsUnit, so here is what I came up with (using my example of above):&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush:powershell"&gt;&lt;![CDATA[ &lt;br /&gt;$result = DoSomething &lt;br /&gt;Assert-That $result (IsEqualTo "expected value")&lt;br /&gt; ]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;I also added another constraint which allows you to assert that some code throws something:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush:powershell"&gt;&lt;![CDATA[ &lt;br /&gt;# The following assertion will always pass &lt;br /&gt;Assert-That { throw "blah!" } (ThrowsException) &lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;This complements the already built-in feature of PsUnit which allows you to add a parameter, $ExpectedException, to the test. If you have been using MSTest you would use the method attribute ExpectedException for this.&lt;br /&gt;&lt;br /&gt;Here is another example which tweaks the constraint to a somewhat more specific type of exception:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush:powershell"&gt;&lt;![CDATA[&lt;br /&gt;# The following assertion will fail since throw in PowerShell creates a System.Management.Automation.ErrorRecord &lt;br /&gt;Assert-That { throw "blah!" } (ThrowsException -Exception $([System.ArgumentException])) &lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;A more usable test using the ThrowsException constraint could be:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush:powershell"&gt;&lt;![CDATA[ &lt;br /&gt;Assert-That { &lt;br /&gt;    # The following web resource does not exist, thus an error should be the result &lt;br /&gt;    Get-Http "http://blogger.com/asdfg" &lt;br /&gt;} (ThrowsException -Exception $([System.Net.WebException])) &lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;The biggest improvement using these new constraints is the output in the test result.&lt;br /&gt;While using PsUnit out-of-the-box...&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush:powershell"&gt;&lt;![CDATA[  &lt;br /&gt;$foo = "bar" &lt;br /&gt;Assert-That $foo { $ActualValue -eq "foo" }  &lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;...results with "&lt;span class="Apple-style-span"  style="color:#FF0000;"&gt;Assert-That returned false!&lt;/span&gt;" in the test result.&lt;br /&gt;Using the constraint in this blog post...:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush:powershell"&gt;&lt;![CDATA[  &lt;br /&gt;$foo = "bar" &lt;br /&gt;Assert-That $foo (IsEqualTo "foo")  &lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;...results with "&lt;span class="Apple-style-span"  style="color:#FF0000;"&gt;ActualValue 'bar' is not equal to expected value 'foo'&lt;/span&gt;".&lt;br /&gt;&lt;br /&gt;The same level of detail is provided by the ThrowsException constraint, which may result in "&lt;span class="Apple-style-span"  style="color:#FF0000;"&gt;No exception was thrown, expected exception of type 'System.ArgumentException'&lt;/span&gt;".&lt;br /&gt;&lt;br /&gt;Any ideas, suggestions etc.? Please don't hesitate to drop a comment!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-885248213400247178?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/11/pimping-psunit-with-constraint-based.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-3844540148655081493</guid><pubDate>Wed, 11 Nov 2009 19:50:00 +0000</pubDate><atom:updated>2009-11-11T23:23:41.708+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>powershell</category><category domain='http://www.blogger.com/atom/ns#'>testing</category><category domain='http://www.blogger.com/atom/ns#'>msbuild</category><category domain='http://www.blogger.com/atom/ns#'>scripting</category><title>Integrating PsUnit and MSBuild</title><description>The last month I have been digging into, adding new and refactoring the Powershell scripts we use in RemoteX Applications. We primarily use PowerShell to configure and deploy our product.&lt;div&gt;More often or too many times - with our latest releases - our fellow collegues at Customer Operations have been telling us "The xyz powershell script doesn't work anymore, what have you done to it???"&lt;/div&gt;&lt;div&gt;I could have answered: "- We don't have automated tests on those scripts, so what do you expect? Manual testing? Pfffff...", but for obvious reasons I didn't :).&lt;/div&gt;&lt;div&gt;So it was time to add some automated tests for those scripts so I could get this guy at Customer Operations back to work.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;All compiled code (C#) is automatically tested in our Continuous Integration builds when someone checks in, but until now we haven't had automated tests for our PowerShell scripts. With "automated" I mean that a test runner executes a test suite during a build.&lt;/div&gt;&lt;div&gt;In order to test our PowerShell scripts I have started using PsUnit. Since we are using Team Foundation Server and MSBuild for our CI builds, I needed to integrate PsUnit with MSBuild somehow.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There are several ways to invoke Powershell from an MSBuild script - we have chosen the Exec task which invokes powershell.exe.&lt;/div&gt;&lt;div&gt;First of all I created a separate build target which invokes PsUnit:&lt;/div&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush:xml"&gt;&lt;![CDATA[&lt;br /&gt;&amp;lt;PropertyGroup&amp;gt;&lt;br /&gt; &amp;lt;CoreTestDependsOn&amp;gt;$(CoreTestDependsOn);RunPsUnit&amp;lt;/CoreTestDependsOn&amp;gt;&lt;br /&gt; &amp;lt;RunPsUnitDependsOn&amp;gt;CoreRunPsUnit&amp;lt;/RunPsUnitDependsOn&amp;gt;&lt;br /&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;Target Name="RunPsUnit" DependsOnTargets="$(RunPsUnitDependsOn)"/&amp;gt;&lt;br /&gt;&amp;lt;Target Name="CoreRunPsUnit" Condition=" '$(RunTest)'!='false' "&amp;gt;&lt;br /&gt; &amp;lt;Exec Command="$(PowerShell) -Command &amp;amp;quot;&amp;amp;amp;{ .\runpsunit.ps1 -PsUnitTestFile %(PsUnitTest.FullPath) }&amp;amp;quot;"/&amp;gt;&lt;br /&gt;&amp;lt;/Target&amp;gt;&lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;Using this batch target, all that needs to be done is to add PsUnitTest items to the build script. Just like the way we set up TestContainer items for use with MSTest:&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush:xml"&gt;&lt;![CDATA[&lt;br /&gt;&amp;lt;ItemGroup&amp;gt;&lt;br /&gt; &amp;lt;PsUnitTest Include="$(SolutionRoot)\Scripts\Tests\*.Test.ps1"/&amp;gt;&lt;br /&gt; &amp;lt;PsUnitTest Include="$(SolutionRoot)\References\PsUnit\*.Test.ps1"/&amp;gt;&lt;br /&gt;&amp;lt;/ItemGroup&amp;gt;&lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;So far so good, but when tests are failing, the build is successful. This is because the Exec task only reports a build error when the executed command returns an exit code other than zero (0x0). So I started looking into the test runner of PsUnit (PsUnit.Run.ps1) and discovered that it didn't send any output nor produced some other exit code than 0x0. The only output PsUnit will send you is some nice colorful information written to the PowerShell host.&lt;div&gt;So I ended up with the following: &lt;/div&gt;&lt;div&gt;1. this tiny tweak at the end of PsUnit.Run.ps1:&lt;/div&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush:powershell"&gt;&lt;![CDATA[&lt;br /&gt;$TestResults&lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;This makes PsUnit.Run.ps1 send the test results along the pipeline.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;2. A small wrapper for the test runner which returns some exit code other than 0x0 to the Exec task in MSBuild:&lt;/div&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush:powershell"&gt;&lt;![CDATA[&lt;br /&gt;$results = Invoke-Expression "$psUnitRun -PsUnitTestFile $PsUnitTestFile"&lt;br /&gt;$results | % {&lt;br /&gt; if( $_.Result -eq "FAIL" ) {&lt;br /&gt;  throw "Test run failed: $($_.Test) - $($_.Reason)"&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;This makes the Exec task report a build error if we find any failing test in the test result from PsUnit - and last but not least - the name of the failing test and the reason ends up nicely in the MSBuild log file. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So now when somebody checks in a change to compiled code, which affects the result of our setup scripts, we will be able to detect errors ASAP! Yay!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-3844540148655081493?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/11/integrating-psunit-and-msbuild.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-4549018572838277427</guid><pubDate>Mon, 09 Nov 2009 16:01:00 +0000</pubDate><atom:updated>2009-11-09T17:03:24.363+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>powershell</category><title>Yay, PowerShell v2 is finally RTMed!</title><description>PowerShell v2 is finally RTMed for the rest of us who still has a couple of boxes not running Windows 2008 Server R2 or Windows 7.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://support.microsoft.com/default.aspx/kb/968929"&gt;Downloads and info for Windows Server 2003, Windows Server 2008 (R1), Windows Vista and Windows XP&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-4549018572838277427?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/11/yay-powershell-v2-is-finally-rtmed.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-3537015750755239600</guid><pubDate>Sat, 31 Oct 2009 18:52:00 +0000</pubDate><atom:updated>2009-10-31T20:36:07.836+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>chicken</category><category domain='http://www.blogger.com/atom/ns#'>cooking</category><category domain='http://www.blogger.com/atom/ns#'>food</category><title>Timjankyckling med rotsakspytt</title><description>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://johan.andersson.net/blog/uploaded_images/IMAGE_255-730991.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 240px; height: 320px;" src="http://johan.andersson.net/blog/uploaded_images/IMAGE_255-730736.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;Mor och far brukar göra en grymt god rotsakspytt som passar bra på hösten. Jag kör en repris av kyckling och parmigiano-reggiano som en avslutning på höstlovet/vecka som gräsänkling.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;PS. Det är inte utan viss längtan efter den beställda HTC HD2 luren man publicerar detta. Bilderna tagna med min HTC Tytn II är verkligen hur suddiga som helst. DS.&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;b&gt;Ingredienser&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Kycklingfiléer&lt;/li&gt;&lt;li&gt;Potatis&lt;/li&gt;&lt;li&gt;Kålrot&lt;/li&gt;&lt;li&gt;Vitkål&lt;/li&gt;&lt;li&gt;Morötter&lt;/li&gt;&lt;li&gt;Lök (gärna purjolök och charlottenlök)&lt;/li&gt;&lt;li&gt;Ost (gärna med lite smak)&lt;/li&gt;&lt;li&gt;Timjan&lt;/li&gt;&lt;li&gt;Paprika(krydda)&lt;/li&gt;&lt;li&gt;Peppar&lt;/li&gt;&lt;li&gt;Smör, olja&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Lägg kycklingfiléerna i en ugnssäker oljad form. Krydda med paprika, timjan och peppar. Sätt in i förvärmd ugn på 175 grader i c:a 60 minuter. Tärna upp potatisen i lagom små delar. Värm en stekpanna med smör i. Lägg i potatisen. Hacka löken och tillsätt i pannan när potatisen har hunnit gotta till sig lite i smöret. Tärna upp/hacka kålroten, morötterna och vitkålen och lägg i pannan. Låt stå och puttra med lock ett tag. Tillsätt mer smör vid behov. Riv osten och tillsätt när kycklingen har c:a 15 min kvar. Ät och njut! &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-3537015750755239600?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/10/timjankyckling-med-rotsakspytt.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-3458714680612080402</guid><pubDate>Thu, 29 Oct 2009 14:54:00 +0000</pubDate><atom:updated>2009-10-29T16:19:12.261+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>powershell</category><category domain='http://www.blogger.com/atom/ns#'>scripting</category><title>PowerTip of the day - Variable descriptions</title><description>I just got this in my inbox from &lt;a href="http://www.powershell.com/"&gt;Powershell.com&lt;/a&gt;:&lt;br /&gt;&lt;span&gt;&lt;strong&gt;Add Descriptions to Variables&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Keeping track of a variable’s purpose can be accomplished by assigning a clear text description:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: c-sharp"&gt;&lt;br /&gt;$ip= '10.10.10.10'&lt;br /&gt;&lt;br /&gt;Set-Variable ip -description 'Server IP or Name'&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;When you now list your variables, you can output the variable description as well:&lt;br /&gt;&lt;pre class="brush: c-sharp"&gt;&lt;br /&gt;dir variable:ip | Format-Table Name, Value, Description&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Playing around a little I found out that you easily can get the same information about system/environment variables using Get-Variable and Format-Table:&lt;br /&gt;&lt;pre style="background-color: navy; color: silver; font-weight: bold"&gt;&lt;br /&gt;PS &amp;gt; gv | ft Name, Description&lt;br /&gt;&lt;br /&gt;Name                                    Description&lt;br /&gt;----                                    -----------&lt;br /&gt;$&lt;br /&gt;?                                       Execution status of last command.&lt;br /&gt;^&lt;br /&gt;_&lt;br /&gt;args&lt;br /&gt;bla                                     Bla bla bla&lt;br /&gt;ConfirmPreference                       Dictates when confirmation should be...&lt;br /&gt;ConsoleFileName                         Name of the current console file.&lt;br /&gt;DebugPreference                         Dictates action taken when an Debug ...&lt;br /&gt;Error&lt;br /&gt;ErrorActionPreference                   Dictates action taken when an Error ...&lt;br /&gt;ErrorView                               Dictates the view mode to use when d...&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-3458714680612080402?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/10/powertip-of-day-variable-descriptions.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-3278779275263095723</guid><pubDate>Wed, 28 Oct 2009 19:34:00 +0000</pubDate><atom:updated>2009-10-28T21:56:51.037+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>castle</category><category domain='http://www.blogger.com/atom/ns#'>.net</category><category domain='http://www.blogger.com/atom/ns#'>ioc</category><category domain='http://www.blogger.com/atom/ns#'>testing</category><category domain='http://www.blogger.com/atom/ns#'>programming</category><category domain='http://www.blogger.com/atom/ns#'>c#</category><title>Switching component implementations in Castle Windsor</title><description>&lt;b&gt;Problem:&lt;/b&gt; Test suite for a system for which I need to replace (inject) the behavior of a certain component. The system is using Castle Windsor with an XML configuration file.&lt;div&gt;In this system integration test I want to use the real container configuration except that I want to switch out a component that does authorization using a database.&lt;br /&gt;&lt;br /&gt;The replacement for the real component is as simple as:&lt;br /&gt;&lt;pre class="brush: c-sharp"&gt;&lt;br /&gt;public bool IUsernamePasswordVerifier.VerifyPasswordFor( string username, string password )&lt;br /&gt;{&lt;br /&gt;    return true;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;  &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Solution:&lt;/b&gt; Tried &lt;a href="http://stackoverflow.com/questions/658344/how-to-overwrite-a-component-with-castle-windsor"&gt;this&lt;/a&gt;, which failed on me. But with a little help from a tiny facility used by the test suite I can now "re-wire" service implementations in the container.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There are probably several other solutions on how one could accomplish the same thing, but this one worked out very well for me.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;ComponentRewriterFacility.cs:&lt;br /&gt;&lt;pre class="brush: c-sharp"&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using Castle.Core;&lt;br /&gt;using Castle.Core.Configuration;&lt;br /&gt;using Castle.MicroKernel;&lt;br /&gt;&lt;br /&gt;namespace ServiceTests.Service&lt;br /&gt;{&lt;br /&gt;    public class ComponentRewriteFacility : IFacility&lt;br /&gt;    {&lt;br /&gt;        readonly IDictionary&amp;lt;Type, Type&amp;gt; _rewrites;&lt;br /&gt;&lt;br /&gt;        public ComponentRewriteFacility()&lt;br /&gt;        {&lt;br /&gt;            _rewrites = new Dictionary&amp;lt;Type, Type&amp;gt;();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void AddRewrite&amp;lt;I, T&amp;gt;() where T : I&lt;br /&gt;        {&lt;br /&gt;            _rewrites.Add( typeof(I), typeof(T) );&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public virtual void Init( IKernel kernel, IConfiguration facilityConfig )&lt;br /&gt;        {&lt;br /&gt;            if( kernel == null )&lt;br /&gt;                throw new ArgumentNullException( "kernel" );&lt;br /&gt;            kernel.ComponentRegistered += ComponentRegistered;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void Terminate()&lt;br /&gt;        {&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        void ComponentRegistered( string key, IHandler handler )&lt;br /&gt;        {&lt;br /&gt;            if( !ShouldRewrite( handler.ComponentModel ) )&lt;br /&gt;                return;&lt;br /&gt;            handler.ComponentModel.Implementation = _rewrites[handler.ComponentModel.Service];&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        protected virtual bool ShouldRewrite( ComponentModel componentModel )&lt;br /&gt;        {&lt;br /&gt;            return _rewrites.ContainsKey( componentModel.Service );&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/i,&gt;&lt;/type,&gt;&lt;/type,type&gt;&lt;/pre&gt;&lt;/div&gt;And in our test suite initializer we add the "re-write rule" like this:&lt;br /&gt;&lt;pre class="brush: c-sharp"&gt;&lt;br /&gt;IWindsorContainer container = new WindsorContainer();&lt;br /&gt;container.AddFacility&amp;lt;ComponentRewriteFacility&amp;gt;( f =&gt; f.AddRewrite&amp;lt;IUsernamePasswordVerifier, AnythingGoesUsernamePasswordVerifier&amp;gt;() );&lt;br /&gt;container.AddFacility&amp;lt;WcfFacility&amp;gt;();&lt;br /&gt;container.Install( Castle.Windsor.Installer.Configuration.FromXmlFile( "Windsor.xml" ) );&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;Like it? Not? Have a better solution? Please let me know!&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-3278779275263095723?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/10/switching-component-implementations-in.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-7728241151914464137</guid><pubDate>Wed, 28 Oct 2009 18:56:00 +0000</pubDate><atom:updated>2009-10-28T20:31:49.419+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>italia</category><category domain='http://www.blogger.com/atom/ns#'>hot</category><category domain='http://www.blogger.com/atom/ns#'>chicken</category><category domain='http://www.blogger.com/atom/ns#'>pasta</category><category domain='http://www.blogger.com/atom/ns#'>food</category><title>Het pastapanna (swedish)</title><description>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://johan.andersson.net/blog/uploaded_images/IMAGE_253-713724.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 240px; height: 320px;" src="http://johan.andersson.net/blog/uploaded_images/IMAGE_253-713456.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;Mitt enkla hopkok till gräsänklingsmiddag @ 2009-10-28, en het pastapanna med inspirerad av luncherna på &lt;a href="http://www.tuttoitalia.se/"&gt;Tutto Italia&lt;/a&gt; i Sickla. De brukar ha en gör-go salamitallrik som det är rätt bra fart i. Då salamin flaggade med sin frånvaro idag fick sambalburken hoppa in som ersättare.  &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="text-decoration: underline;"&gt;Ingredienser&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Ekologisk Gnocchi (ICA)&lt;/li&gt;&lt;li&gt;Kycklingfilé&lt;/li&gt;&lt;li&gt;500 g krossade tomater med vitlök (ICA)&lt;/li&gt;&lt;li&gt;Ett gäng soltorkade tomater i olivolja&lt;/li&gt;&lt;li&gt;1 dl blandade ekologiska oliver (ICA)&lt;/li&gt;&lt;li&gt;Svartpeppar&lt;/li&gt;&lt;li&gt;Sambal&lt;/li&gt;&lt;li&gt;Ekologisk buljong utan jäst och socker (Biofood)&lt;/li&gt;&lt;li&gt;Ekologisk italiensk olivolja (Coop, Änglamark)&lt;/li&gt;&lt;li&gt;Parmigiano-Reggiano&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Koka pastan. Tärna upp kycklingen och bryn i smör i en stekpanna. När den är genomstekt tillsätter du de krossade tomaterna, buljong och peppar. Dela de soltorkade tomaterna i två delar och lägg i pannan. Tillsätt sambal efter eget tycke. Låt reduceras något. Tillsätt oliver och olivolja och låt puttra i 5 min. Riv en rejäl dos parmigiano-reggiano över vid servering. Ät och njut!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.ica.se/FrontServlet?s=butiker&amp;amp;state=butiker_dynamic&amp;amp;viewid=1386333"&gt;ICA Eco&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.biofood.se/Produkter.html"&gt;Biofood&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.coop.se/includefiles/MODULER/CCMS/show_page.asp?iMappeID=254&amp;amp;sSideNavn=%C4nglamark+-+Smaks%E4ttare+och+konserver"&gt;Coop Änglamark&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-7728241151914464137?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/10/het-pastapanna-swedish.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-3113278431275275473</guid><pubDate>Wed, 21 Oct 2009 12:57:00 +0000</pubDate><atom:updated>2009-10-21T18:02:31.013+02:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>powershell</category><category domain='http://www.blogger.com/atom/ns#'>programming</category><category domain='http://www.blogger.com/atom/ns#'>scripting</category><title>PowerShell Scripting Guidelines</title><description>Lately I have been doing some work related to how we automate the process of how we install, configure and deploy our product into a server environment. Since our pre-requisites are Windows Server 2008 and Windows 7, we can totally go crazy with PowerShell scripts. Next thing to sort out after upgrading to Windows Server 2008 R2 is of course PowerShell Remoting.. :)&lt;br /&gt;&lt;br /&gt;However, using quite an amount of PowerShell scripts, we need some guidelines to structure them. This to complement our guidelines covering OO design and C# code style.&lt;br /&gt;&lt;br /&gt;So I have started out with the following draft and I'm looking for some tips and comments about this and what you (yes, you!) believe is a good rule of thumb to use when developing and maintaining a bunch of PowerShell scripts.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(Sorry for the ugly formatting. Code was pasted from PowerGUI to a word doc and then to blogger :))&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;h1&gt;&lt;span lang="EN-US"  style="mso-fareast-font-family:Cambria; mso-fareast-theme-font:major-latin;mso-bidi-mso-bidi-theme-font: major-latin;mso-ansi-language:EN-USfont-family:Cambria;"&gt;&lt;span style="mso-list:Ignore"&gt;1&lt;span style="font:7.0pt &amp;quot;Times New Roman&amp;quot;"&gt;         &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Scripting Guidelines&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/h1&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;When there is a need of a script, use your mighty PowerShell skills!&lt;br /&gt;Here is a couple of guidelines which should be followed to speed up development, maintenance and usage of PowerShell scripts.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Apply the above mentioned principles when applicable.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;h2&gt;&lt;span lang="EN-US"  style="mso-fareast-font-family:Cambria; mso-fareast-theme-font:major-latin;mso-bidi-mso-bidi-theme-font: major-latin;mso-ansi-language:EN-USfont-family:Cambria;"&gt;&lt;span style="mso-list:Ignore"&gt;1.1&lt;span style="font:7.0pt &amp;quot;Times New Roman&amp;quot;"&gt;       &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Function files&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/h2&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Package common functions into function files and dot-source them in the script which needs them.&lt;br /&gt;Example:&lt;br /&gt;&lt;/span&gt;&lt;span lang="EN-US"   style="font-size:9.0pt;mso-bidi- line-height:115%;mso-ansi-language:EN-USfont-family:Consolas;font-size:11.0pt;"&gt;. ..\DB\Common.ps1&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;h2&gt;&lt;span lang="EN-US"  style="mso-fareast-font-family:Cambria; mso-fareast-theme-font:major-latin;mso-bidi-mso-bidi-theme-font: major-latin;mso-ansi-language:EN-USfont-family:Cambria;"&gt;&lt;span style="mso-list:Ignore"&gt;1.2&lt;span style="font:7.0pt &amp;quot;Times New Roman&amp;quot;"&gt;       &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;File names&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/h2&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Name PS1 files using standard verbs like get, set, remove, new etc., or a verb that fits the purpose or the script. Do not use verbs in file names for files that have generic purpose, like a function library file. Also consider using PowerShell v2 modules when applicable.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Scripts that are to be called from the prompt are easier to understand if they are named in such way that no “usage” or get-help is needed when invoking the script. Like add-user.ps1, remove-database.ps1 and so on.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Avoid complex scripts with multiple purposes which becomes complex with parameter sets (get-help about_functions_advanced_parameters)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;h2&gt;&lt;span lang="EN-US"  style="mso-fareast-font-family:Cambria; mso-fareast-theme-font:major-latin;mso-bidi-mso-bidi-theme-font: major-latin;mso-ansi-language:EN-USfont-family:Cambria;"&gt;&lt;span style="mso-list:Ignore"&gt;1.3&lt;span style="font:7.0pt &amp;quot;Times New Roman&amp;quot;"&gt;       &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Script and function parameters&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/h2&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Use built-in support to handle function and script parameters. Avoid index-based unnamed parameters using $args.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Reference: get-help about_arguments; get-help about_functions; get-help about_functions_advanced_parameters&lt;br /&gt;MSDN: &lt;/span&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms714433(VS.85).aspx"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;http://msdn.microsoft.com/en-us/library/ms714433(VS.85).aspx&lt;/span&gt;&lt;/a&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Example, testme.ps1:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:blue;"&gt;param&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;&lt;span style="mso-tab-count:1"&gt;            &lt;/span&gt;[&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:teal;"&gt;Switch&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;] &lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:purple;"&gt;$ver&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt; &lt;/span&gt;&lt;span lang="EN-US"    style="font-size: 9.0pt;mso-bidi-mso-ansi-language: EN-USfont-family:Consolas;font-size:10.0pt;color:red;"&gt;=&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt; [&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:teal;"&gt;Switch&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;]::&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:saddlebrown;"&gt;Present&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;b&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:cadetblue;"&gt;Write-Host&lt;/span&gt;&lt;/b&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt; &lt;/span&gt;&lt;span lang="EN-US"    style="font-size: 9.0pt;mso-bidi-mso-ansi-language: EN-USfont-family:Consolas;font-size:10.0pt;color:navy;"&gt;$args&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;&lt;span style="mso-tab-count:1"&gt;         &lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;b&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:cadetblue;"&gt;Write-Host&lt;/span&gt;&lt;/b&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt; &lt;/span&gt;&lt;span lang="EN-US"    style="font-size: 9.0pt;mso-bidi-mso-ansi-language: EN-USfont-family:Consolas;font-size:10.0pt;color:maroon;"&gt;"Testing!"&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt; mso-bidi-mso-ansi-language: EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:blue;"&gt;if&lt;/span&gt;&lt;span lang="EN-US"    style="font-size: 9.0pt;mso-bidi-mso-ansi-language: EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;( &lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:purple;"&gt;$ver&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt; ) &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;&lt;span style="mso-tab-count:1"&gt;            &lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:cadetblue;"&gt;Write-Host&lt;/span&gt;&lt;/b&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt; &lt;/span&gt;&lt;span lang="EN-US"    style="font-size: 9.0pt;mso-bidi-mso-ansi-language: EN-USfont-family:Consolas;font-size:10.0pt;color:maroon;"&gt;"Testing even more!"&lt;/span&gt;&lt;span lang="EN-US"    style="font-size: 9.0pt;mso-bidi-mso-ansi-language: EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-line-height:115%;mso-ansi-language: EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Output:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"   style="font-size:8.0pt;mso-bidi-line-height:115%;Lucida Console&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:11.0pt;"&gt;PS &gt; .\testme.ps1 –ver&lt;br /&gt;PS &gt; .\testme.ps1 -ver:$false&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span lang="EN-US"  style="Lucida Console&amp;quot;; mso-ansi-language:EN-USfont-family:&amp;quot;;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;h2&gt;&lt;span lang="EN-US"  style="mso-fareast-font-family:Cambria; mso-fareast-theme-font:major-latin;mso-bidi-mso-bidi-theme-font: major-latin;mso-ansi-language:EN-USfont-family:Cambria;"&gt;&lt;span style="mso-list:Ignore"&gt;1.4&lt;span style="font:7.0pt &amp;quot;Times New Roman&amp;quot;"&gt;       &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Decorate function parameters appropriately using validation rules&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/h2&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Decorate your parameters with validation rules and help messages to avoid tedious work on custom “script usage” functions. Your script users will be able to use “&lt;/span&gt;&lt;span lang="EN-US"   style="font-size:8.0pt;mso-bidi-line-height:115%; Lucida Console&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:11.0pt;"&gt;get-help yourscript.ps1&lt;/span&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;”, or the equivalent “&lt;/span&gt;&lt;span lang="EN-US"   style="font-size:8.0pt;mso-bidi-line-height:115%; Lucida Console&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:11.0pt;"&gt;yourscript.ps1 -?&lt;/span&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;” to get script usage information. Users will also be prompted if mandatory parameters are left out blank.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Get-help will also print out common parameters (get-help about_commonparameters).&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Example: &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:blue;"&gt;param&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt;&lt;span style="mso-tab-count:1"&gt;            &lt;/span&gt;[&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:teal;"&gt;Switch&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt;] &lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:purple;"&gt;$ver&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt; &lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:red;"&gt;=&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt; [&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:teal;"&gt;Switch&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt;]::&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:saddlebrown;"&gt;Present&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt;,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt;&lt;span style="mso-tab-count:1"&gt;            &lt;/span&gt;[Parameter(mandatory&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:red;"&gt;=&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:blue;"&gt;$true&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt;, helpmessage&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;;mso-bidi-Courier New&amp;quot;; mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:red;"&gt;=&lt;/span&gt;&lt;span lang="EN-US"    style="font-size: 9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;;mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:maroon;"&gt;"Your name"&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt;)]&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt;&lt;span style="mso-tab-count:1"&gt;            &lt;/span&gt;[ValidateNotNullOrEmpty()]&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt;&lt;span style="mso-tab-count:1"&gt;            &lt;/span&gt;[&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:teal;"&gt;string&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt;] &lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:purple;"&gt;$name&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt; &lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:red;"&gt;=&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt; &lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:maroon;"&gt;"John Doe"&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;;mso-bidi-Courier New&amp;quot;; mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;b&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:cadetblue;"&gt;Write-Host&lt;/span&gt;&lt;/b&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt; &lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:navy;"&gt;$args&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt;&lt;span style="mso-tab-count:1"&gt;       &lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;b&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:cadetblue;"&gt;Write-Host&lt;/span&gt;&lt;/b&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt; &lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:maroon;"&gt;"Hello $name!"&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;;mso-bidi-Courier New&amp;quot;; mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:blue;"&gt;if&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt;( &lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:purple;"&gt;$ver&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt; ) &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt;&lt;span style="mso-tab-count:1"&gt;            &lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:cadetblue;"&gt;Write-Host&lt;/span&gt;&lt;/b&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt; &lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:maroon;"&gt;"Your name is $($name.Length) characters long"&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-font-family:&amp;quot;Lucida Console&amp;quot;; mso-bidi-Courier New&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:10.0pt;color:black;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-size:9.0pt;mso-bidi- line-height:115%;font-family:&amp;quot;Lucida Console&amp;quot;;mso-bidi-Courier New&amp;quot;; font-family:&amp;quot;;font-size:10.0pt;color:black;"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Output:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"   style="font-size:8.0pt;mso-bidi-line-height:115%;Lucida Console&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:11.0pt;"&gt;PS &gt; get-help .\testme.ps1&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"   style="font-size:8.0pt;mso-bidi-line-height:115%;Lucida Console&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:11.0pt;"&gt;testme.ps1 [-name] &lt;string&gt; [-ver] [-Verbose] [-Debug] [-ErrorAction &lt;actionpreference&gt;] [-WarningAction &lt;actionpreference&gt;] [-ErrorVariable &lt;string&gt;] [-WarningVariable &lt;string&gt;] [-OutVariable &lt;string&gt;] [-OutBuffer &lt;int32&gt;]&lt;o:p&gt;&lt;/o:p&gt;&lt;/int32&gt;&lt;/string&gt;&lt;/string&gt;&lt;/string&gt;&lt;/actionpreference&gt;&lt;/actionpreference&gt;&lt;/string&gt;&lt;/span&gt;&lt;/p&gt;  &lt;h2&gt;&lt;span lang="EN-US"  style="mso-fareast-font-family:Cambria; mso-fareast-theme-font:major-latin;mso-bidi-mso-bidi-theme-font: major-latin;mso-ansi-language:EN-USfont-family:Cambria;"&gt;&lt;span style="mso-list:Ignore"&gt;1.5&lt;span style="font:7.0pt &amp;quot;Times New Roman&amp;quot;"&gt;       &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Document script usage using PowerShell comment based help&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/h2&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;When it is necessary to document how a script can be used, or when you want to provide more information about your script’s parameters than just the name, document it using the PowerShell help syntax. This can be compared to using XML comments in languages such as C#/VB or javadoc tags in Java.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;See “get-help about_comment_based_help” for more information.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Example:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;&lt;&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:green;"&gt;#&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;.Synopsis&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;&lt;span style="mso-tab-count:1"&gt;            &lt;/span&gt;Synopsis text here&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;.Description&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;&lt;span style="mso-tab-count:1"&gt;            &lt;/span&gt;Usage description here&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;.Parameter ver&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;&lt;span style="mso-tab-count:1"&gt;            &lt;/span&gt;Enabling this &lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:blue;"&gt;switch&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt; prints out the length of the given name&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;.Parameter name&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;&lt;span style="mso-tab-count:1"&gt;            &lt;/span&gt;The name to say hello to&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:green;"&gt;#&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:blue;"&gt;param&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;&lt;span style="mso-tab-count:1"&gt;            &lt;/span&gt;[&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:teal;"&gt;Switch&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;] &lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:purple;"&gt;$ver&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt; &lt;/span&gt;&lt;span lang="EN-US"    style="font-size: 9.0pt;mso-bidi-mso-ansi-language: EN-USfont-family:Consolas;font-size:10.0pt;color:red;"&gt;=&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt; [&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:teal;"&gt;Switch&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;]::&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:saddlebrown;"&gt;Present&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;&lt;span style="mso-tab-count:1"&gt;            &lt;/span&gt;[Parameter(mandatory&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:red;"&gt;=&lt;/span&gt;&lt;span lang="EN-US"    style="font-size: 9.0pt;mso-bidi-mso-ansi-language: EN-USfont-family:Consolas;font-size:10.0pt;color:blue;"&gt;$true&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;, helpmessage&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:red;"&gt;=&lt;/span&gt;&lt;span lang="EN-US"    style="font-size: 9.0pt;mso-bidi-mso-ansi-language: EN-USfont-family:Consolas;font-size:10.0pt;color:maroon;"&gt;"Your name"&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt; mso-bidi-mso-ansi-language: EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;)]&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;&lt;span style="mso-tab-count:1"&gt;            &lt;/span&gt;[ValidateNotNullOrEmpty()]&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;&lt;span style="mso-tab-count:1"&gt;            &lt;/span&gt;[&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:teal;"&gt;string&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;] &lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:purple;"&gt;$name&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt; &lt;/span&gt;&lt;span lang="EN-US"    style="font-size: 9.0pt;mso-bidi-mso-ansi-language: EN-USfont-family:Consolas;font-size:10.0pt;color:red;"&gt;=&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt; &lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:maroon;"&gt;"John Doe"&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;b&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:cadetblue;"&gt;Write-Host&lt;/span&gt;&lt;/b&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt; &lt;/span&gt;&lt;span lang="EN-US"    style="font-size: 9.0pt;mso-bidi-mso-ansi-language: EN-USfont-family:Consolas;font-size:10.0pt;color:navy;"&gt;$args&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;&lt;span style="mso-tab-count:1"&gt;         &lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;b&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:cadetblue;"&gt;Write-Host&lt;/span&gt;&lt;/b&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt; &lt;/span&gt;&lt;span lang="EN-US"    style="font-size: 9.0pt;mso-bidi-mso-ansi-language: EN-USfont-family:Consolas;font-size:10.0pt;color:maroon;"&gt;"Hello $name!"&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt; mso-bidi-mso-ansi-language: EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:blue;"&gt;if&lt;/span&gt;&lt;span lang="EN-US"    style="font-size: 9.0pt;mso-bidi-mso-ansi-language: EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;( &lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:purple;"&gt;$ver&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt; ) &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin-bottom:0cm;margin-bottom:.0001pt;line-height: normal;mso-layout-grid-align:none;text-autospace:none"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;&lt;span style="mso-tab-count:1"&gt;            &lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:cadetblue;"&gt;Write-Host&lt;/span&gt;&lt;/b&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt; &lt;/span&gt;&lt;span lang="EN-US"    style="font-size: 9.0pt;mso-bidi-mso-ansi-language: EN-USfont-family:Consolas;font-size:10.0pt;color:maroon;"&gt;"Your name is $($name.Length) characters long"&lt;/span&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi- mso-ansi-language:EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"    style="font-size:9.0pt;mso-bidi-line-height:115%;mso-ansi-language: EN-USfont-family:Consolas;font-size:10.0pt;color:black;"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Output:&lt;br /&gt;&lt;/span&gt;&lt;span lang="EN-US"   style="line-height:115%;font-family: &amp;quot;Lucida Console&amp;quot;;mso-bidi-mso-ansi-language:EN-USfont-family:Consolas;font-size:8.0pt;"&gt;PS&gt; get-help -full .\testme.ps1&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"   style="line-height:115%; font-family:&amp;quot;Lucida Console&amp;quot;;mso-bidi-mso-ansi-language: EN-USfont-family:Consolas;font-size:8.0pt;"&gt;NAME&lt;br /&gt;&lt;span style="mso-spacerun:yes"&gt;    &lt;/span&gt;C:\temp\testme.ps1&lt;br /&gt;&lt;br /&gt;SYNOPSIS&lt;br /&gt;&lt;span style="mso-spacerun:yes"&gt;    &lt;/span&gt;Synopsis text here&lt;br /&gt;&lt;br /&gt;SYNTAX&lt;br /&gt;&lt;span style="mso-spacerun:yes"&gt;    &lt;/span&gt;C:\temp\testme.ps1 [-ver] [-name] &lt;string&gt; [&lt;commonparameters&gt;]&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;DESCRIPTION&lt;br /&gt;&lt;span style="mso-spacerun:yes"&gt;    &lt;/span&gt;Usage description here&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;PARAMETERS&lt;br /&gt;&lt;span style="mso-spacerun:yes"&gt;    &lt;/span&gt;-ver [&lt;switchparameter&gt;]&lt;br /&gt;&lt;span style="mso-spacerun:yes"&gt;        &lt;/span&gt;Enabling this switch prints out the length of the given name&lt;br /&gt;&lt;br /&gt;&lt;span style="mso-spacerun:yes"&gt;        &lt;/span&gt;Required?&lt;span style="mso-spacerun:yes"&gt;                    &lt;/span&gt;False&lt;br /&gt;&lt;span style="mso-spacerun:yes"&gt;        &lt;/span&gt;Position?&lt;span style="mso-spacerun:yes"&gt;                    &lt;/span&gt;Named&lt;br /&gt;&lt;span style="mso-spacerun:yes"&gt;        &lt;/span&gt;Default value&lt;br /&gt;&lt;span style="mso-spacerun:yes"&gt;        &lt;/span&gt;Accept pipeline input?&lt;span style="mso-spacerun:yes"&gt;       &lt;/span&gt;False&lt;br /&gt;&lt;span style="mso-spacerun:yes"&gt;        &lt;/span&gt;Accept wildcard characters?&lt;br /&gt;&lt;br /&gt;&lt;span style="mso-spacerun:yes"&gt;    &lt;/span&gt;-name &lt;string&gt;&lt;br /&gt;&lt;span style="mso-spacerun:yes"&gt;        &lt;/span&gt;The name to say hello to&lt;br /&gt;&lt;br /&gt;&lt;span style="mso-spacerun:yes"&gt;        &lt;/span&gt;Required?&lt;span style="mso-spacerun:yes"&gt;                    &lt;/span&gt;True&lt;br /&gt;&lt;span style="mso-spacerun:yes"&gt;        &lt;/span&gt;Position?&lt;span style="mso-spacerun:yes"&gt;                    &lt;/span&gt;1&lt;br /&gt;&lt;span style="mso-spacerun:yes"&gt;        &lt;/span&gt;Default value&lt;br /&gt;&lt;span style="mso-spacerun:yes"&gt;        &lt;/span&gt;Accept pipeline input?&lt;span style="mso-spacerun:yes"&gt;       &lt;/span&gt;False&lt;br /&gt;&lt;span style="mso-spacerun:yes"&gt;        &lt;/span&gt;Accept wildcard characters?&lt;br /&gt;&lt;br /&gt;&lt;span style="mso-spacerun:yes"&gt;    &lt;/span&gt;&lt;commonparameters&gt;&lt;br /&gt;&lt;span style="mso-spacerun:yes"&gt;   &lt;/span&gt;&lt;span style="mso-spacerun:yes"&gt;     &lt;/span&gt;This cmdlet supports the common parameters: Verbose, Debug,&lt;br /&gt;&lt;span style="mso-spacerun:yes"&gt;        &lt;/span&gt;ErrorAction, ErrorVariable, WarningAction, WarningVariable,&lt;br /&gt;&lt;span style="mso-spacerun:yes"&gt;        &lt;/span&gt;OutBuffer and OutVariable. For more information, type,&lt;br /&gt;&lt;span style="mso-spacerun:yes"&gt;        &lt;/span&gt;"get-help about_commonparameters".&lt;br /&gt;&lt;br /&gt;INPUTS&lt;br /&gt;&lt;br /&gt;OUTPUTS&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;RELATED LINKS&lt;o:p&gt;&lt;/o:p&gt;&lt;/commonparameters&gt;&lt;/string&gt;&lt;/switchparameter&gt;&lt;/commonparameters&gt;&lt;/string&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;h2&gt;&lt;span lang="EN-US"  style="mso-fareast-font-family:Cambria; mso-fareast-theme-font:major-latin;mso-bidi-mso-bidi-theme-font: major-latin;mso-ansi-language:EN-USfont-family:Cambria;"&gt;&lt;span style="mso-list:Ignore"&gt;1.6&lt;span style="font:7.0pt &amp;quot;Times New Roman&amp;quot;"&gt;       &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Use validation rules to perform parameter input validation&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/h2&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;PowerShell has several built-in validation rules for input validation. Use them as long as they add more value than doing custom validation using if-statements.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;The built-in validation rules are: AllowNull, AllowEmptyString, AllowEmptyCollection, ValidateCount, ValidateLength, ValidatePattern, ValidateRange, ValidateScript, ValidateSet, ValidateNotNull, ValidateNotNullOrEmpty&lt;br /&gt;See “&lt;/span&gt;&lt;span lang="EN-US"   style="font-size:8.0pt;mso-bidi- line-height:115%;Lucida Console&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:11.0pt;"&gt;get-help about_functions_advanced_parameters&lt;/span&gt;&lt;span lang="EN-US" style="mso-ansi-language: EN-US"&gt;” for further reference.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;h2&gt;&lt;span lang="EN-US"  style="mso-fareast-font-family:Cambria; mso-fareast-theme-font:major-latin;mso-bidi-mso-bidi-theme-font: major-latin;mso-ansi-language:EN-USfont-family:Cambria;"&gt;&lt;span style="mso-list:Ignore"&gt;1.7&lt;span style="font:7.0pt &amp;quot;Times New Roman&amp;quot;"&gt;       &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Putting the right stuff on the pipeline&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/h2&gt;  &lt;p class="MsoListParagraphCxSpFirst" style="text-indent:-18.0pt;mso-list:l1 level1 lfo2"&gt;&lt;span lang="EN-US"  style="font-family:Symbol;mso-fareast-font-family:Symbol;mso-bidi-mso-ansi-language:EN-USfont-family:Symbol;"&gt;&lt;span style="mso-list:Ignore"&gt;·&lt;span style="font:7.0pt &amp;quot;Times New Roman&amp;quot;"&gt;         &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Use write-host for console information with fancy colors&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoListParagraphCxSpMiddle" style="text-indent:-18.0pt;mso-list:l1 level1 lfo2"&gt;&lt;span lang="EN-US"  style="font-family:Symbol;mso-fareast-font-family:Symbol;mso-bidi-mso-ansi-language:EN-USfont-family:Symbol;"&gt;&lt;span style="mso-list:Ignore"&gt;·&lt;span style="font:7.0pt &amp;quot;Times New Roman&amp;quot;"&gt;         &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Use write-output to be able to pipe your script/function to another script/function.&lt;br /&gt;Example pipeline scenario, sending a user from add-user to new-guestbookentry:&lt;br /&gt;&lt;/span&gt;&lt;span lang="EN-US"   style="font-size:8.0pt;mso-bidi- line-height:115%;Lucida Console&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:11.0pt;"&gt;. .\guestbooks-functions.ps1;&lt;br /&gt;add-user “foo” “password” | new-guestbookentry “Welcome to our guestbooks.com!”&lt;/span&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoListParagraphCxSpLast" style="text-indent:-18.0pt;mso-list:l1 level1 lfo2"&gt;&lt;span lang="EN-US"  style="font-family:Symbol;mso-fareast-font-family:Symbol;mso-bidi-mso-ansi-language:EN-USfont-family:Symbol;"&gt;&lt;span style="mso-list:Ignore"&gt;·&lt;span style="font:7.0pt &amp;quot;Times New Roman&amp;quot;"&gt;         &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;Avoid unwanted objects on the pipeline using termination with $null assignments or piping the output to NULL, example:&lt;br /&gt;&lt;/span&gt;&lt;span lang="EN-US"   style="font-size:8.0pt;mso-bidi- line-height:115%;Lucida Console&amp;quot;;mso-ansi-language:EN-USfont-family:&amp;quot;;font-size:11.0pt;"&gt;add-user “foo” “password” # put the added user on the pipeline&lt;br /&gt;$null = add-user “foo” “password” # added user object “terminated”&lt;br /&gt;add-user “foo” “password” | out-null # added user object piped to NULL instead of the output&lt;/span&gt;&lt;span lang="EN-US" style="mso-ansi-language:EN-US"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-3113278431275275473?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/10/powershell-scripting-guidelines.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-8522326717479195177</guid><pubDate>Thu, 20 Aug 2009 19:47:00 +0000</pubDate><atom:updated>2009-08-20T22:06:59.323+02:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>powershell</category><category domain='http://www.blogger.com/atom/ns#'>iis</category><category domain='http://www.blogger.com/atom/ns#'>scripting</category><title>Note to self: Windows is getting sensitive with the IIS PowerShell provider</title><description>Today I have struggled with some of the most basic automation tasks with the new IIS 7 web server; Creating a web site, application pool and application using a PowerShell script.&lt;br /&gt;&lt;br /&gt;Starting out with &lt;a href="http://learn.iis.net/page.aspx/433/powershell-snap-in-creating-web-sites-web-applications-virtual-directories-and-application-pools/"&gt;this tutorial&lt;/a&gt; I managed to use the following sample to accomplish my task:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;New-Item IIS:\Sites\DemoSite -physicalPath C:\DemoSite -bindings @{protocol="http";bindingInformation=":8080:"}&lt;br /&gt;&lt;br /&gt;Set-ItemProperty IIS:\Sites\DemoSite -name applicationPool -value DemoAppPool&lt;br /&gt;&lt;br /&gt;New-Item IIS:\Sites\DemoSite\DemoApp -physicalPath C:\DemoSite\DemoApp -type Application&lt;br /&gt;&lt;br /&gt;Set-ItemProperty IIS:\sites\DemoSite\DemoApp -name applicationPool -value DemoAppPool&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Everything worked fine with the samples and I started to setup a testing environment on my machine. That involved setting up a local IIS 7, creating some directories in the file system for my test website etc.&lt;br /&gt;All tasks seemed to work, but I repeatedly got the following error when trying to assign the correct application pool to the application:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Set-ItemProperty : Value cannot be null.&lt;br /&gt;Parameter name: path&lt;br /&gt;At C:\.....\WebSetup.ps1:37 char:17&lt;br /&gt;+ Set-ItemProperty  &lt;&lt;&lt;&lt; IIS:\Sites\DemoSite\Server -name applicationPool -value DemoAppPool&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I tried to use other cmdlets to change the application pool setting, but with no success. I also tried to change all paths, the name of the web site etc. according to the sample. The sample code worked, but the error remained when executing Set-ItemProperty in my script.&lt;br /&gt;I doubled checked the documentation, the sample, the value given to the parameter -Path - but it still failed.&lt;br /&gt;I was just going to post a question about this matter in some forums when I figured it all out.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;The name of the directories I created in the file system was using lowercase characters, but not the entries in the IIS configuration!&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The cause of this must be the code in either the file system provider or the IIS provider for PowerShell. Some part of the code which is executed when invoking the Set-ItemProperty cmdlet is doing some case sensitive work..&lt;br /&gt;The lesson and recommendation after this experience is that I will try to create both my entries in the file system and in the IIS configuration from the same script. :)&lt;br /&gt;&lt;br /&gt;Windows is definitely getting more and more sensitive these days...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-8522326717479195177?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/08/note-to-self-windows-is-getting.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-4576578068541747179</guid><pubDate>Thu, 07 May 2009 20:14:00 +0000</pubDate><atom:updated>2009-05-07T22:47:07.415+02:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>tfs</category><category domain='http://www.blogger.com/atom/ns#'>mvc</category><category domain='http://www.blogger.com/atom/ns#'>boo</category><category domain='http://www.blogger.com/atom/ns#'>asp.net</category><category domain='http://www.blogger.com/atom/ns#'>software</category><category domain='http://www.blogger.com/atom/ns#'>sourcecontrol</category><category domain='http://www.blogger.com/atom/ns#'>web</category><title>CodeSaga - The version control repository story teller</title><description>&lt;a href="http://www.codesaga.com/"&gt;&lt;img border="0" src="http://www.codesaga.com/Content/logo3.gif" align="right" width="257" height="53"/&gt;&lt;/a&gt;&lt;br /&gt;Just installed &lt;a href="http://www.codesaga.com/"&gt;CodeSaga&lt;/a&gt; on our internal TFS server and I must say I'm impressed! &lt;br /&gt;For a long time I wanted an application like &lt;a href="http://www.atlassian.com/software/fisheye/"&gt;FishEye&lt;/a&gt; for our TFS source code repository, but unfortunately, FishEye only works with Perforce, CVS and Subversion...&lt;br /&gt;&lt;br /&gt;CodeSaga was quite easy to set up, even though an MSI package would have been nice.&lt;br /&gt;But I guess that is something &lt;a href="http://www.codinginstinct.com/"&gt;Torkel&lt;/a&gt; &lt;a href="http://trac.assembla.com/codesaga/ticket/36"&gt;might be working on&lt;/a&gt; in a near future.&lt;br /&gt;One feature CodeSaga doesn't have yet is the charts of FishEye. But there is a tab already for it in the application, but the page behind it only displays this message: &lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;"Interactive Silverlight charts coming soon to a theather near you!"&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Very nice! I'm looking forward to get them into our installation.. :)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.codinginstinct.com/"&gt;Torkel Ödegaard&lt;/a&gt; is a consultant at &lt;a href="http://www.avega.se"&gt;Avega&lt;/a&gt; and as far as I understand he created this application as a demo/sample application that shows what you can do with &lt;a href="http://www.asp.net/mvc/"&gt;ASP.Net MVC&lt;/a&gt;. The application also utilizes some of the nice frameworks I also like very much (&lt;a href="http://www.castleproject.org/container/index.html"&gt;Castle Windsor&lt;/a&gt;, &lt;a href="http://sourceforge.net/projects/rhino-tools/"&gt;Rhino Tools&lt;/a&gt;) and &lt;a href="http://boo.codehaus.org/"&gt;Boo&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;I will definitely look into the code when I get some time for it.&lt;br /&gt;But hey, good for me: I will attend to a talk next tuesday where Torkel is going to speak about ASP.Net MVC. I guess I will ask one or two questions about CodeSaga :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-4576578068541747179?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/05/codesaga-version-control-repository.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-3315353543298681468</guid><pubDate>Thu, 07 May 2009 16:13:00 +0000</pubDate><atom:updated>2009-05-07T22:47:46.775+02:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>rest</category><category domain='http://www.blogger.com/atom/ns#'>programming</category><category domain='http://www.blogger.com/atom/ns#'>xsl</category><category domain='http://www.blogger.com/atom/ns#'>wcf</category><title>How to inject XSL stylesheet reference in WCF service response using a Message encoder</title><description>In order to shape up the presentation of the responses from a &lt;a href="http://www.developer.com/net/article.php/10916_3695436_1"&gt;RESTful WCF web service&lt;/a&gt; to clients such as Firefox, you'll need to add an XSL stylesheet reference.&lt;br /&gt;In order to do this, the most straight forward thing to do is to hack into your XML serializable classes and implement this using &lt;a href="http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx"&gt;IXmlSerializable&lt;/a&gt;. &lt;br /&gt;Since we want to control this in our service, based on the endpoint URI, this approach was not suitable for our needs. &lt;br /&gt;Also, we don't like cluttering down our serializable entity classes with "presentation logic"/encoding stuff. :)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/be6192a3-6520-4893-9aa6-1c3d0919da03"&gt;I posted a question&lt;/a&gt; about this in MSDN Forums and got a pretty nice answer from &lt;a href="http://shevaspace.blogspot.com/"&gt;Marco Zhou&lt;/a&gt;. He has written a &lt;a href="http://www.google.com/search?q=wcf+message+encoder"&gt;message encoder&lt;/a&gt; which injects the XSL stylesheet reference on a lower level which is exactly what we wanted to do.&lt;br /&gt;&lt;br /&gt;Thanks &lt;a href="http://shevaspace.blogspot.com/"&gt;Marco&lt;/a&gt;!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-3315353543298681468?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/05/how-to-inject-xsl-stylesheet-reference.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-2492568068314637987</guid><pubDate>Tue, 05 May 2009 12:05:00 +0000</pubDate><atom:updated>2009-05-07T10:27:25.473+02:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>castle</category><category domain='http://www.blogger.com/atom/ns#'>.net</category><category domain='http://www.blogger.com/atom/ns#'>ioc</category><category domain='http://www.blogger.com/atom/ns#'>programming</category><title>Castle Windsor 2.0 RTMed</title><description>Oh yeah! &lt;a href="http://ayende.com/Blog/archive/2009/05/05/castle-windsor-2.0-rtm-released.aspx"&gt;Castle Windsor 2.0 is RTMed&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;I just can't wait 'til we upgrade &lt;a href="http://www.remotex.com"&gt;RemoteX Applications&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-2492568068314637987?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/05/castle-windsor-20-rtmed.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-7593567281438390974</guid><pubDate>Sat, 11 Apr 2009 04:19:00 +0000</pubDate><atom:updated>2009-04-11T07:51:19.017+02:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>powershell</category><category domain='http://www.blogger.com/atom/ns#'>jquery</category><category domain='http://www.blogger.com/atom/ns#'>boo</category><category domain='http://www.blogger.com/atom/ns#'>ironpython</category><category domain='http://www.blogger.com/atom/ns#'>programming</category><category domain='http://www.blogger.com/atom/ns#'>c#</category><category domain='http://www.blogger.com/atom/ns#'>grails</category><category domain='http://www.blogger.com/atom/ns#'>languages</category><category domain='http://www.blogger.com/atom/ns#'>groovy</category><category domain='http://www.blogger.com/atom/ns#'>scripting</category><title>Groovy, RESTful Grails and jQuery - where are we heading in .Net land?</title><description>While we heavily focus on &lt;a href="http://msdn.microsoft.com/en-us/netframework/aa663324.aspx"&gt;Windows Communication Foundation&lt;/a&gt; at &lt;a href="http://www.remotex.se/"&gt;work&lt;/a&gt; my collegue &lt;a href="http://www.morkeleb.com/"&gt;Morten&lt;/a&gt; has made some interesting &lt;a href="http://www.morkeleb.com/tag/grails/"&gt;developments with Grails and jQuery&lt;/a&gt; lately. Hosting provided by &lt;a href="http://www.mor.ph/"&gt;mor.ph&lt;/a&gt;, the &lt;a href="http://en.wikipedia.org/wiki/Platform_as_a_service"&gt;PaaS&lt;/a&gt; he have chosen to use.&lt;br /&gt;&lt;br /&gt;&lt;div align="center"&gt;&lt;img src="http://assets.mor.ph/images/steph_logo.png" align="center" width="127" height="61"/&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;For almost one and a half year ago the team I work in decided to move all scripting efforts to &lt;a href="http://www.microsoft.com/windowsserver2003/technologies/management/powershell/default.mspx"&gt;PowerShell&lt;/a&gt; instead of using other scripting technologies for our system.&lt;br /&gt;(Worth to notice here is that the whole system is built up around the Microsoft .Net platform - with extra salt and pepper.. You got &lt;a href="http://msdn.microsoft.com/en-us/netframework/aa663326.aspx"&gt;WPF&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/teamsystem/default.aspx"&gt;Team System&lt;/a&gt;, &lt;a href="http://www.microsoft.com/windowsserver2003/technologies/management/powershell/default.mspx"&gt;PowerShell&lt;/a&gt;, etc.).&lt;br /&gt;&lt;br /&gt;&lt;div align="center"&gt;&lt;img src="http://mallow.wakoopa.com/avatars/000/003/081/normal.png" align="center" width="48" height="48"/&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Now that we got &lt;a href="http://www.microsoft.com/windowsserver2003/technologies/management/powershell/default.mspx"&gt;PowerShell&lt;/a&gt; we can do quite neat things in scripts that are built upon our classes and system modules written in C#. For example, writing a script which adds an user to the system using our domain model implementation (written in C#) and a REST client is no biggie at all. (the way it should be)&lt;br /&gt;&lt;br /&gt;So where are we heading in .Net land to achieve more with less?&lt;br /&gt;I believe we are in a huge need of languages such as &lt;a href="http://www.microsoft.com/windowsserver2003/technologies/management/powershell/default.mspx"&gt;PowerShell&lt;/a&gt; and &lt;a href="http://www.ironpython.info"&gt;IronPython&lt;/a&gt;.&lt;br /&gt;&lt;div align="center"&gt;&lt;img src="http://viva.sourceforge.net/talk/jug-mar-2004/images/groovy-logo.png" align="center" width="113" height="56"/&gt;&lt;/div&gt;&lt;br /&gt;Do we need an equivalent for &lt;a href="http://groovy.codehaus.org/"&gt;Groovy&lt;/a&gt; or are we just fine with &lt;a href="http://www.ironpython.info"&gt;IronPython&lt;/a&gt;, &lt;a href="http://www.microsoft.com/windowsserver2003/technologies/management/powershell/default.mspx"&gt;PowerShell&lt;/a&gt; or maybe we should move our attention to &lt;a href="http://boo.codehaus.org/"&gt;the wrist friendly Boo&lt;/a&gt;?&lt;br /&gt;&lt;div align="center"&gt;&lt;img src="http://bits.ohloh.net/attachments/2486/boo-logo-128_med.png" align="center" width="64" height="64"/&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;What I want is to write RESTful Web Services with very few self-explanatory lines of code, hosted by WCF. Is that possible? &lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Where is the Groovy in my RESTful .Net land?&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-7593567281438390974?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/04/groovy-restful-grails-and-jquery-where.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-4510949333068833495</guid><pubDate>Tue, 24 Mar 2009 22:12:00 +0000</pubDate><atom:updated>2009-03-25T01:57:00.013+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>jquery</category><category domain='http://www.blogger.com/atom/ns#'>programming</category><category domain='http://www.blogger.com/atom/ns#'>web</category><category domain='http://www.blogger.com/atom/ns#'>networking</category><title>A simple bandwidth test based on HTTP, AJAX and jQuery</title><description>Recently I had the opportunity to work with my friend &lt;a href="http://www.linkedin.com/pub/0/22/517"&gt;Micael&lt;/a&gt; on a HTTP broadband testing application. This test will be used as a zero-touch diagnose tool to identify network related issues between users and a video conference system server.&lt;br /&gt;&lt;br /&gt;The test was produced for the non-profit organization &lt;a href="http://www.infinitefamily.org/"&gt;Infinite Family&lt;/a&gt; which involves users located both in the USA and South Africa. The video conference system is located in South Africa and the internet connection to South Africa is provided by a satellite link. Only the hop over the satellite link adds a few hundred milliseconds in response time (ICMP Ping), so it can be really poor conditions for a video link!&lt;br /&gt;&lt;br /&gt;The test has equal capabilities as many of &lt;a href="http://www.bredbandskollen.se"&gt;the other&lt;/a&gt; &lt;a href="http://us.mcafee.com/root/speedometer/test_3000.asp"&gt;tests&lt;/a&gt; &lt;a href="http://www.speedtest.net/"&gt;out&lt;/a&gt; &lt;a href="http://speedtest.raketforskning.com/internet-speed-test.html"&gt;there&lt;/a&gt;. What it does is that it tries to calculate a response time, which of course is not ICMP Ping as one might think, the test only does HTTP and AJAX. Instead, the test uses a HTTP HEAD request to get somewhat a measurement of how long it takes to establish a TCP session and send some data over port 80.&lt;br /&gt;The test does not only measure the response time, it also measure upload and download speeds. For these kind of tests a lot more data is sent back and forth to the HTTP server using (AJAX) HTTP requests.&lt;br /&gt;&lt;br /&gt;The whole test consists of one HTML page with references to &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; and &lt;a href="http://jqueryui.com/"&gt;jQuery UI&lt;/a&gt;.&lt;br /&gt;This test was the first project in which I could try out &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; for real. I had some hard time get it working properly on my PCs and the kids' Mac, but now it works in IE, Opera, Firefox and Safari on both Mac OS and Windows.&lt;br /&gt;I must say I really like working with jQuery. To me it's somewhat aligned with the way I use LINQ and extension methods when coding in C#, so it was a piece of cake start coding with this neat Javascript library.&lt;br /&gt;The progress bar used in the test is a pretty simple thing to do with a few DIV elements and a bit of CSS. That was the approach I used in an early version, but I decided to try out &lt;a href="http://jqueryui.com/"&gt;jQuery UI&lt;/a&gt; as soon as I jumped on the &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; track.&lt;br /&gt;&lt;br /&gt;You can find the test right &lt;a href="http://johan.andersson.net/nettest"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-4510949333068833495?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/03/simple-bandwidth-test-based-on-http.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-9150462831790880489</guid><pubDate>Sat, 21 Mar 2009 10:42:00 +0000</pubDate><atom:updated>2009-03-25T01:08:08.784+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>qrcode</category><category domain='http://www.blogger.com/atom/ns#'>fun</category><category domain='http://www.blogger.com/atom/ns#'>events</category><category domain='http://www.blogger.com/atom/ns#'>remotex</category><category domain='http://www.blogger.com/atom/ns#'>flipper</category><title>Bacchi Orden Open</title><description>Tomorrow is the Bacchi Orden Open taking place in Hornstull, Stockholm.&lt;br /&gt;&lt;a href="http://www.remotex.com"&gt;RemoteX Technologies&lt;/a&gt; is sponsoring and &lt;a href="http://boo.bacchiorden.org/?php=registered&amp;objId=47&amp;objType=club#3"&gt;I and my collegue Erik will play&lt;/a&gt; in the tournament (thanks &lt;a href="http://pinball.wikia.com/wiki/Patrik_Bodin"&gt;Pal&lt;/a&gt;!). &lt;br /&gt;&lt;br /&gt;&lt;a href="http://pinball.wikia.com/wiki/Patrik_Bodin"&gt;The Pal&lt;/a&gt; asked me quite a while ago for ideas on how we (&lt;a href="http://www.remotex.com"&gt;RemoteX Technologies&lt;/a&gt;) could help them out in digitalizing the scorekeeping process during the event. First I thought about putting together a customized version of &lt;a href="http://www.remotex.se/Engelska/Products/tabid/124/language/sv-SE/Default.aspx"&gt;RemoteX Applications&lt;/a&gt; which would help entering scores etc using PDAs. However, the scorekeeping process and the service process (which is what RemoteX Applications primarily supports) did not align very well, so we skipped that idea.&lt;br /&gt;The solution ended up in using their already existing web application (based on the LAMP stack), with some minor adjustments to support Pocket Internet Explorer, Opera for Mobile and such.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://upload.wikimedia.org/wikipedia/en/thumb/c/cd/DesignQR.png/180px-DesignQR.png" alt="QR Code with Face design" width="180" height="180" align="right"/&gt;&lt;br /&gt;Each player plays two so called entries and each entry consists of 4 random games.&lt;br /&gt;Each game on each entry is registered a score and the best score is used in a player ranking algorithm to produce the tournament standings page.&lt;br /&gt;To ease the pain of writing down the score on a piece of paper and THEN enter them into the web application, the solution also involves a free software called &lt;a href="http://www.i-nigma.com"&gt;i-Nigma&lt;/a&gt; which is used to scan &lt;a href="http://en.wikipedia.org/wiki/QR_Code"&gt;QR-codes&lt;/a&gt;.&lt;br /&gt;All players get their two entries printed on papers. Each printed entry has four QR-codes, each representing a link to a page on which the score is to be entered by the scorekeeper.&lt;br /&gt;So basically, the scorekeeping process is:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt; The player plays a game&lt;br /&gt;&lt;li&gt; Calls for the scorekeeper to register the score of the game&lt;br /&gt;&lt;li&gt; The scorekeeper uses a mobile phone equipped with i-Nigma to scan the QR-code of the game&lt;br /&gt;&lt;li&gt; The scorekeeper enters the score in a text field in the web browser on the mobile phone&lt;br /&gt;&lt;li&gt; The player can continue play the remaining games in the entry&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;AFTER EVENT UPDATE:&lt;br /&gt;Everything worked out eventually, but we came up with a few issues we need to address before the upcoming (bigger) event, &lt;a href="http://www.stockholmopen.nu"&gt;Stockholm Open&lt;/a&gt;:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;i-Nigma is not ready out of the box. Further configuration needs to be done on the mobile phones in order to turn off security checks related to camera usage, turning on the led light ("flash")&lt;br /&gt;&lt;li&gt;i-Nigma can't turn on the led light/flash on the mobile phone. This becomes an issue when trying to scan the QR-codes in a dark room.&lt;br /&gt;&lt;li&gt;Either i-Nigma or more probably Windows Mobile does not play very well together. Query strings are chopped of when using ampersands as the separator between query string variables. An adjustment was made live during the event and addresses the issue by replacing ampersands with semicolon.&lt;br /&gt;&lt;li&gt;Info in QR-code should be printed as normal text together with the code to allow for a pen-and-paper backup solution (compare with EAN codes where the number is printed together with the bar code)&lt;br /&gt;&lt;li&gt;Facility issue: Test the WiFi/cell network before the event!! Signal was poor and it was nearly impossible to connect for the two HTC TyTn phones we used&lt;br /&gt;&lt;li&gt;More testing up-front with realistic conditions. We had to re-print every pre-printed entry on a sloooow ink-jet printer (which neither wanted to play WiFi)&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;We had some really nasty problems during the event, but as my former CEO Ulf Engerby at &lt;a href="http://www.qbranch.se"&gt;Qbranch&lt;/a&gt; would put it: Success is planned, shit happens!&lt;br /&gt;&lt;br /&gt;If you want more information about the event, please visit &lt;a href="http://boo.bacchiorden.org"&gt;the website&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-9150462831790880489?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/03/bacchi-orden-open.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-6821056491601437177</guid><pubDate>Mon, 16 Mar 2009 11:02:00 +0000</pubDate><atom:updated>2009-03-16T13:20:13.201+01:00</atom:updated><title>How I succeeded to configure Pidgin to work with our Office Communications Server</title><description>Since it was a real hassle to figure out these settings I decided to note them here for future references. Since I didn't find this variant of the Pidgin+SIPE+LCS configuration anywhere else, it may be useful for others too.&lt;br /&gt;&lt;br /&gt;While talking to others using Pidgin + LCS I noticed the configuration may differ depending on your setup, i.e. internal only or external LCS / SIP server.&lt;br /&gt;At work we use an internal only LCS server which is only listening on its default TCP port (5060).&lt;br /&gt;Below you can see that I need to enter domain + username in the auth* fields. I know others that don't use these fields in their setup, but they do have an externally accessible (over TLS/SSL, port 443) LCS / SIP server.&lt;br /&gt;So be prepared, your result may vary :).&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt; Download &lt;a href="http://www.pidgin.im/"&gt;Pidgin&lt;/a&gt; (v2.5.5 in my case)&lt;br /&gt;&lt;li&gt; Download &lt;a href="http://sipe.sf.net/"&gt;SIPE&lt;/a&gt; (&lt;a href="http://sourceforge.net/project/showfiles.php?group_id=194563&amp;amp;package_id=229450"&gt;v1.3.3, libsipe.dll, precompiled dist for Windows&lt;/a&gt;)&lt;br /&gt;&lt;li&gt; Put libsipe.dll in the plugins directory of Pidgin&lt;br /&gt;&lt;li&gt; Go to Accounts -&amp;gt; Manage Accounts&lt;br /&gt;&lt;li&gt; Choose Add..&lt;br /&gt;&lt;li&gt; Enter the following settings.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;Tab: Basic&lt;br /&gt;Protocol = Microsoft LCS/OCS&lt;br /&gt;Username = &amp;lt;your SIP address in Active Directory is your primary e-mail address&amp;gt;&lt;br /&gt;Password = &amp;lt;your Active Directory password&amp;gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;Tab: Advanced&lt;br /&gt;Use Proxy = Checked&lt;br /&gt;Proxy Server = &amp;lt;the FQDN of your LCS server, i.e. mylcs.corp.local&amp;gt;&lt;br /&gt;Use non-standard port = Checked&lt;br /&gt;Port = 5060&lt;br /&gt;Connection Type = TCP&lt;br /&gt;Auth User = &amp;lt;your Active Directory username&amp;gt;&lt;br /&gt;Auth Domain = &amp;lt;your Active Directory domain name in dotted form, i.e. corp.local&amp;gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;li&gt; Click Save and you should see your LCS contacts appearing in the Buddy List of Pidgin&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;All Done!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-6821056491601437177?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/03/how-i-succeeded-to-configure-pidgin-to.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-8152904321237374014</guid><pubDate>Thu, 12 Mar 2009 21:00:00 +0000</pubDate><atom:updated>2009-03-13T01:51:09.844+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>wpf</category><category domain='http://www.blogger.com/atom/ns#'>.net</category><category domain='http://www.blogger.com/atom/ns#'>programming</category><title>How To Make the Firefox/YouTube Wait Symbol In WPF</title><description>Recently I thought about doing one of those trendy animated "hour glasses", &lt;a href="http://www.overset.com/2006/09/27/flash-wait-animation-ie-browser-throbber/"&gt;the "wait" symbol&lt;/a&gt; which appears when that computer of yours is waiting or working on stuff in the background.&lt;br /&gt;&lt;br /&gt;So what do I mean by "doing one".. In HTML? with jQuery UI perhaps? No and no.&lt;br /&gt;&lt;br /&gt;About 3-4 months ago we started to get WPF into production in our product at work and now we're doing all our new features based on WPF and XAML.&lt;br /&gt;So this animated "hour glass" (or "spinner" which is the word I will use from here) must of course be created in WPF.&lt;br /&gt;&lt;br /&gt;I believe that you guys and girls out there who have worked with XAML, since the spec came out in 2006, probably just say "Say hi to XAML, my friend". For me however, I'm quite proud of how easy it was for me to create this animated little thing.&lt;br /&gt;&lt;br /&gt;When I brought this up during lunch a couple of days ago I discussed what the least CPU consumtive design would be.&lt;br /&gt;My first design thought I came up with was based on 8 circles with ColorAnimations which would make the circles look like the were rotating.&lt;br /&gt;After a quick discussion with my fellow collegues &lt;a href="http://www.morkeleb.com"&gt;Morten&lt;/a&gt; and &lt;a href="http://w2k.fz.se/blog"&gt;Wilhelm&lt;/a&gt; I got interested about the idea of using a rotating (using RenderTransform) Canvas instead. This idea worked out very well and &lt;a href="http://johan.andersson.net/wpf/spinner.xaml"&gt;here is the result&lt;/a&gt; (you must have .Net installed to view it in your browser). &lt;br /&gt;&lt;br /&gt;So the XAML required to achieve this is quite simple, here is a summary:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt; A &lt;a href="http://msdn.microsoft.com/en-us/library/ms754278.aspx"&gt;Canvas&lt;/a&gt; is used to distribute the 8 &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.shapes.ellipse.aspx"&gt;circles&lt;/a&gt; on&lt;br /&gt;&lt;li&gt; Each circle has its fixed position and its own transparency (which makes the "tail" effect)&lt;br /&gt;&lt;li&gt; We add a trigger to the &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.loaded.aspx"&gt;FrameworkElement.Loaded&lt;/a&gt; event for the Canvas, in which we...&lt;br /&gt;&lt;li&gt; ...add a &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.media.animation.doubleanimation.aspx"&gt;DoubleAnimation&lt;/a&gt; targeting the &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.media.rotatetransform.angle.aspx"&gt;Angle property&lt;/a&gt; of the &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.media.rotatetransform.aspx"&gt;RotateTransform&lt;/a&gt; we also added to the Canvas&lt;br /&gt;&lt;li&gt; We use a &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.media.rotatetransform.aspx"&gt;ViewBox&lt;/a&gt; as the parent of the Canvas which lets us scale the animation to fit in i.e. a TabPage header control (like the tabs in Firefox)&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;And here is the XAML:&lt;br /&gt;&lt;pre class="brush: xml"&gt;&lt;br /&gt;&amp;lt;Viewbox&amp;gt;&lt;br /&gt;  &amp;lt;Canvas Width="80" Height="80" Name="canvas"&amp;gt;&lt;br /&gt;   &amp;lt;Canvas.RenderTransform&amp;gt;&lt;br /&gt;    &amp;lt;RotateTransform Angle="0" CenterX="40" CenterY="40" /&amp;gt; &lt;br /&gt;   &amp;lt;/Canvas.RenderTransform&amp;gt;&lt;br /&gt;   &amp;lt;Canvas.Triggers&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;EventTrigger RoutedEvent="FrameworkElement.Loaded"&amp;gt;&lt;br /&gt;     &amp;lt;EventTrigger.Actions&amp;gt;&lt;br /&gt;      &amp;lt;BeginStoryboard&amp;gt;&lt;br /&gt;       &amp;lt;Storyboard&amp;gt;&lt;br /&gt;        &amp;lt;DoubleAnimation Storyboard.TargetName="canvas" &lt;br /&gt;              Storyboard.TargetProperty="(Canvas.RenderTransform).(RotateTransform.Angle)" &lt;br /&gt;              To="360" &lt;br /&gt;              Duration="0:0:0.7" &lt;br /&gt;              RepeatBehavior="Forever"/&amp;gt;&lt;br /&gt;       &amp;lt;/Storyboard&amp;gt;&lt;br /&gt;&lt;br /&gt;      &amp;lt;/BeginStoryboard&amp;gt;&lt;br /&gt;     &amp;lt;/EventTrigger.Actions&amp;gt;&lt;br /&gt;    &amp;lt;/EventTrigger&amp;gt;&lt;br /&gt;   &amp;lt;/Canvas.Triggers&amp;gt;&lt;br /&gt;   &amp;lt;Ellipse Canvas.Top="0" Canvas.Left="30" Width="20" Height="20" Fill="#08000000"/&amp;gt;&lt;br /&gt;   &amp;lt;Ellipse Canvas.Top="10" Canvas.Left="50" Width="20" Height="20" Fill="#15000000"/&amp;gt;&lt;br /&gt;&lt;br /&gt;   &amp;lt;Ellipse Canvas.Top="30" Canvas.Left="60" Width="20" Height="20" Fill="#38000000"/&amp;gt;&lt;br /&gt;   &amp;lt;Ellipse Canvas.Top="50" Canvas.Left="50" Width="20" Height="20" Fill="#55000000"/&amp;gt;&lt;br /&gt;   &amp;lt;Ellipse Canvas.Top="60" Canvas.Left="30" Width="20" Height="20" Fill="#88000000"/&amp;gt;&lt;br /&gt;   &amp;lt;Ellipse Canvas.Top="50" Canvas.Left="10" Width="20" Height="20" Fill="#aa000000"/&amp;gt;&lt;br /&gt;   &amp;lt;Ellipse Canvas.Top="30" Canvas.Left="0" Width="20" Height="20" Fill="#cc000000"/&amp;gt;&lt;br /&gt;   &amp;lt;Ellipse Canvas.Top="10" Canvas.Left="10" Width="20" Height="20" Fill="#ff000000"/&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;/Canvas&amp;gt;&lt;br /&gt; &amp;lt;/Viewbox&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Pretty easy, or what do you think?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-8152904321237374014?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/03/how-to-make-firefoxyoutube-wait-symbol.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-3078804034728986194</guid><pubDate>Thu, 12 Mar 2009 18:03:00 +0000</pubDate><atom:updated>2009-03-24T09:35:22.730+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>windows forms</category><category domain='http://www.blogger.com/atom/ns#'>.net</category><category domain='http://www.blogger.com/atom/ns#'>programming</category><category domain='http://www.blogger.com/atom/ns#'>c#</category><category domain='http://www.blogger.com/atom/ns#'>ood</category><category domain='http://www.blogger.com/atom/ns#'>fluent interfaces</category><title>A fluent interface and the Builder pattern</title><description>My former collegue &lt;a href="http://thomaslundstrom.blogspot.com/"&gt;Thomas Lundström&lt;/a&gt; &lt;a href="http://thomaslundstrom.blogspot.com/2008/11/fluent-interfaces-by-lambdas-in-c.html"&gt;blogged about&lt;/a&gt; &lt;a href="http://thomaslundstrom.blogspot.com/2008/11/on-migrations-apis-in-net.html"&gt;fluent interfaces&lt;/a&gt; quite a while ago, which he followed up &lt;a href="http://blogs.msdn.com/johanl/archive/2009/02/13/en-liten-dsl-f-r-att-best-lla-kaffe.aspx#9442940"&gt;in a comment&lt;/a&gt; to &lt;a href="http://blogs.msdn.com/johanl"&gt;Johan Lindfors'&lt;/a&gt; post &lt;a href="http://blogs.msdn.com/johanl/archive/2009/02/13/en-liten-dsl-f-r-att-best-lla-kaffe.aspx"&gt;"A small DSL to order coffee" (in Swedish)&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The blog post and its comments discusses two different approaches to fluent interfaces. The first approach is based on getters which mutates the instance when they are called. Some people think this is a very bad design - getters should not mutate the instance!&lt;br /&gt;I agree on that. I strongly believe that a get operation should be idempotent and not mutate the object instance. This for the same reason a HTTP GET request should not mutate a resource and a HTTP POST/PUT should mutate a collection/the resource. &lt;br /&gt;&lt;span style="font-style:italic; font-size:smaller;"&gt;(That's why I prefer RESTful web services more than SOAP over HTTP, but that's a totally different blog post. :)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The second approach is the one that Thomas points out. It's the classical &lt;a href="http://en.wikipedia.org/wiki/Builder_pattern"&gt;Builder Pattern&lt;/a&gt; where you have a totally separate class which is used to build object instances. It &lt;a href="http://groups.google.com/group/comp.object/browse_thread/thread/db4b3914ddea5131/25e7e96e2e91983b?lnk=st&amp;q&amp;rnum=1&amp;pli=1"&gt;differentiates&lt;/a&gt; itself among the creational OOD design patterns by targeting primarily mutable objects. It's like a bunch of &lt;a href="http://en.wikipedia.org/wiki/Factory_method_pattern"&gt;Factory&lt;/a&gt; methods which is used like a &lt;a href="http://en.wikipedia.org/wiki/Factory_method_pattern"&gt;Factory&lt;/a&gt;, but instead of having thousands of different methods in one Factory (overloads for example), the Builder is used in several calls to create/configure the final object instance.&lt;br /&gt;&lt;br /&gt;An approach which was recently used at work is a mix of the two approaches mentioned above. Instead of having a separate builder we have builder methods on the object instance itself, either directly or via extension methods. Separate from the builder methods we got some Factory Methods. These are the starting point to create a basic instance. The builder methods are then used to further shape the object instance to our needs.&lt;br /&gt;&lt;br /&gt;Approach #1 - getters which creates/mutate the object instace:&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;Coffee myLatte = Coffee.OrderLatte.Double.FatFree.Vanilla;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Approach #2 - a separate builder&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;Coffee myLatte = CoffeeBuilder.Latte().Double().FatFree().Vanilla().Build();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Our approach - a mix of factory methods and builder methods on the object instance itself&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;Coffee myLatte = Coffee.Latte().Double().FatFree().Vanilla();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So what's the pros and cons with the last two approaches?&lt;br /&gt;I guess they are quite similar, but here is some pros:&lt;br /&gt;- The separate builder seems a bit more aligned with the Separation Of Concerns principle&lt;br /&gt;- The built-in builder methods via extension methods provides a lightweight class structure, even for classes in a third-party class library, such as the &lt;a href="http://en.wikipedia.org/wiki/Base_Class_Library"&gt;BCL&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;font-size:smaller"&gt;(Please post a comment if you can think of more pros and cons or if you just totally disagree with me :)&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;So of course, the $10.000 question answer is... It depends on your context!&lt;br /&gt;Anyhow, here is a sample how we tend to use this mix of Factory Methods and Builder methods at work.&lt;br /&gt;&lt;br /&gt;The following code is used to build construct the collection of &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridviewcolumn.aspx"&gt;DataGridViewColumns&lt;/a&gt; used in a Windows Forms &lt;a href="http://msdn.microsoft.com/en-us/library/e0ywh3cz.aspx"&gt;DataGridView control&lt;/a&gt;.&lt;br /&gt;The CreateColumns() method is used to create an enumeration of the columns to use and TextColumn() is a sample Factory Method.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp"&gt;&lt;br /&gt;protected override IEnumerable&lt;DataGridViewColumn&gt; CreateColumns()&lt;br /&gt;{&lt;br /&gt; yield return TextColumn()&lt;br /&gt;  .For( WorkOrderPresenter.Properties.Title )&lt;br /&gt;  .WeightedWidth( 100 );&lt;br /&gt;&lt;br /&gt; yield return TextColumn()&lt;br /&gt;  .For( WorkOrderPresenter.Properties.Description )&lt;br /&gt;  .WeightedWidth( 200 );&lt;br /&gt;&lt;br /&gt; yield return ComboBoxColumn( _activityBindingSource )&lt;br /&gt;  .For( WorkOrderPresenter.Properties.Activity )&lt;br /&gt;  .WeightedWidth( 100 )&lt;br /&gt;  .Width( 90, 130 );&lt;br /&gt;....&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/// &lt;summary&gt;&lt;br /&gt;/// Creates a textbox column with default behavior.&lt;br /&gt;/// &lt;/summary&gt;&lt;br /&gt;protected virtual DataGridViewTextBoxColumn TextColumn()&lt;br /&gt;{&lt;br /&gt; return new DataGridViewTextBoxColumn().WrapContents().WithDefaultBehavior();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The methods For(), WeightedWidth(), Width(), WrapContents() and WithDefaultBehavior() are Builder (extension) methods on DataGridViewColumn.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-3078804034728986194?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/03/fluent-interface-and-builder-pattern.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-2018624268400516717</guid><pubDate>Mon, 09 Mar 2009 11:46:00 +0000</pubDate><atom:updated>2009-03-11T22:36:10.459+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>.net</category><category domain='http://www.blogger.com/atom/ns#'>programming</category><category domain='http://www.blogger.com/atom/ns#'>debugging</category><title>Bye bye Debug.WriteLine!</title><description>Recently I had the opportunity to deal with a couple nasty WM_PAINT handlers. Everyone who have been in a situation where you need to debug some broken paint operations knows that it can be really hard to debug using breakpoints, since you can't break into the debugger. When you break into the debugger, the WM_PAINT event will trigger once again when you switch back to the program you are debugging. Of course you can overcome this by placing the debugger and the debugee on different areas of your screen, but mostly I don't think it pays back to use breakpoints for these kind of scenarios.&lt;br /&gt;&lt;br /&gt;So what do we do when we have a bug in a WM_PAINT handler? Write a unit test? Nope. At least I don't, even if that would be my preferred way to go.&lt;br /&gt;As long as I remember I think I have inserted alot of those Debug.WriteLine() statements all around my code, so I can get some kind of trace log for the program.&lt;br /&gt;However, this requires modification and recompilation of the code. &lt;br /&gt;&lt;br /&gt;So let me introduce to you something I started using recently: Tracepoints!&lt;br /&gt;I read about them years ago and have tried to use them in earlier versions of Visual Studio. A week ago they became my new little helper... in Visual Studio 2008.&lt;br /&gt;&lt;br /&gt;Here is a quick how to from MSDN on how you can use them: &lt;br /&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/232dxah7.aspx"&gt;How to: Specify a Tracepoint/Breakpoint Action&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So now I don't use Debug.WriteLine() anymore. Instead, I let a tracepoint print a message including the expression I need to evaluate and print.&lt;br /&gt;However, even though this feature works great, you may run into trouble.&lt;br /&gt;Today I discovered issues where the expression evaluation times out!&lt;br /&gt;The timeout occurred when I had quite a number of tracepoint set in a piece of code I was debugging on my Windows Mobile device.&lt;br /&gt;&lt;br /&gt;Every time I have to deal with UI components which implements a quite complex handler for WM_PAINT I always think "There must be some way to test this!". So far I haven't found a satisfactory design where UI components meets the requirements of my unit testing framework. &lt;br /&gt;If you have ideas or links on how to succeed with automated testing and UI components, please let me know!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Update: &lt;a href="http://blogs.conchango.com/merrickchaffer/"&gt;Merrick Chaffer&lt;/a&gt; has a &lt;a href="http://blogs.conchango.com/merrickchaffer/archive/2008/06/23/insert-tracepoint-in-visual-studio-for-debug-writeline-alternative.aspx"&gt;quite similar blog post&lt;/a&gt; with a nice screen shot on the dialog where you set up your tracepoint&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-2018624268400516717?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/03/bye-bye-debugwriteline.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-9291563.post-3530946511316579732</guid><pubDate>Tue, 03 Mar 2009 08:30:00 +0000</pubDate><atom:updated>2009-03-03T10:00:39.709+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>environmental</category><title>Consider the environment before printing</title><description>About a year ago or so I received e-mails with the following message in its signature:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="color:green;" lang="EN-GB"&gt;&lt;span style="font-family:Webdings;font-size:180%;"&gt;P&lt;/span&gt;  &lt;b&gt;&lt;span style="font-family:Arial,Helvetica;font-size:85%;"&gt;Please consider the environment  before printing this e-mail&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;   &lt;/blockquote&gt;(if you see the capital 'P' character in the beginning of the message, please read on...)&lt;br /&gt;&lt;br /&gt;Now, one year after, I see this message more often.&lt;br /&gt;Normally I try to avoid long e-mail signatures (which easily can get longer than the e-mail body), but due to the number of printed e-mails in the recycle bin in our printer room at work I believe this is a keeper.&lt;br /&gt;&lt;br /&gt;When receiving an e-mail with this message it has also a small graphic besides it showing a small green tree and a road. This is actually not an image attached to the e-mail (which I &lt;span style="font-style: italic;"&gt;really&lt;/span&gt; try to avoid in my e-mail signature, like the corporate logo etc.), as it's the capital 'P' character in the WebDings font.&lt;br /&gt;&lt;br /&gt;With that said, it won't show up if you aren't using Outlook or Internet Explorer or any other e-mail viewer with capabilities to display rich formatted text. For example, it won't show up in Firefox.&lt;br /&gt;&lt;br /&gt;Side-track:&lt;br /&gt;&lt;span style="font-style: italic;"&gt;It's exactly the same with smileys. Ever read an e-mail on your mobile phone (using Pocket Outlook for instance) and you wondered about all the capital 'J' characters? The smiley is the symbol displayed when you type capital 'J' and use the Wingdings font. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I tried to find some info about this green message so I could copy it into my e-mail signature. Please see &lt;a href="http://www.blogjer.com/2008/01/21/please-consider-the-environment-before-printing-this-email/"&gt;this blog post&lt;/a&gt; for more info! (and add the message to your e-mail signature today)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291563-3530946511316579732?l=johan.andersson.net%2Fblog%2Findex.html' alt='' /&gt;&lt;/div&gt;</description><link>http://johan.andersson.net/blog/2009/03/consider-environment-before-printing.html</link><author>noreply@blogger.com (Johan Andersson)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></item></channel></rss>