<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" version="2.0">
  <channel>
    <title>Code Assassin</title>
    <link>http://www.codeassassin.com/blog/</link>
    <description>Silently disposing your objects in the dead of night</description>
    <language>en-au</language>
    <copyright>Jason Stangroome</copyright>
    <lastBuildDate>Wed, 20 May 2009 05:41:30 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 1.9.6264.0</generator>
    <managingEditor>contact@codeassassin.com</managingEditor>
    <webMaster>contact@codeassassin.com</webMaster>
    <geo:lat>-27.28</geo:lat><geo:long>153.01</geo:long><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/CodeAssassin" type="application/rss+xml" /><item>
      <trackback:ping>http://www.codeassassin.com/blog/Trackback.aspx?guid=543994df-954d-436b-b050-c3f93c746c11</trackback:ping>
      <pingback:server>http://www.codeassassin.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.codeassassin.com/blog/PermaLink,guid,543994df-954d-436b-b050-c3f93c746c11.aspx</pingback:target>
      <dc:creator>Jason</dc:creator>
      <wfw:comment>http://www.codeassassin.com/blog/CommentView,guid,543994df-954d-436b-b050-c3f93c746c11.aspx</wfw:comment>
      <wfw:commentRss>http://www.codeassassin.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=543994df-954d-436b-b050-c3f93c746c11</wfw:commentRss>
      
      <title>PowerShell for Developers</title>
      <guid isPermaLink="false">http://www.codeassassin.com/blog/PermaLink,guid,543994df-954d-436b-b050-c3f93c746c11.aspx</guid>
      <link>http://www.codeassassin.com/blog/PermaLink,guid,543994df-954d-436b-b050-c3f93c746c11.aspx</link>
      <pubDate>Wed, 20 May 2009 05:41:30 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
Several weeks ago &lt;a href="http://richardsbraindump.blogspot.com/"&gt;Richard Banks&lt;/a&gt; (&lt;a href="http://twitter.com/rbanks54"&gt;@rbanks54&lt;/a&gt;)&#xD;
coerced me to find time to present to the Australian Virtual Alt.NET User Group between&#xD;
moving house and deploying a new website to production for my current client.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
I agreed and with an absurdly short amount of preparation presented to a small group&#xD;
online using Microsoft Live Meeting and a shared PowerShell console window. You can &lt;a href="http://ozalt.net/blog/virtual-alt-net-11-may-09-powershell-and-ngourd/"&gt;watch&#xD;
the presentation&lt;/a&gt; on the &lt;a href="http://ozalt.net/blog/"&gt;Oz Alt.NET Community&#xD;
Blog&lt;/a&gt;.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
The “slides” and example scripts can be &lt;a href="http://dl.getdropbox.com/u/255217/OzVAN-PowerShell.zip"&gt;downloaded&#xD;
here&lt;/a&gt;.&#xD;
&lt;/p&gt;&#xD;
        &lt;img width="0" height="0" src="http://www.codeassassin.com/blog/aggbug.ashx?id=543994df-954d-436b-b050-c3f93c746c11"&gt;&lt;/img&gt;&#xD;
      &lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=YHutY8QatUg:ZaQl6klNWFk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=YHutY8QatUg:ZaQl6klNWFk:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=YHutY8QatUg:ZaQl6klNWFk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?i=YHutY8QatUg:ZaQl6klNWFk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=YHutY8QatUg:ZaQl6klNWFk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?i=YHutY8QatUg:ZaQl6klNWFk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=YHutY8QatUg:ZaQl6klNWFk:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeAssassin/~4/YHutY8QatUg" height="1" width="1"/&gt;</description>
      <comments>http://www.codeassassin.com/blog/CommentView,guid,543994df-954d-436b-b050-c3f93c746c11.aspx</comments>
      <category>PowerShell</category>
    </item>
    <item>
      <trackback:ping>http://www.codeassassin.com/blog/Trackback.aspx?guid=60340df4-9866-4c2b-80fc-7daf7103d5d8</trackback:ping>
      <pingback:server>http://www.codeassassin.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.codeassassin.com/blog/PermaLink,guid,60340df4-9866-4c2b-80fc-7daf7103d5d8.aspx</pingback:target>
      <dc:creator>Jason</dc:creator>
      <wfw:comment>http://www.codeassassin.com/blog/CommentView,guid,60340df4-9866-4c2b-80fc-7daf7103d5d8.aspx</wfw:comment>
      <wfw:commentRss>http://www.codeassassin.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=60340df4-9866-4c2b-80fc-7daf7103d5d8</wfw:commentRss>
      <slash:comments>1</slash:comments>
      
      <title>Code Coverage Delta with Team System and PowerShell</title>
      <guid isPermaLink="false">http://www.codeassassin.com/blog/PermaLink,guid,60340df4-9866-4c2b-80fc-7daf7103d5d8.aspx</guid>
      <link>http://www.codeassassin.com/blog/PermaLink,guid,60340df4-9866-4c2b-80fc-7daf7103d5d8.aspx</link>
      <pubDate>Sun, 01 Mar 2009 11:37:09 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
My last post documented my first venture into working with Visual Studio's Code Analysis&#xD;
output with PowerShell to find classes that need more testing. Since then I've taken&#xD;
the idea further to analyse how coverage has changed over a series of builds from&#xD;
TFS.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
What resulted is a PowerShell script that takes, as a minimum, the name of a TFS Project&#xD;
and the name of a Build Definition within that project. The script will then, by default,&#xD;
locate the two most recent successful builds, grab the code coverage data from the&#xD;
test runs of each of those builds and output a list of classes whose coverage has&#xD;
changed between those builds, citing the change in the number of blocks not covered.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Additional parameters to the script allow partially successful or failed builds to&#xD;
be considered and also to analyse coverage change over a span of several builds rather&#xD;
just two consecutive builds.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
The primary motivator behind developing this script was to be able to identify more&#xD;
accurately where coverage was lost when a new build has an overall coverage percentage&#xD;
lower than the last. This then helps to locate, among other things, where new code&#xD;
has been added without testing or where existing tests have been deleted or disabled.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
A code base with a strong commitment to the Single Responsibility Principle should&#xD;
find class-level granularity sufficient but extending the script to support method-level&#xD;
reporting should be trivial given that the Coverage Analysis DataSet already includes&#xD;
all the required information.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
The script requires the Team Foundation Server PowerShell Snapin from the TFS October&#xD;
2008 Power Tools and the Visual Studio Coverage Analysis assemblies presumably available&#xD;
in Visual Studio 2008 Professional or higher. These dependencies only support 32-bit&#xD;
PowerShell so my script unfortunately suffers the same constraint.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a href="http://www.codeassassin.com/public/Compare-TfsBuildCoverage.zip"&gt;Download&#xD;
the script here&lt;/a&gt;, and use it something like this:&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
PS C:\TfsWorkspace\&amp;gt; C:\Scripts\Compare-TfsBuildCoverage.ps1 -project Foo -build&#xD;
FooBuild | sort DeltaBlocksNotCovered&#xD;
&lt;/p&gt;&#xD;
        &lt;img width="0" height="0" src="http://www.codeassassin.com/blog/aggbug.ashx?id=60340df4-9866-4c2b-80fc-7daf7103d5d8"&gt;&lt;/img&gt;&#xD;
      &lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=6fMRXZ5MSo0:DU7dkPk3uP0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=6fMRXZ5MSo0:DU7dkPk3uP0:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=6fMRXZ5MSo0:DU7dkPk3uP0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?i=6fMRXZ5MSo0:DU7dkPk3uP0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=6fMRXZ5MSo0:DU7dkPk3uP0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?i=6fMRXZ5MSo0:DU7dkPk3uP0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=6fMRXZ5MSo0:DU7dkPk3uP0:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeAssassin/~4/6fMRXZ5MSo0" height="1" width="1"/&gt;</description>
      <comments>http://www.codeassassin.com/blog/CommentView,guid,60340df4-9866-4c2b-80fc-7daf7103d5d8.aspx</comments>
      <category>PowerShell;Team Foundation Server;Unit Testing</category>
    </item>
    <item>
      <trackback:ping>http://www.codeassassin.com/blog/Trackback.aspx?guid=4d951141-cd88-40c0-b717-953424416007</trackback:ping>
      <pingback:server>http://www.codeassassin.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.codeassassin.com/blog/PermaLink,guid,4d951141-cd88-40c0-b717-953424416007.aspx</pingback:target>
      <dc:creator>Jason</dc:creator>
      <wfw:comment>http://www.codeassassin.com/blog/CommentView,guid,4d951141-cd88-40c0-b717-953424416007.aspx</wfw:comment>
      <wfw:commentRss>http://www.codeassassin.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=4d951141-cd88-40c0-b717-953424416007</wfw:commentRss>
      
      <title>Analyse Code Coverage with PowerShell</title>
      <guid isPermaLink="false">http://www.codeassassin.com/blog/PermaLink,guid,4d951141-cd88-40c0-b717-953424416007.aspx</guid>
      <link>http://www.codeassassin.com/blog/PermaLink,guid,4d951141-cd88-40c0-b717-953424416007.aspx</link>
      <pubDate>Fri, 13 Feb 2009 14:28:20 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
Visual Studio 2008 Team System's built-in Code Coverage is nice but the standard results&#xD;
window only allows you to drill down through each assembly, then namespace, class,&#xD;
and finally method. You can't easily find the class with the least blocks covered,&#xD;
something I needed to do the other day.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
I found &lt;a href="http://blogs.msdn.com/ms_joc/articles/406608.aspx"&gt;John Cunningham's&#xD;
blog about "off-road" code coverage&lt;/a&gt; and was pleased to see that Microsoft had&#xD;
provided an assembly in Visual Studio that can be used to parse the *.coverage file&#xD;
output by a test run. I followed his example to write a PowerShell script to provide&#xD;
basic access to the data.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
You can &lt;a href="/public/Get-CodeCoverageDataSet.zip"&gt;download my script here&lt;/a&gt;.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Then you can use it like this:&#xD;
&lt;/p&gt;&#xD;
        &lt;pre name="code" class="ps1"&gt;$CoverageDS = ./Get-CodeCoverageDataSet.ps1 "data.coverage"&#xD;
$CoverageDS.Class `&#xD;
  | Sort-Object -Property BlocksNotCovered -Descending `&#xD;
  | Select-Object `&#xD;
    -First 25 `&#xD;
    -Property `&#xD;
      BlocksNotCovered, `&#xD;
      @{ &#xD;
        Name = "Namespace"; &#xD;
        Expression = { &#xD;
          $CoverageDS.NamespaceTable.FindByNamespaceKeyName($_.NamespaceKeyName).NamespaceName&#xD;
        }&#xD;
      }, `&#xD;
      ClassName&#xD;
&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
The coverage file is typically found in the TestResults\[TestRunName]\In\[ComputerName]\&#xD;
folder. You can easily perform queries over methods or lines rather than classes by&#xD;
using the other tables in the returned dataset. You can also use the ConvertTo-Html&#xD;
cmdlet to easily create a report for your team.&#xD;
&lt;/p&gt;&#xD;
        &lt;img width="0" height="0" src="http://www.codeassassin.com/blog/aggbug.ashx?id=4d951141-cd88-40c0-b717-953424416007"&gt;&lt;/img&gt;&#xD;
      &lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=YPrVzp64qo8:PFwW1S-DOE0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=YPrVzp64qo8:PFwW1S-DOE0:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=YPrVzp64qo8:PFwW1S-DOE0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?i=YPrVzp64qo8:PFwW1S-DOE0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=YPrVzp64qo8:PFwW1S-DOE0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?i=YPrVzp64qo8:PFwW1S-DOE0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=YPrVzp64qo8:PFwW1S-DOE0:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeAssassin/~4/YPrVzp64qo8" height="1" width="1"/&gt;</description>
      <comments>http://www.codeassassin.com/blog/CommentView,guid,4d951141-cd88-40c0-b717-953424416007.aspx</comments>
      <category>PowerShell;Unit Testing</category>
    </item>
    <item>
      <trackback:ping>http://www.codeassassin.com/blog/Trackback.aspx?guid=f3ff2ae9-23fe-4636-99fd-4e0b0b7ff01d</trackback:ping>
      <pingback:server>http://www.codeassassin.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.codeassassin.com/blog/PermaLink,guid,f3ff2ae9-23fe-4636-99fd-4e0b0b7ff01d.aspx</pingback:target>
      <dc:creator>Jason</dc:creator>
      <wfw:comment>http://www.codeassassin.com/blog/CommentView,guid,f3ff2ae9-23fe-4636-99fd-4e0b0b7ff01d.aspx</wfw:comment>
      <wfw:commentRss>http://www.codeassassin.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=f3ff2ae9-23fe-4636-99fd-4e0b0b7ff01d</wfw:commentRss>
      
      <title>Is -ism me?</title>
      <guid isPermaLink="false">http://www.codeassassin.com/blog/PermaLink,guid,f3ff2ae9-23fe-4636-99fd-4e0b0b7ff01d.aspx</guid>
      <link>http://www.codeassassin.com/blog/PermaLink,guid,f3ff2ae9-23fe-4636-99fd-4e0b0b7ff01d.aspx</link>
      <pubDate>Tue, 10 Feb 2009 12:27:50 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
In a sad attempt to get blogging again, I am going to start by responding to &lt;a href="http://www.nervoustych.com/blog/PermaLink,guid,826827b3-3f22-47cf-a034-5c127578977c.aspx"&gt;this&#xD;
blatant prod&lt;/a&gt;. I agree with some of &lt;a href="http://www.linkedin.com/pub/7/b62/608"&gt;Jim&lt;/a&gt;'s&#xD;
answers but to keep it interesting I've selected a disjoint set and &lt;a href="http://futurama.wikia.com/wiki/Elzar"&gt;knocked&#xD;
it up a notch&lt;/a&gt;.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
I am:&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Pragmatic about &lt;a href="http://www.imdb.com/title/tt0120655/"&gt;dogmatism&lt;/a&gt;.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Practicing &lt;a href="http://www.codeassassin.com/dvds.txt"&gt;consumerism&lt;/a&gt;.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Prone to &lt;a href="http://en.wikipedia.org/wiki/Defeatism"&gt;defeatism&lt;/a&gt;.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Parodying &lt;a href="http://www.polar.fi/au-en/products/running_multisport/RS200"&gt;athleticism&lt;/a&gt;.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Proof of &lt;a href="http://xkcd.com/505/"&gt;determinism&lt;/a&gt;.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
To keep it going, the same rule applies: if you've read this then follow suit blogging&#xD;
your own answers, even if you are busy writing your own blog engine.&#xD;
&lt;/p&gt;&#xD;
        &lt;img width="0" height="0" src="http://www.codeassassin.com/blog/aggbug.ashx?id=f3ff2ae9-23fe-4636-99fd-4e0b0b7ff01d"&gt;&lt;/img&gt;&#xD;
      &lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=oBl6-t_sbcw:SIjphq9h_W8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=oBl6-t_sbcw:SIjphq9h_W8:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=oBl6-t_sbcw:SIjphq9h_W8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?i=oBl6-t_sbcw:SIjphq9h_W8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=oBl6-t_sbcw:SIjphq9h_W8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?i=oBl6-t_sbcw:SIjphq9h_W8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=oBl6-t_sbcw:SIjphq9h_W8:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeAssassin/~4/oBl6-t_sbcw" height="1" width="1"/&gt;</description>
      <comments>http://www.codeassassin.com/blog/CommentView,guid,f3ff2ae9-23fe-4636-99fd-4e0b0b7ff01d.aspx</comments>
      <category>Metablog</category>
    </item>
    <item>
      <trackback:ping>http://www.codeassassin.com/blog/Trackback.aspx?guid=cc3a732c-4eb2-4487-acf8-9f964c32347d</trackback:ping>
      <pingback:server>http://www.codeassassin.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.codeassassin.com/blog/PermaLink,guid,cc3a732c-4eb2-4487-acf8-9f964c32347d.aspx</pingback:target>
      <dc:creator>Jason</dc:creator>
      <wfw:comment>http://www.codeassassin.com/blog/CommentView,guid,cc3a732c-4eb2-4487-acf8-9f964c32347d.aspx</wfw:comment>
      <wfw:commentRss>http://www.codeassassin.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=cc3a732c-4eb2-4487-acf8-9f964c32347d</wfw:commentRss>
      
      <title>Adelaide Geek Dinner Handover</title>
      <guid isPermaLink="false">http://www.codeassassin.com/blog/PermaLink,guid,cc3a732c-4eb2-4487-acf8-9f964c32347d.aspx</guid>
      <link>http://www.codeassassin.com/blog/PermaLink,guid,cc3a732c-4eb2-4487-acf8-9f964c32347d.aspx</link>
      <pubDate>Tue, 21 Oct 2008 11:03:03 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
As I have recently accepted a new job interstate, I will no longer be organising dinners&#xD;
for fellow developers in Adelaide. However, rather than allow such a fun event to&#xD;
disappear, I am passing the awesome responsibility of organising the dinners to my&#xD;
friend and colleague, &lt;a href="http://nervoustych.com/blog/" target="_blank"&gt;Jim Burger&lt;/a&gt;,&#xD;
whom many of you have met on previous occasions.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
I will be giving Jim a hard time to make sure he continues to arrange a dinner at&#xD;
least once each quarter and I believe it will also help to ensure he remembers to&#xD;
attend them himself ;). Names and contact details of previous attendees and people&#xD;
who have registered their interest will be given to Jim so he can send you the next&#xD;
invite but let him or I know if you'd rather be removed from the list.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
If you've never been invited to an Adelaide Geek Dinner before but want to be on the&#xD;
list, just contact Jim or I and you'll surely be invited to the next one.&#xD;
&lt;/p&gt;&#xD;
        &lt;img width="0" height="0" src="http://www.codeassassin.com/blog/aggbug.ashx?id=cc3a732c-4eb2-4487-acf8-9f964c32347d"&gt;&lt;/img&gt;&#xD;
      &lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=rxL99f_mO5g:nPcj2S0TEZo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=rxL99f_mO5g:nPcj2S0TEZo:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=rxL99f_mO5g:nPcj2S0TEZo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?i=rxL99f_mO5g:nPcj2S0TEZo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=rxL99f_mO5g:nPcj2S0TEZo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?i=rxL99f_mO5g:nPcj2S0TEZo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=rxL99f_mO5g:nPcj2S0TEZo:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeAssassin/~4/rxL99f_mO5g" height="1" width="1"/&gt;</description>
      <comments>http://www.codeassassin.com/blog/CommentView,guid,cc3a732c-4eb2-4487-acf8-9f964c32347d.aspx</comments>
      <category>Geek Dinner</category>
    </item>
    <item>
      <trackback:ping>http://www.codeassassin.com/blog/Trackback.aspx?guid=41a7b075-4ae8-4742-a3b1-0df55577fb00</trackback:ping>
      <pingback:server>http://www.codeassassin.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.codeassassin.com/blog/PermaLink,guid,41a7b075-4ae8-4742-a3b1-0df55577fb00.aspx</pingback:target>
      <dc:creator>Jason</dc:creator>
      <wfw:comment>http://www.codeassassin.com/blog/CommentView,guid,41a7b075-4ae8-4742-a3b1-0df55577fb00.aspx</wfw:comment>
      <wfw:commentRss>http://www.codeassassin.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=41a7b075-4ae8-4742-a3b1-0df55577fb00</wfw:commentRss>
      
      <title>Strongly Typed Windows Forms Data Binding</title>
      <guid isPermaLink="false">http://www.codeassassin.com/blog/PermaLink,guid,41a7b075-4ae8-4742-a3b1-0df55577fb00.aspx</guid>
      <link>http://www.codeassassin.com/blog/PermaLink,guid,41a7b075-4ae8-4742-a3b1-0df55577fb00.aspx</link>
      <pubDate>Tue, 14 Oct 2008 11:12:36 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
I was recently inspired by a &lt;a href="http://stackoverflow.com/questions/152250/get-class-property-name" target="_blank"&gt;question&#xD;
about property names in strings&lt;/a&gt; on &lt;a href="http://stackoverflow.com/" target="_blank"&gt;Stack&#xD;
Overflow&lt;/a&gt;. The problem is that Windows Forms data binding takes the names&#xD;
of properties to bind as string parameters and if these properties change or are removed,&#xD;
errors won't surface until the bound control is exercised at run-time. So, using &lt;a href="http://www.paulstovell.com/blog/" target="_blank"&gt;Paul's&lt;/a&gt;&lt;a href="http://www.paulstovell.com/blog/strongly-typed-property-names" target="_blank"&gt;strongly&#xD;
typed property name ideas&lt;/a&gt;, I propose this alternative syntax for programmatic&#xD;
data binding in Windows Forms:&#xD;
&lt;/p&gt;&#xD;
        &lt;pre class="c#" name="code"&gt;nameTextBox.Bind(t =&amp;gt; t.Text, aBindingSource, (Customer c) =&amp;gt; c.FirstName);&#xD;
// Binds the Text property on nameTextBox to the FirstName property&#xD;
// of the current Customer in aBindingSource, no string literals required.&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
And the following code to implement support for it:&#xD;
&lt;/p&gt;&#xD;
        &lt;pre class="c#" name="code"&gt;public static class ControlExtensions&#xD;
{&#xD;
    public static Binding Bind&amp;lt;TControl, TDataSourceItem&amp;gt;(this TControl control, Expression&amp;lt;Func&amp;lt;TControl, object&amp;gt;&amp;gt; controlProperty, object dataSource, Expression&amp;lt;Func&amp;lt;TDataSourceItem, object&amp;gt;&amp;gt; dataSourceProperty) where TControl: Control&#xD;
    {&#xD;
        return control.DataBindings.Add(PropertyName.For(controlProperty), dataSource, PropertyName.For(dataSourceProperty));&#xD;
    }&#xD;
}&#xD;
&#xD;
public static class PropertyName&#xD;
{&#xD;
    public static string For&amp;lt;T&amp;gt;(Expression&amp;lt;Func&amp;lt;T, object&amp;gt;&amp;gt; property)&#xD;
    {&#xD;
        var member = property.Body as MemberExpression;&#xD;
        if (null == member)&#xD;
        {&#xD;
            var unary = property.Body as UnaryExpression;&#xD;
            if (null != unary) member = unary.Operand as MemberExpression;&#xD;
        }&#xD;
        return null != member ? member.Member.Name : string.Empty;&#xD;
    }&#xD;
}&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
Thoughts? Overkill?&#xD;
&lt;/p&gt;&#xD;
        &lt;img width="0" height="0" src="http://www.codeassassin.com/blog/aggbug.ashx?id=41a7b075-4ae8-4742-a3b1-0df55577fb00"&gt;&lt;/img&gt;&#xD;
      &lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=OmFFIjNVbfE:Knz7Lj3HpUc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=OmFFIjNVbfE:Knz7Lj3HpUc:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=OmFFIjNVbfE:Knz7Lj3HpUc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?i=OmFFIjNVbfE:Knz7Lj3HpUc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=OmFFIjNVbfE:Knz7Lj3HpUc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?i=OmFFIjNVbfE:Knz7Lj3HpUc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=OmFFIjNVbfE:Knz7Lj3HpUc:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeAssassin/~4/OmFFIjNVbfE" height="1" width="1"/&gt;</description>
      <comments>http://www.codeassassin.com/blog/CommentView,guid,41a7b075-4ae8-4742-a3b1-0df55577fb00.aspx</comments>
      <category>.NET Framework</category>
    </item>
    <item>
      <trackback:ping>http://www.codeassassin.com/blog/Trackback.aspx?guid=3752f97b-bcc6-463c-9cbb-00f387d76c19</trackback:ping>
      <pingback:server>http://www.codeassassin.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.codeassassin.com/blog/PermaLink,guid,3752f97b-bcc6-463c-9cbb-00f387d76c19.aspx</pingback:target>
      <dc:creator>Jason</dc:creator>
      <wfw:comment>http://www.codeassassin.com/blog/CommentView,guid,3752f97b-bcc6-463c-9cbb-00f387d76c19.aspx</wfw:comment>
      <wfw:commentRss>http://www.codeassassin.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=3752f97b-bcc6-463c-9cbb-00f387d76c19</wfw:commentRss>
      
      <title>Binding... and IList&amp;lt;T&amp;gt; does not inherit from IList.</title>
      <guid isPermaLink="false">http://www.codeassassin.com/blog/PermaLink,guid,3752f97b-bcc6-463c-9cbb-00f387d76c19.aspx</guid>
      <link>http://www.codeassassin.com/blog/PermaLink,guid,3752f97b-bcc6-463c-9cbb-00f387d76c19.aspx</link>
      <pubDate>Mon, 04 Aug 2008 07:05:34 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
A note to myself, and to others who may find it useful:&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Use &lt;a href="http://msdn.microsoft.com/en-us/library/ms132397.aspx" target="_blank"&gt;System.Collections.ObjectModel.Collection&amp;lt;T&amp;gt;&lt;/a&gt; (or&#xD;
a subclass) as the return type for properties exposing collections of related items&#xD;
on your presentation model classes if you intend to bind to the relationships with&#xD;
Windows Forms &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.bindingsource.aspx" target="_blank"&gt;BindingSources&lt;/a&gt;.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Collection&amp;lt;T&amp;gt; appears to be the lowest-level type in Framework 3.5 that provides&#xD;
both the non-generic IList implementation as required by the binding system and also&#xD;
provides strongly-typed programmatic access to the elements of the collection. It&#xD;
is used as the base for BindingList&amp;lt;T&amp;gt;, ObservableCollection&amp;lt;T&amp;gt; and many&#xD;
others and you can easily inherit from it yourself.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Using a return type of IList&amp;lt;T&amp;gt; or ICollection&amp;lt;T&amp;gt; instead, which may be&#xD;
preferred for being less concrete, is &lt;strong&gt;not &lt;/strong&gt;sufficient as neither of&#xD;
these inherit from the non-generic IList and will fail to bind correctly (sometimes&#xD;
throwing exceptions) at run-time when the parent list of the bound relationship is&#xD;
empty.&#xD;
&lt;/p&gt;&#xD;
        &lt;img width="0" height="0" src="http://www.codeassassin.com/blog/aggbug.ashx?id=3752f97b-bcc6-463c-9cbb-00f387d76c19"&gt;&lt;/img&gt;&#xD;
      &lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=CDokuRKMJ5c:mEgp9C9qbVg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=CDokuRKMJ5c:mEgp9C9qbVg:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=CDokuRKMJ5c:mEgp9C9qbVg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?i=CDokuRKMJ5c:mEgp9C9qbVg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=CDokuRKMJ5c:mEgp9C9qbVg:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?i=CDokuRKMJ5c:mEgp9C9qbVg:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=CDokuRKMJ5c:mEgp9C9qbVg:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeAssassin/~4/CDokuRKMJ5c" height="1" width="1"/&gt;</description>
      <comments>http://www.codeassassin.com/blog/CommentView,guid,3752f97b-bcc6-463c-9cbb-00f387d76c19.aspx</comments>
      <category>.NET Framework</category>
    </item>
    <item>
      <trackback:ping>http://www.codeassassin.com/blog/Trackback.aspx?guid=d2cd786d-4233-4fd1-ba15-250fa33c8148</trackback:ping>
      <pingback:server>http://www.codeassassin.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.codeassassin.com/blog/PermaLink,guid,d2cd786d-4233-4fd1-ba15-250fa33c8148.aspx</pingback:target>
      <dc:creator>Jason</dc:creator>
      <wfw:comment>http://www.codeassassin.com/blog/CommentView,guid,d2cd786d-4233-4fd1-ba15-250fa33c8148.aspx</wfw:comment>
      <wfw:commentRss>http://www.codeassassin.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=d2cd786d-4233-4fd1-ba15-250fa33c8148</wfw:commentRss>
      
      <title>Adelaide Geek Dinner August 2008 Announcement</title>
      <guid isPermaLink="false">http://www.codeassassin.com/blog/PermaLink,guid,d2cd786d-4233-4fd1-ba15-250fa33c8148.aspx</guid>
      <link>http://www.codeassassin.com/blog/PermaLink,guid,d2cd786d-4233-4fd1-ba15-250fa33c8148.aspx</link>
      <pubDate>Fri, 01 Aug 2008 12:07:48 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
As &lt;a href="http://www.codeassassin.com/blog/PermaLink,guid,ac5db07c-f73c-40a2-9077-474025f3f953.aspx" target="_blank"&gt;promised&#xD;
in May&lt;/a&gt;, it is time for the August Geek Dinner, specifically the time will be 6:30pm&#xD;
on Saturday 16th August. Everyone seemed to enjoy the food and atmosphere of &lt;a href="http://www.cafeamore.com.au/" target="_blank"&gt;Caffe&#xD;
Amore&lt;/a&gt; on the corner of Pulteney and Pirie Streets last time so we'll be going&#xD;
there again this time.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
If you're already on the geek dinner mailing list from previous times expect an invitation&#xD;
shortly. If you've never been invited before or you think your invite may be lost&#xD;
in the mail, just contact me and I'll make sure you get included.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Please RSVP before Wednesday 13th August so I can finalise the booking with the restaurant.&#xD;
Hope to see you all there!&#xD;
&lt;/p&gt;&#xD;
        &lt;img width="0" height="0" src="http://www.codeassassin.com/blog/aggbug.ashx?id=d2cd786d-4233-4fd1-ba15-250fa33c8148"&gt;&lt;/img&gt;&#xD;
      &lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=LON_QfwtPy4:UyMJcjheFS4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=LON_QfwtPy4:UyMJcjheFS4:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=LON_QfwtPy4:UyMJcjheFS4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?i=LON_QfwtPy4:UyMJcjheFS4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=LON_QfwtPy4:UyMJcjheFS4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?i=LON_QfwtPy4:UyMJcjheFS4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=LON_QfwtPy4:UyMJcjheFS4:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeAssassin/~4/LON_QfwtPy4" height="1" width="1"/&gt;</description>
      <comments>http://www.codeassassin.com/blog/CommentView,guid,d2cd786d-4233-4fd1-ba15-250fa33c8148.aspx</comments>
      <category>Geek Dinner</category>
    </item>
    <item>
      <trackback:ping>http://www.codeassassin.com/blog/Trackback.aspx?guid=45aa2cca-09b4-4955-b573-5b8a915d4c25</trackback:ping>
      <pingback:server>http://www.codeassassin.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.codeassassin.com/blog/PermaLink,guid,45aa2cca-09b4-4955-b573-5b8a915d4c25.aspx</pingback:target>
      <dc:creator>Jason</dc:creator>
      <wfw:comment>http://www.codeassassin.com/blog/CommentView,guid,45aa2cca-09b4-4955-b573-5b8a915d4c25.aspx</wfw:comment>
      <wfw:commentRss>http://www.codeassassin.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=45aa2cca-09b4-4955-b573-5b8a915d4c25</wfw:commentRss>
      <slash:comments>1</slash:comments>
      
      <title>TFS Deployer Least Privilege</title>
      <guid isPermaLink="false">http://www.codeassassin.com/blog/PermaLink,guid,45aa2cca-09b4-4955-b573-5b8a915d4c25.aspx</guid>
      <link>http://www.codeassassin.com/blog/PermaLink,guid,45aa2cca-09b4-4955-b573-5b8a915d4c25.aspx</link>
      <pubDate>Sat, 05 Jul 2008 00:54:16 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
The original &lt;a href="http://www.codeplex.com/tfsdeployer" target="_blank"&gt;TFS Deployer&lt;/a&gt; attempted&#xD;
to access various restricted resources than effectively required it to run as an administrator&#xD;
user. Since some changes were made in February, Deployer can now be executed under&#xD;
a standard user account with some additional considerations which follow.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;strong&gt;Team Foundation Server Permissions&lt;/strong&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
The TFS Deployer service account must be a member of the Team Foundation Valid Users&#xD;
server-level group on the server specified by the TeamFoundationServerUrl config setting&#xD;
and also a member of the Readers project-level group for the Team Projects that Deployer&#xD;
will be monitoring.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
If you intend to make use of the &lt;a href="http://www.codeassassin.com/blog/PermaLink,guid,9121ee83-17b9-4b02-872c-d0a9e182aad8.aspx" target="_blank"&gt;Retain&#xD;
Build feature&lt;/a&gt;, the Deployer service account will also need the Write To Operational&#xD;
Build Store project-level permission on applicable Team Projects.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;strong&gt;PowerShell Execution Policy&lt;/strong&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
TFS Deployer can execute Windows Command Scripts if you really need it to but PowerShell&#xD;
scripts are the preferred option. However, PowerShell is built to be secure-by-default&#xD;
and installs with script-running capabilities disabled. It is left for the user to&#xD;
enable scripts after PowerShell has been installed and can be performed by opening&#xD;
the PowerShell console as an administrator and executing either:&#xD;
&lt;/p&gt;&#xD;
        &lt;pre&gt;Set-ExecutionPolicy AllSigned ; # or&lt;br&gt;&#xD;
Set-ExecutionPolicy RemoteSigned&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
The former choice will require you to sign all your deployment scripts in source control&#xD;
with a certificate trusted by the Deployer. &lt;a href="http://www.hanselman.com/blog/" target="_blank"&gt;Scott&#xD;
Hanselman&lt;/a&gt; has a comprehensive post on his blog describing the &lt;a href="http://www.hanselman.com/blog/SigningPowerShellScripts.aspx" target="_blank"&gt;signing&#xD;
process&lt;/a&gt;. The latter choice &lt;a href="http://blogs.msdn.com/powershell/archive/2007/03/07/how-does-the-remotesigned-execution-policy-work.aspx" target="_blank"&gt;will&#xD;
not impose this requirement&lt;/a&gt; because files retrieved from source control by Deployer&#xD;
are not marked with a zone identifier.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;strong&gt;HTTP Namespace Reservation&lt;/strong&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
TFS Deployer utilises self-hosted WCF over HTTP to subscribe to Build Quality Change&#xD;
events from TFS. This technique relies on the Windows HTTP Server API which requires&#xD;
the Deployer service account to have been granted rights to listen on the portion&#xD;
of the HTTP URL namespace it uses for event notification. By default only local administrators&#xD;
have access to the entire namespace and permissions must be granted using the httpcfg&#xD;
tool (on Windows XP and Server 2003) or the netsh tool (on Vista and Server 2008).&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Using the netsh tool, from an administrator command prompt, the following command&#xD;
(as a single line) will grant rights to the appropriate URL for TFS Deployer (assuming&#xD;
you are using the default port number):&#xD;
&lt;/p&gt;&#xD;
        &lt;pre&gt;netsh http add urlacl url=http://+:8881/BuildStatusChangeEvent user=DOMAIN\TfsDeployerUser&lt;/pre&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a href="http://msdn.microsoft.com/en-us/library/ms733768.aspx" target="_blank"&gt;Using&#xD;
the httpcfg tool&lt;/a&gt; is more difficult as it requires an ACL string in Security Descriptor&#xD;
Definition Language (SDDL). However, &lt;a href="http://www.leastprivilege.com/" target="_blank"&gt;Dominick&#xD;
Baier&lt;/a&gt; has &lt;a href="http://www.leastprivilege.com/URIACLsAndWCFRevisited.aspx" target="_blank"&gt;created&#xD;
a tool&lt;/a&gt; to simplify this process and I can recommend it. &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;strong&gt;Additional Permissions&lt;/strong&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
All deployment scripts executed by TFS Deployer will be executed under the context&#xD;
of the service account unless the scripts explicitly contain alternate credentials.&#xD;
If the scripts copy files to a network share, configure a web site in IIS, or even&#xD;
upgrade the schema of a SQL database, ensure that the service account also has the&#xD;
minimum privileges to perform those actions too.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Any problems, questions, or suggestions... let me know.&#xD;
&lt;/p&gt;&#xD;
        &lt;img width="0" height="0" src="http://www.codeassassin.com/blog/aggbug.ashx?id=45aa2cca-09b4-4955-b573-5b8a915d4c25"&gt;&lt;/img&gt;&#xD;
      &lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=Y3pOWJNT8I0:H10Q3mhYqgo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=Y3pOWJNT8I0:H10Q3mhYqgo:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=Y3pOWJNT8I0:H10Q3mhYqgo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?i=Y3pOWJNT8I0:H10Q3mhYqgo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=Y3pOWJNT8I0:H10Q3mhYqgo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?i=Y3pOWJNT8I0:H10Q3mhYqgo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=Y3pOWJNT8I0:H10Q3mhYqgo:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeAssassin/~4/Y3pOWJNT8I0" height="1" width="1"/&gt;</description>
      <comments>http://www.codeassassin.com/blog/CommentView,guid,45aa2cca-09b4-4955-b573-5b8a915d4c25.aspx</comments>
      <category>Least Privilege;PowerShell;Team Foundation Server</category>
    </item>
    <item>
      <trackback:ping>http://www.codeassassin.com/blog/Trackback.aspx?guid=9121ee83-17b9-4b02-872c-d0a9e182aad8</trackback:ping>
      <pingback:server>http://www.codeassassin.com/blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.codeassassin.com/blog/PermaLink,guid,9121ee83-17b9-4b02-872c-d0a9e182aad8.aspx</pingback:target>
      <dc:creator>Jason</dc:creator>
      <wfw:comment>http://www.codeassassin.com/blog/CommentView,guid,9121ee83-17b9-4b02-872c-d0a9e182aad8.aspx</wfw:comment>
      <wfw:commentRss>http://www.codeassassin.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=9121ee83-17b9-4b02-872c-d0a9e182aad8</wfw:commentRss>
      
      <title>Explaining new features in TFS Deployer</title>
      <guid isPermaLink="false">http://www.codeassassin.com/blog/PermaLink,guid,9121ee83-17b9-4b02-872c-d0a9e182aad8.aspx</guid>
      <link>http://www.codeassassin.com/blog/PermaLink,guid,9121ee83-17b9-4b02-872c-d0a9e182aad8.aspx</link>
      <pubDate>Wed, 02 Jul 2008 13:35:22 GMT</pubDate>
      <description>&lt;body xmlns="http://www.w3.org/1999/xhtml"&gt;&#xD;
        &lt;p&gt;&#xD;
Since I began helping &lt;a href="http://notgartner.wordpress.com/" target="_blank"&gt;Mitch&lt;/a&gt; with&#xD;
changes to &lt;a href="http://www.codeplex.com/tfsdeployer" target="_blank"&gt;TFS Deployer&lt;/a&gt; to&#xD;
make it compatible with TFS 2008, I have slowly been adding small features that seemed&#xD;
useful in my work environment. However, unless you've read the code, you probably&#xD;
wouldn't know they exist so I'll describe them here.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;strong&gt;Quality Mapping Wildcard&lt;/strong&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
TFS Deployer operates on executing scripts for particular build quality transitions.&#xD;
Normally transitions like "Test" to "Production" are common. However you may wish&#xD;
to have a script that runs when the quality is set to "QA" regardless of what is was&#xD;
before. You can now specify asterisk (*) in place of the value of either of the OriginalQuality&#xD;
or the NewQuality attributes in the DeploymentMappings.xml file to specify a match&#xD;
on any quality. &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;strong&gt;Retain Build&lt;/strong&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Team Build in TFS 2008 now has Retention Policies to clean out old builds. If you&#xD;
deploy a build with TFS Deployer you don't want the policy deleting the build outputs.&#xD;
You may also want builds to become subject to policy again after you retire them from&#xD;
failed acceptance testing. You can add a RetainBuild attribute to a Mapping element&#xD;
in the D*M*.xml file. A value of "true" will mark the build to be kept upon successful&#xD;
execution of the deployment script. A value of "false" will unmark it, and an absent&#xD;
attribute will leave the retain flag alone.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;strong&gt;Shared Deployment Resources&lt;/strong&gt;&#xD;
        &lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
With multiple Team Builds defined and multiple deployment configurations you're bound&#xD;
to end up with scripts with common components you'd like to refactor out to a shared&#xD;
location. You can now specify a TFS path (ie $/MyProj/TeamBuildTypes/Shared/Deployment/)&#xD;
in the TfsDeployer.exe.config file in the SharedResourceServerPath application setting.&#xD;
If provided TFS Deployer will get the files in this directory and place them in the&#xD;
same folder as the deployment script on each script run.&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
The first two features are in the &lt;a href="http://www.codeplex.com/tfsdeployer/Release/ProjectReleases.aspx" target="_blank"&gt;latest&#xD;
release drop&lt;/a&gt; on CodePlex. The latter is only in the latest change set, so check&#xD;
the &lt;a href="http://www.codeplex.com/tfsdeployer/SourceControl/ListDownloadableCommits.aspx" target="_blank"&gt;Source&#xD;
Code&lt;/a&gt; tab if you intend to use shared resources. Any problems, questions, or suggestions...&#xD;
let me know.&#xD;
&lt;/p&gt;&#xD;
        &lt;img width="0" height="0" src="http://www.codeassassin.com/blog/aggbug.ashx?id=9121ee83-17b9-4b02-872c-d0a9e182aad8"&gt;&lt;/img&gt;&#xD;
      &lt;/body&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=isOdVhsm5Ec:FehX_Zd-8gs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=isOdVhsm5Ec:FehX_Zd-8gs:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=isOdVhsm5Ec:FehX_Zd-8gs:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?i=isOdVhsm5Ec:FehX_Zd-8gs:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=isOdVhsm5Ec:FehX_Zd-8gs:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?i=isOdVhsm5Ec:FehX_Zd-8gs:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/CodeAssassin?a=isOdVhsm5Ec:FehX_Zd-8gs:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodeAssassin?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodeAssassin/~4/isOdVhsm5Ec" height="1" width="1"/&gt;</description>
      <comments>http://www.codeassassin.com/blog/CommentView,guid,9121ee83-17b9-4b02-872c-d0a9e182aad8.aspx</comments>
      <category>Team Foundation Server</category>
    </item>
  </channel>
</rss>
