<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Meandering thoughts</title>
	<atom:link href="http://magpie.sytes.net/jesperhogstrom/feed/" rel="self" type="application/rss+xml" />
	<link>http://magpie.sytes.net/jesperhogstrom</link>
	<description>Words are flying out like endless rain into a paper cup.</description>
	<lastBuildDate>Sat, 28 Jan 2012 13:25:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<item>
		<title>Foundations of a dev team</title>
		<link>http://magpie.sytes.net/jesperhogstrom/2012/01/foundations-of-a-dev-team/</link>
		<comments>http://magpie.sytes.net/jesperhogstrom/2012/01/foundations-of-a-dev-team/#comments</comments>
		<pubDate>Fri, 27 Jan 2012 23:43:41 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[development infrastructure]]></category>

		<guid isPermaLink="false">http://magpie.sytes.net/jesperhogstrom/?p=578</guid>
		<description><![CDATA[Last week I spoke to an old friend about what fundamental advice to give to a development team. There are many areas that needs catering to. I tend to start with setting up a machinery into which you put source code and out comes a nicely packaged installer. And then the rest will follow, sort [...]]]></description>
			<content:encoded><![CDATA[<p>Last week I spoke to an old friend about what fundamental advice to give to a development team. There are many areas that needs catering to. I tend to start with setting up a machinery into which you put source code and out comes a nicely packaged installer. And then the rest will follow, sort of <img src='http://magpie.sytes.net/jesperhogstrom/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Here is my list of build machine/infrastructure centered focus areas &#8211; some technical and some attitude based.</p>
<p>* Use a source control system &#8211; be it svn, git, p4 or something else.<br />
* Use a build machine (TeamCity, CC.Net, Cruise, Jenkins, &#8230;)<br />
* Make that build machine trigger a compile of everything on check-in.<br />
* Write unit tests.<br />
* Run the unit tests on build machine after the checkin-build.<br />
* Run static checkers and source analysis (fxcop, stylecop, cppcheck, cpplint) on the build machine on each check-in.<br />
* Break the build on failure.<br />
* Make build failures obvious (lava-lamps are great!).<br />
* Foster a culture of checking in often.<br />
* Foster a culture of keeping build-broken times to a minimum.<br />
* Do not assign shame to a broken build.<br />
* Make sure whatever your build machine does can be executed on every developer machine.</p>
<p>The above statements leave a lot to be worked out, I know. However, no matter how you solve it you are better off if you do! </p>
<p>If this seems like a tall order, you&#8217;ll probably need some help. Not to worry! The internet is full of advice. </p>
<p>Have fun setting up your team and the machinery to support it. I do look forward to your input!</p>
<p>&#8211;Jesper Hogstrom</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fmagpie.sytes.net%2Fjesperhogstrom%2F2012%2F01%2Ffoundations-of-a-dev-team%2F&amp;title=Foundations%20of%20a%20dev%20team"><img src="http://magpie.sytes.net/jesperhogstrom/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://magpie.sytes.net/jesperhogstrom/2012/01/foundations-of-a-dev-team/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Jesper Got Published: TWIM #21</title>
		<link>http://magpie.sytes.net/jesperhogstrom/2012/01/jesper-got-published-twim-21/</link>
		<comments>http://magpie.sytes.net/jesperhogstrom/2012/01/jesper-got-published-twim-21/#comments</comments>
		<pubDate>Sun, 15 Jan 2012 18:27:02 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[internet media]]></category>
		<category><![CDATA[mp3]]></category>
		<category><![CDATA[personligt]]></category>
		<category><![CDATA[letters]]></category>
		<category><![CDATA[twim]]></category>

		<guid isPermaLink="false">http://magpie.sytes.net/jesperhogstrom/?p=575</guid>
		<description><![CDATA[I wrote a letter about what cancer is to This Week In Microbiology, and it got published in episode #21. Here&#8217;s the letter: &#160; Dear Vincent, the other day I was in a discussion about what can get cancer, something that ultimately boiled down to what cancer really is. Our reasoning went along the lines [...]]]></description>
			<content:encoded><![CDATA[<p>I wrote a letter about what cancer is to<a href="http://www.microbeworld.org/index.php?option=com_content&amp;view=category&amp;id=107:this-week-in-microbiology&amp;layout=blog&amp;Itemid=275" target="_blank"> This Week In Microbiology</a>, and it got published in <a href="http://www.microbeworld.org/index.php?option=com_content&amp;view=article&amp;id=1076:twim-21-symbiotic-margheritas&amp;catid=107:this-week-in-microbiology&amp;Itemid=275">episode #21</a>. Here&#8217;s the letter:</p>
<p>&nbsp;</p>
<p><em>Dear Vincent,</em></p>
<p><em>the other day I was in a discussion about what can get cancer, something that ultimately boiled down to what cancer really is. Our reasoning went along the lines of establishing that there are organisms containing any number of cells, ranging from one and up. If I remember correctly, C. Elegans has 957 cells. Presumably there is some organism with 956, 955 and so on.</em></p>
<p><em>It seems it doesn&#8217;t make any sense to talk about a one celled organism developing cancer &#8211; though I am interested to have that confirmed! The nematode just mentioned has cell specialization, so it could presumably develop some form of cancer. What is the lower limit of cells an organism must have to succumb to the decease or should the question really be posed in a completely different way?</em></p>
<p><em>Also, some organisms of very few cells occasionally gang up and form a super-organism. This includes some slime moulds and the pre-larvae state of jelly fish. Can such &#8220;temporary&#8221; organisms develop cancer?</em></p>
<p><em>The question is grander than just parasites, and I have a feeling that viruses, living or not, have no propensity to develop cancer. Hence my addressing the question to TWIM.</em></p>
<p><em>While I have your attention, allow me to once again thank you and everyone in each of the podcast teams for your effort in sharing your knowledge and doing it in such an enjoyable tone and fashion.</em></p>
<p><em>All the best,</em></p>
<p><em>Jesper</em><br />
<em>Software architect</em><br />
<em>Sweden</em></p>
<p>The question is answered by Vincent andElio near the end of the show.</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fmagpie.sytes.net%2Fjesperhogstrom%2F2012%2F01%2Fjesper-got-published-twim-21%2F&amp;title=Jesper%20Got%20Published%3A%20TWIM%20%2321"><img src="http://magpie.sytes.net/jesperhogstrom/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://magpie.sytes.net/jesperhogstrom/2012/01/jesper-got-published-twim-21/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Recursive msbuild</title>
		<link>http://magpie.sytes.net/jesperhogstrom/2011/12/recursive-msbuild/</link>
		<comments>http://magpie.sytes.net/jesperhogstrom/2011/12/recursive-msbuild/#comments</comments>
		<pubDate>Tue, 06 Dec 2011 04:07:15 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[development infrastructure]]></category>
		<category><![CDATA[msbuild]]></category>
		<category><![CDATA[recursion]]></category>

		<guid isPermaLink="false">http://magpie.sytes.net/jesperhogstrom/?p=567</guid>
		<description><![CDATA[Today a co-worker asked me a really interesting thing about msbuild. He wanted to extract some information about the binary he just compiled into a textfile and add that file as a resource to the binary he just compiled. It is worth mentioning he had a really good reason to do this as well. The [...]]]></description>
			<content:encoded><![CDATA[<p>Today a co-worker asked me a really interesting thing about msbuild. He wanted to extract some information about the binary he just compiled into a textfile and add that file as a resource to the binary he just compiled. It is worth mentioning he had a really good reason to do this as well.</p>
<p>The good reason and the fact that it was quite an interesting question got me thinking on how to do that with minimal effort. Minimal effort is always a good sign of a lazy programmer, and lazy programmers are better. At least that&#8217;s what I read somewhere <img src='http://magpie.sytes.net/jesperhogstrom/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>First of all, it wouldn&#8217;t be possible to simply call the target Build again, as msbuild doesn&#8217;t invoke the same target twice in one run.</p>
<p>I figured it&#8217;d be necessary to call msbuild again, and in the recursively invoked msbuild to all the tricks.</p>
<p>First off, I wrote a simple program to extract some information from a binary file.</p>
<div class="codecolorer-container csharp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0600FF;">namespace</span> GenApi<br />
<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">using</span> <span style="color: #000000;">System</span>.<span style="color: #0000FF;">Reflection</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #FF0000;">class</span> Program<br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">static</span> <span style="color: #0600FF;">void</span> Main<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span><span style="color: #000000;">&#91;</span><span style="color: #000000;">&#93;</span> args<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var a = Assembly.<span style="color: #0000FF;">LoadFrom</span><span style="color: #000000;">&#40;</span>args<span style="color: #000000;">&#91;</span><span style="color: #FF0000;">0</span><span style="color: #000000;">&#93;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span>var type <span style="color: #0600FF;">in</span> a.<span style="color: #0000FF;">GetTypes</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span>type.<span style="color: #0000FF;">FullName</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<span style="color: #000000;">&#125;</span></div></div>
<p>Not overly complex, but good enough for demonstration purposes. I compiled this to genapi.exe and moved it to the root folder of the project I wanted to tamper with. </p>
<p>Msbuild is a quite powerful system, and it has numerous extension points. One of these is to override &#8211; or actually redeclare &#8211; a target named AfterBuild. This target is invoked after the chain of targets pertaining to build is complete. The default implementation of AfterBuild is to do nothing.</p>
<p>At this point I need to mention the importance of understanding the build system used. There are quite a number of problems that can and should be solved by extending and enhancing the build process. The first step on that journey to enlightenment is to start thinking about the build system as part of the product development infrastructure. It is not just some mumbo-jumbo mixed with two bottles of magic that happened to ship with .Net and Visual Studio. It is an orchestration environment of quite some power.</p>
<p>Anyway, start with right-clicking the project node in the solution explorer and select Unload project. Right-click the same node again and select &#8216;Edit&#8230;&#8217;. You&#8217;ll now get the csproj file as a textfile in your source editor in VS.</p>
<p>The end of the project file looks like</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"> &nbsp;<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Import</span> <span style="color: #000066;">Project</span>=<span style="color: #ff0000;">&quot;$(MSBuildToolsPath)\Microsoft.CSharp.targets&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #808080; font-style: italic;">&lt;!-- To modify your build process, add your task inside one of the targets below and uncomment it. <br />
&nbsp; &nbsp; &nbsp; &nbsp;Other similar extension points exist, see Microsoft.Common.targets.<br />
&nbsp; &lt;Target Name=&quot;BeforeBuild&quot;&gt;</span><br />
</span><br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Target<span style="font-weight: bold; color: black;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Target</span> <span style="color: #000066;">Name</span>=<span style="color: #ff0000;">&quot;AfterBuild&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Target<span style="font-weight: bold; color: black;">&gt;</span></span></span><br />
&nbsp; --&gt;<br />
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Project<span style="font-weight: bold; color: black;">&gt;</span></span></span></div></div>
<p>This is exactly what we want to do. First, to try the waters, I wrote a simple AfterBuild target just to make sure it got executed.</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Target</span> <span style="color: #000066;">Name</span>=<span style="color: #ff0000;">&quot;AfterBuild&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><br />
&nbsp; &nbsp;<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Error</span> <span style="color: #000066;">Text</span>=<span style="color: #ff0000;">&quot;Yes, AfterBuild works...&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span><br />
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Target<span style="font-weight: bold; color: black;">&gt;</span></span></span></div></div>
<p>Reload the project file, and turn on more logging by selecting Tools | Options | Projects and Solutions | Build and Run and go for Normal in both the combo-boxes. View output from build by Ctrl-W, O.</p>
<p>Rebuild and you&#8217;ll get something like</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">GenerateTargetFrameworkMonikerAttribute:<br />
Skipping target &quot;GenerateTargetFrameworkMonikerAttribute&quot; because all output files are up-to-date with respect to the input files.<br />
CopyFilesToOutputDirectory:<br />
&nbsp; IncludeMe -&gt; c:\users\jhm\documents\visual studio 2010\Projects\SelfInclusion\IncludeMe\bin\Debug\IncludeMe.exe<br />
c:\users\jhm\documents\visual studio 2010\Projects\SelfInclusion\IncludeMe\IncludeMe.csproj(56,5): error : Yes, AfterBuild works...<br />
<br />
Build FAILED.</div></div>
<p>Great. Build failed.</p>
<p>Now let&#8217;s do some serious work.</p>
<p>What we need is to generate the &#8220;api&#8221;. The target for this looks like</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"> &nbsp;<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Target</span> <span style="color: #000066;">Name</span>=<span style="color: #ff0000;">&quot;GenerateApi&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">Inputs</span>=<span style="color: #ff0000;">&quot;$(OutputPath)\$(AssemblyName).exe&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">Outputs</span>=<span style="color: #ff0000;">&quot;api.txt&quot;</span> <span style="font-weight: bold; color: black;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Exec</span> <span style="color: #000066;">Command</span>=<span style="color: #ff0000;">&quot;genapi.exe $(OutputPath)\$(AssemblyName).exe &amp;gt; api.txt&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Target<span style="font-weight: bold; color: black;">&gt;</span></span></span></div></div>
<p>The generated file, &#8216;api.txt&#8217; needs to be included. We could in theory add it to the project once we have it, but imho it makes much more sense to only add it after it is generated. Thus, we need to modify the Resource item. To avoid doing that too early, this must be done in a target as well. Manipulating items and properties in targets is msbuild&#8217;s way to handle deferred evaluation.</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"> &nbsp;<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Target</span> <span style="color: #000066;">Name</span>=<span style="color: #ff0000;">&quot;AddResource&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;ItemGroup<span style="font-weight: bold; color: black;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Resource</span> <span style="color: #000066;">Include</span>=<span style="color: #ff0000;">&quot;api.txt&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/ItemGroup<span style="font-weight: bold; color: black;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Target<span style="font-weight: bold; color: black;">&gt;</span></span></span></div></div>
<p>Now what with the afterbuild target? There are many ways to skin a cat, and I opted for two invocations of the csproj file, first to generate the resource, and then to rebuild the project with the freshly generated file.</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"> &nbsp;<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Target</span> <span style="color: #000066;">Name</span>=<span style="color: #ff0000;">&quot;AfterBuild&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;MSBuild</span> <span style="color: #000066;">Projects</span>=<span style="color: #ff0000;">&quot;Includeme.csproj&quot;</span> <span style="color: #000066;">Targets</span>=<span style="color: #ff0000;">&quot;GenerateApi&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;MSBuild</span> <span style="color: #000066;">Projects</span>=<span style="color: #ff0000;">&quot;Includeme.csproj&quot;</span> <span style="color: #000066;">Targets</span>=<span style="color: #ff0000;">&quot;Build&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Target<span style="font-weight: bold; color: black;">&gt;</span></span></span></div></div>
<p>However, the code above suffers from a serious mistake. When msbuild is invoked for the second time, it will surely call build, but it will also end up in the AfterBuild-target and call itself again. Infinite recursion. Not good. To prevent this from happening, we need to pass a token indicating we&#8217;re in level two, and also check that before executing anything. Improved version looks like</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"> &nbsp;<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Target</span> <span style="color: #000066;">Name</span>=<span style="color: #ff0000;">&quot;AfterBuild&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;MSBuild</span> <span style="color: #000066;">Projects</span>=<span style="color: #ff0000;">&quot;Includeme.csproj&quot;</span> <span style="color: #000066;">Targets</span>=<span style="color: #ff0000;">&quot;GenerateApi&quot;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">Condition</span>=<span style="color: #ff0000;">&quot;'$(second)' == ''&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;MSBuild</span> <span style="color: #000066;">Projects</span>=<span style="color: #ff0000;">&quot;Includeme.csproj&quot;</span> <span style="color: #000066;">Targets</span>=<span style="color: #ff0000;">&quot;Build&quot;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">Properties</span>=<span style="color: #ff0000;">&quot;second=true&quot;</span> <span style="color: #000066;">Condition</span>=<span style="color: #ff0000;">&quot;'$(second)' == ''&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Target<span style="font-weight: bold; color: black;">&gt;</span></span></span></div></div>
<p>Much better! However, when are we calling the AddResource-target? To fix that we need to do some indirection, as msbuild doesn&#8217;t seem to commit item changes to global scope until a target is completed. Thus, instead of invoking the Build-target, we invoke a new target named SecondBuild. It in turn depends on AddResource and Build.</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Target</span> <span style="color: #000066;">Name</span>=<span style="color: #ff0000;">&quot;SecondBuild&quot;</span> <span style="color: #000066;">DependsOnTargets</span>=<span style="color: #ff0000;">&quot;AddResource;Build&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span></div></div>
<p>The complete code that works thus looks like:</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"> &nbsp;<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Target</span> <span style="color: #000066;">Name</span>=<span style="color: #ff0000;">&quot;AfterBuild&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;MSBuild</span> <span style="color: #000066;">Projects</span>=<span style="color: #ff0000;">&quot;Includeme.csproj&quot;</span> <span style="color: #000066;">Targets</span>=<span style="color: #ff0000;">&quot;GenerateApi&quot;</span> <span style="color: #000066;">Condition</span>=<span style="color: #ff0000;">&quot;'$(second)' == ''&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;MSBuild</span> <span style="color: #000066;">Projects</span>=<span style="color: #ff0000;">&quot;Includeme.csproj&quot;</span> <span style="color: #000066;">Targets</span>=<span style="color: #ff0000;">&quot;SecondBuild&quot;</span> <span style="color: #000066;">Properties</span>=<span style="color: #ff0000;">&quot;second=true&quot;</span> <span style="color: #000066;">Condition</span>=<span style="color: #ff0000;">&quot;'$(second)' == ''&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Target<span style="font-weight: bold; color: black;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Target</span> <span style="color: #000066;">Name</span>=<span style="color: #ff0000;">&quot;SecondBuild&quot;</span> <span style="color: #000066;">DependsOnTargets</span>=<span style="color: #ff0000;">&quot;AddResource;Build&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Target</span> <span style="color: #000066;">Name</span>=<span style="color: #ff0000;">&quot;GenerateApi&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">Inputs</span>=<span style="color: #ff0000;">&quot;$(OutputPath)\$(AssemblyName).exe&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">Outputs</span>=<span style="color: #ff0000;">&quot;api.txt&quot;</span> <span style="font-weight: bold; color: black;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Exec</span> <span style="color: #000066;">Command</span>=<span style="color: #ff0000;">&quot;genapi.exe $(OutputPath)\$(AssemblyName).exe &amp;gt; api.txt&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Target<span style="font-weight: bold; color: black;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Target</span> <span style="color: #000066;">Name</span>=<span style="color: #ff0000;">&quot;AddResource&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;ItemGroup<span style="font-weight: bold; color: black;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Resource</span> <span style="color: #000066;">Include</span>=<span style="color: #ff0000;">&quot;api.txt&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/ItemGroup<span style="font-weight: bold; color: black;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Target<span style="font-weight: bold; color: black;">&gt;</span></span></span></div></div>
<p>Staying true to the agile programming cycle, this is where one should pause and refactor. Could the code be written any cleaner? Do we need two invocations of msbuild? As it turns out, no, not really. The same effect can be achieved with the following, more compact version:</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"> &nbsp;<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Target</span> <span style="color: #000066;">Name</span>=<span style="color: #ff0000;">&quot;AfterBuild&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;MSBuild</span> <span style="color: #000066;">Projects</span>=<span style="color: #ff0000;">&quot;Includeme.csproj&quot;</span> <span style="color: #000066;">Targets</span>=<span style="color: #ff0000;">&quot;GenerateApi;AddResource;Build&quot;</span> <span style="color: #000066;">Properties</span>=<span style="color: #ff0000;">&quot;second=true&quot;</span> <span style="color: #000066;">Condition</span>=<span style="color: #ff0000;">&quot;'$(second)' == ''&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Target<span style="font-weight: bold; color: black;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Target</span> <span style="color: #000066;">Name</span>=<span style="color: #ff0000;">&quot;GenerateApi&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">Inputs</span>=<span style="color: #ff0000;">&quot;$(OutputPath)\$(AssemblyName).exe&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">Outputs</span>=<span style="color: #ff0000;">&quot;api.txt&quot;</span> <span style="font-weight: bold; color: black;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Exec</span> <span style="color: #000066;">Command</span>=<span style="color: #ff0000;">&quot;genapi.exe $(OutputPath)\$(AssemblyName).exe &amp;gt; api.txt&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Target<span style="font-weight: bold; color: black;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Target</span> <span style="color: #000066;">Name</span>=<span style="color: #ff0000;">&quot;AddResource&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;ItemGroup<span style="font-weight: bold; color: black;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Resource</span> <span style="color: #000066;">Include</span>=<span style="color: #ff0000;">&quot;api.txt&quot;</span> <span style="font-weight: bold; color: black;">/&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/ItemGroup<span style="font-weight: bold; color: black;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Target<span style="font-weight: bold; color: black;">&gt;</span></span></span></div></div>
<p>There you go. A simple way to include information about a binary in the binary itself. All from one Build request from inside VS.</p>
<p>A very interesting question and a fairly simple and clean answer. </p>
<p>Happy building!</p>
<p>&#8211;Jesper</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fmagpie.sytes.net%2Fjesperhogstrom%2F2011%2F12%2Frecursive-msbuild%2F&amp;title=Recursive%20msbuild"><img src="http://magpie.sytes.net/jesperhogstrom/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://magpie.sytes.net/jesperhogstrom/2011/12/recursive-msbuild/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Setting up an msbuild script system</title>
		<link>http://magpie.sytes.net/jesperhogstrom/2011/05/setting-up-an-msbuild-script-system/</link>
		<comments>http://magpie.sytes.net/jesperhogstrom/2011/05/setting-up-an-msbuild-script-system/#comments</comments>
		<pubDate>Tue, 17 May 2011 20:56:48 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[development infrastructure]]></category>
		<category><![CDATA[build systems]]></category>
		<category><![CDATA[msbuild]]></category>

		<guid isPermaLink="false">http://magpie.sytes.net/jesperhogstrom/?p=559</guid>
		<description><![CDATA[msbuild is not all that hard, but it does come with a whole slew of parameters. You don&#8217;t want to memorize them all. Thus, define a good ol&#8217; batch file to launch msbuild: @echo off set msbuild20=C:\Windows\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe set msbuild35=C:\Windows\Microsoft.NET\Framework\v3.5\MSBuild.exe set msbuild40=C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe set msbuild=%msbuild40% set log_quiet=/v:q set log_minimal=/v:m set log_normal=/v:n set log_detailed=/v:d set log_diag=/v:diag set _loglevel=%log_normal% [...]]]></description>
			<content:encoded><![CDATA[<p>msbuild is not all that hard, but it does come with a whole slew of parameters. You don&#8217;t want to memorize them all. Thus, define a good ol&#8217; batch file to launch msbuild:</p>
<div class="codecolorer-container dos default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">@<span style="color: #b1b100; font-weight: bold;">echo</span> off<br />
<span style="color: #b1b100; font-weight: bold;">set</span> <span style="color: #448844;">msbuild20</span>=C:\Windows\Microsoft.NET\Framework\v2<span style="">.0</span><span style="">.50727</span>\MSBuild.exe<br />
<span style="color: #b1b100; font-weight: bold;">set</span> <span style="color: #448844;">msbuild35</span>=C:\Windows\Microsoft.NET\Framework\v3<span style="">.5</span>\MSBuild.exe<br />
<span style="color: #b1b100; font-weight: bold;">set</span> <span style="color: #448844;">msbuild40</span>=C:\Windows\Microsoft.NET\Framework\v4<span style="">.0</span><span style="">.30319</span>\MSBuild.exe<br />
<br />
<span style="color: #b1b100; font-weight: bold;">set</span> <span style="color: #448844;">msbuild</span>=%<span style="color: #448888;">msbuild40</span>%<br />
<br />
<span style="color: #b1b100; font-weight: bold;">set</span> <span style="color: #448844;">log_quiet</span>=/v:q<br />
<span style="color: #b1b100; font-weight: bold;">set</span> <span style="color: #448844;">log_minimal</span>=/v:m<br />
<span style="color: #b1b100; font-weight: bold;">set</span> <span style="color: #448844;">log_normal</span>=/v:n<br />
<span style="color: #b1b100; font-weight: bold;">set</span> <span style="color: #448844;">log_detailed</span>=/v:d<br />
<span style="color: #b1b100; font-weight: bold;">set</span> <span style="color: #448844;">log_diag</span>=/v:diag<br />
<br />
<span style="color: #b1b100; font-weight: bold;">set</span> <span style="color: #448844;">_loglevel</span>=%<span style="color: #448888;">log_normal</span>%<br />
<br />
<span style="color: #b1b100; font-weight: bold;">set</span> <span style="color: #448844;">projectfile</span>=build.msproj<br />
<br />
:<span style="color: #b100b1; font-weight: bold;">start</span><br />
<span style="color: #b1b100; font-weight: bold;">set</span> <span style="color: #448844;">target</span>=<br />
<span style="color: #00b100; font-weight: bold;">if</span> &quot;%<span style="color: #448888;"><span style="">1</span></span>&quot; != &quot;&quot; <span style="color: #b1b100; font-weight: bold;">set</span> <span style="color: #448844;">target</span>=/t:%<span style="color: #448888;"><span style="">1</span></span><br />
%<span style="color: #448888;">msbuild</span>% %<span style="color: #448888;">_loglevel</span>% %<span style="color: #448888;">target</span>% %<span style="color: #448888;">projectfile</span>%<br />
<span style="color: #b1b100; font-weight: bold;">shift</span><br />
<span style="color: #00b100; font-weight: bold;">if</span> &quot;%<span style="color: #448888;"><span style="">1</span></span>&quot; == &quot;&quot; <span style="color: #00b100; font-weight: bold;">goto</span> <span style="color: #b100b1; font-weight: bold;">nomoreparams</span><br />
<span style="color: #00b100; font-weight: bold;">goto</span> <span style="color: #b100b1; font-weight: bold;">start</span><br />
<br />
:<span style="color: #b100b1; font-weight: bold;">nomoreparams</span><br />
<span style="color: #00b100; font-weight: bold;">if</span> <span style="color: #000000; font-weight: bold;">ERRORLEVEL</span> <span style="">1</span> <span style="color: #00b100; font-weight: bold;">goto</span> <span style="color: #b100b1; font-weight: bold;">error</span><br />
<span style="color: #b1b100; font-weight: bold;">echo</span> Build completed. Congratulations!<br />
<span style="color: #00b100; font-weight: bold;">goto</span> <span style="color: #b100b1; font-weight: bold;">end</span><br />
<br />
:<span style="color: #b100b1; font-weight: bold;">error</span><br />
<span style="color: #b1b100; font-weight: bold;">echo</span> There was an error. Sorry it didn't work out.<br />
<span style="color: #00b100; font-weight: bold;">goto</span> <span style="color: #b100b1; font-weight: bold;">end</span><br />
<br />
:<span style="color: #b100b1; font-weight: bold;">end</span></div></div>
<p>This simple little file will allow you to type things like <i>build debug</i> or <i>build release</i> without worrying exactly how to specify the target. If you want to make it extra nice, control log level with an environment variable, by adding the following line:</p>
<div class="codecolorer-container dos default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #b1b100; font-weight: bold;">set</span> <span style="color: #448844;">_loglevel</span>=%<span style="color: #448888;">log_normal</span>%<br />
<span style="color: #00b100; font-weight: bold;">if</span> &quot;loglevel%<span style="color: #448888;">&quot; != &quot;&quot; <span style="color: #b1b100; font-weight: bold;">set</span> <span style="color: #448844;">_loglevel</span>=</span>%loglevel% &nbsp;&lt;-- new line</div></div>
<p>simply <i>set loglevel=/v:n</i> from command line to change the log level.</p>
<p>You may also want to pass in some variables, like current directory</p>
<div class="codecolorer-container dos default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">%<span style="color: #448888;">msbuild</span>% %<span style="color: #448888;">_loglevel</span>% %<span style="color: #448888;">target</span>% /p:StartDir=%<span style="color: #448888;">CD</span>% %<span style="color: #448888;">projectfile</span>%</div></div>
<p>That will give you the property $(StartDir) available inside your project file.</p>
<p>Speaking of which, here&#8217;s a minimal sample:</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Project</span><br />
&nbsp; <span style="color: #000066;">ToolsVersion</span>=<span style="color: #ff0000;">&quot;4.0&quot;</span><br />
&nbsp; <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">&quot;http://schemas.microsoft.com/developer/msbuild/2003&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><br />
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Project<span style="font-weight: bold; color: black;">&gt;</span></span></span></div></div>
<p>Admittedly very bare bone.</p>
<p>Let&#8217;s add some meat:</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Project</span><br />
&nbsp; <span style="color: #000066;">DefaultTargets</span>=<span style="color: #ff0000;">&quot;Showhelp&quot;</span><br />
&nbsp; <span style="color: #000066;">ToolsVersion</span>=<span style="color: #ff0000;">&quot;4.0&quot;</span><br />
&nbsp; <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">&quot;http://schemas.microsoft.com/developer/msbuild/2003&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><br />
&nbsp; <br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;PropertyGroup<span style="font-weight: bold; color: black;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;CR<span style="font-weight: bold; color: black;">&gt;</span></span></span>%0A<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/CR<span style="font-weight: bold; color: black;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/PropertyGroup<span style="font-weight: bold; color: black;">&gt;</span></span></span><br />
&nbsp; <br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Target</span> <span style="color: #000066;">Name</span>=<span style="color: #ff0000;">&quot;ShowHelp&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Message</span> <span style="color: #000066;">Text</span>=<span style="color: #ff0000;">&quot;Available targets&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Message</span> <span style="color: #000066;">Text</span>=<span style="color: #ff0000;">&quot;* @(_availableTargets, '$(CR)* ')&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Target<span style="font-weight: bold; color: black;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Project<span style="font-weight: bold; color: black;">&gt;</span></span></span></div></div>
<p>If you follow the good practice of adding new targets to the item list _availableTargets, you have a help page showing if you pass in no parameters.</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;ItemGroup<span style="font-weight: bold; color: black;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;_availableTargets</span> <span style="color: #000066;">Include</span>=<span style="color: #ff0000;">&quot;Debug&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;_availableTargets</span> <span style="color: #000066;">Include</span>=<span style="color: #ff0000;">&quot;Release&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;_availableTargets</span> <span style="color: #000066;">Include</span>=<span style="color: #ff0000;">&quot;Clean&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/ItemGroup<span style="font-weight: bold; color: black;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Project<span style="font-weight: bold; color: black;">&gt;</span></span></span></div></div>
<p>Obviously we&#8217;ll have to write the actual targets too, but so far we&#8217;ve seen that<br />
* We can add things to a list.<br />
* Display that list with a different separator than semi-colon.<br />
* Define properties with escaped characters (by using the hexadecimal ascii values prefixed by a percent character).</p>
<p>It&#8217;s far from complete, but it&#8217;s a very good start!</p>
<p>&#8211;Jesper Hogstrom</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fmagpie.sytes.net%2Fjesperhogstrom%2F2011%2F05%2Fsetting-up-an-msbuild-script-system%2F&amp;title=Setting%20up%20an%20msbuild%20script%20system"><img src="http://magpie.sytes.net/jesperhogstrom/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://magpie.sytes.net/jesperhogstrom/2011/05/setting-up-an-msbuild-script-system/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Designing a build system</title>
		<link>http://magpie.sytes.net/jesperhogstrom/2011/05/designing-a-build-system/</link>
		<comments>http://magpie.sytes.net/jesperhogstrom/2011/05/designing-a-build-system/#comments</comments>
		<pubDate>Sun, 15 May 2011 12:56:19 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[development infrastructure]]></category>
		<category><![CDATA[build systems]]></category>

		<guid isPermaLink="false">http://magpie.sytes.net/jesperhogstrom/?p=548</guid>
		<description><![CDATA[When developing software it is somewhat obvious that the programmers need to be able to build the source code and run the tests on their own machines. It is slightly &#8211; but only slightly! &#8211; less obvious that the same code needs to build on a separate machine, known as a build machine. There are [...]]]></description>
			<content:encoded><![CDATA[<p>When developing software it is somewhat obvious that the programmers need to be able to build the source code and run the tests on their own machines. It is slightly &#8211; but only slightly! &#8211; less obvious that the same code needs to build on a separate machine, known as a build machine. There are several purposes of that, mainly to</p>
<p>* Ensure everything compiles after each check-in (structural integrity)</p>
<p>* Execute unit tests to ensure functional integrity.</p>
<p>* Run various kinds of static analysis on the source or binaries.</p>
<p>* Prepare builds for internal (e.g. QA) and external (e.g. customers) consumption.</p>
<p>A build machine is typically controlled by a build orchestrator, like Cruise (now a part of <a href="http://www.thoughtworks-studios.com/go-agile-release-management" target="_blank">Go</a>), <a href="CruiseControl.Net" target="_blank">CruiseControl.Net</a>, <a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=3660cacf-f077-44d3-a9d9-97e801da2035" target="_blank">TFS</a> or <a href="http://www.jetbrains.com/teamcity/" target="_blank">TeamCity</a>. It may be a single machine, a system of agents or something else. Let&#8217;s call this the build machinery.</p>
<p>The build orchestrator is in some way connected to the version control system (VCS), be it <a href="http://www.perforce.com/" target="_blank">Perforce</a>, <a href="http://git-scm.com/" target="_blank">Git</a>, <a href="http://subversion.apache.org/" target="_blank">Subversion</a> or TFS.</p>
<p>When a file is updated in the VCS, the build orchestrator gets a signal and starts executing a build script, typically written in <a href="http://msdn.microsoft.com/en-us/library/0k6kkbsd.aspx" target="_blank">msbuild</a>, <a href="http://ant.apache.org/" target="_blank">ant</a>/<a href="http://nant.sourceforge.net/" target="_blank">nant</a>, <a href="http://www.gnu.org/software/make/" target="_blank">make</a> or some shell language. It is to prefer to use a language that is designed for build orchestration, thus allowing for specification of dependencies, error handling and maybe even logging.</p>
<p>The fundamental components of a build system are thus:</p>
<p>* A build script</p>
<p>* A build machinery</p>
<p>* A version control system</p>
<p>Luckily, the build machinery and version control system are standard products, so you don&#8217;t need to worry about rolling your own.</p>
<p>However, the build script is something where you want to invest some energy. The purpose of the build script is to ensure that you can reproduce a bit-identical build from bit-identical sources. It should also have the ability to execute a suite of other targets.</p>
<p>A target is the end result of a build script invocation, or rather, what you want the script to produce &#8211; the transformation of inputs to an output.</p>
<p>Some examples of targets you want your build script to produce:</p>
<p>* <em>Debug </em>- A debug build of all sources.</p>
<p>* <em>Release </em>- A release build of all sources.</p>
<p>* <em>Testcases </em>- Compilation of all unit tests.</p>
<p>* <em>Documentation </em>- Collect all documentation source documents and transform them into the desired output format.</p>
<p>* <em>Installer </em>- Collect all files that goes in to the installation file and produce it.</p>
<p>You can also have your build script do a number of other things, such as</p>
<p>* <em>RunTests </em>- Execute all unit tests in the test framework you use.</p>
<p>* <em>RunSmokeTests </em>- Execute all UI level tests using whatever test robot you use.</p>
<p>* <em>Publish&lt;something&gt;</em> &#8211; Upload some artifact to a different server for wider consumption.</p>
<p>* <em>Clean&lt;something&gt;, Spotless</em> &#8211; Remove output from the source tree, ensuring next build creates everything from source documents.</p>
<p>An important aspect of a build script is that <strong>it should be possible to execute both on the build machiner/build agents and the developer machines</strong>!  You should be able to &#8220;make debug&#8221; or &#8220;build documentation&#8221; or &#8220;want testcases&#8221; from a command line prompt on all relevant machines. Otherwise it is very hard to perform an action on a developer machine to ensure the check in will pass. It also helps a great deal when developing the build script.</p>
<p>There are some really critical consequences of the above:  The build system must be self-contained! This means <strong>everything required during compile time must be reachable by the build machinery</strong> &#8211; and if it isn&#8217;t checked in you need some other way to pin which version (of a tool, SDK or third party tool) you want. Speaking of which, you&#8217;ll also need to <strong>version control the build scripts</strong> themselves.</p>
<p>So, to summarize what you need to get started:</p>
<p>* A build machinery.</p>
<p>* A version control system.</p>
<p>* A build script that automates everything that happens between coding and preparing a testable artifact.</p>
<p>* Everything required during compile time and test time reachable by the build script (either checked in or reachable on another file system).</p>
<p>The build script and repository of prerequisites require by far the most design &#8211; or rather &#8211; those two items are by far the least described out there.</p>
<p>I&#8217;ve designed build systems using various build machineries (CruiseControl.Net, TeamCity, TFS) using both make and msbuild. Nowadays I write msbuild scripts building .Net and C++ projects for a teamcity environment. However, there are a number of concepts that do not change. I&#8217;ve found the most important to be:</p>
<p>* Do not rely on what is installed on the machine you&#8217;re building on. Everything must be controlled!</p>
<p>* Designate an output/staging directory, and make sure everything that is produced ends up in under that directory.</p>
<p>* Define a structure of all projects and stick to it.</p>
<p>* The build should behave the same way if building from inside an IDE as when building from command line.</p>
<h2>Everything must be controlled</h2>
<p>Developers typically install something that goes into a build, add some references to globally available (GACed in the .Net world) DLLs and everything works just fine. Until the build happens on a different machine, when things blow up, as the global state of that machine isn&#8217;t the same as on the dev machine.</p>
<p>It is imperative that everything you use during compile time is checked in! This means not only your third party components, but also the unit testing framework and the tools used in the build chain, such as help compilers, installer creators and so on.</p>
<p>Often it is quite simple to meet this requirement. At other times it is harder, like when COM-servers need to be registered, registry entries must be found and other evil global conditions that must be fulfilled. As the build master, your job is to understand how you can script things to make all machines look like that have enough of the global state to fool the tools and components you use.</p>
<p>If you adhere to this rule adding a new build agent, or replacing a developer machine is very much simpler, as fewer things need to be installed.</p>
<p>I draw the line at the .Net level &#8211; all involved machined are allowed to have .Net installed. It would be possible to write scripts that didn&#8217;t rely on the presence of a .Net installation, but I find it not worth it at this point. If we were targeting strictly different .Net versions I might reconsider.</p>
<h2>Staging directory</h2>
<p>Visual Studio adds a bin and obj directory under each project. Not nice. You&#8217;d rather have all output end up under stage\debug or stage\release or stage\installer. Keeping everything under a stage directory reduce the risk of someone checking in binaries they&#8217;ve just built, and makes cleaning the tree significantly easier. Instead of traversing the world, you just rmdir stage\debug. Or rmdir stage if you really want to make things spotless.</p>
<p>Achieving this is not incredibly difficult, as all compilers tend to have a flag indicating where they should deliver the output. The trick is finding the sweet spot that minimize the amount of configuration required for each new project.</p>
<h2>Project Structure</h2>
<p>Project structure makes it easier to find your way around projects, reduce the learning time when moving to a new team and makes it much easier to write a build script that works across the board, as everything looks quite the same. I don&#8217;t know what structure makes sense to you, but something like</p>
<pre>-$+
  +-Build
  +-Common
  +-Documentation
  +-Source
  +-Stage
  +-Tests
  +-Xternals
</pre>
<p>is a good start. It is also fairly obvious what goes where. Try to keep the root directory rather clean!</p>
<h2>Behave the same from command line and IDE</h2>
<p>This is trickier than it sounds. Assume you set up a wrapper msbuild script that calls msbuild to build your solution file. You play nice and pass in whatever properties you need to the second level of msbuild and everything works as expected. From command line.</p>
<p>From inside Visual Studio however, you don&#8217;t get the parameters passed in from your script, as VS is now the root caller. Your fellow developers will get a different result than you and the build agents. There are likely several ways to accomplish this, and they all involve some manipulating the project files (csproj, vcxproj). If you are using some other IDE there are surely other ways.</p>
<p>That just about covers the high level aspects of a build system. Admittedly there are details left to cover, but they lack the generality I wanted for this post. The above should work for most circumstances and most platforms.</p>
<p>&#8211;Jesper Hogstrom</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fmagpie.sytes.net%2Fjesperhogstrom%2F2011%2F05%2Fdesigning-a-build-system%2F&amp;title=Designing%20a%20build%20system"><img src="http://magpie.sytes.net/jesperhogstrom/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://magpie.sytes.net/jesperhogstrom/2011/05/designing-a-build-system/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using unit test names as specifications</title>
		<link>http://magpie.sytes.net/jesperhogstrom/2011/01/using-unit-test-names-as-specifications/</link>
		<comments>http://magpie.sytes.net/jesperhogstrom/2011/01/using-unit-test-names-as-specifications/#comments</comments>
		<pubDate>Sun, 30 Jan 2011 12:30:34 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[development infrastructure]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[unit test]]></category>

		<guid isPermaLink="false">http://magpie.sytes.net/jesperhogstrom/?p=539</guid>
		<description><![CDATA[We spend a lot of time writing test cases and they sure serve us good. Wouldn&#8217;t it be nice if we could use the tests as a specification of the capabilities of the tested object? Let&#8217;s say we have a test that looks something like &#91;TestFixture&#93; public class MyCoolGizmoFixture &#123; &#91;Test&#93; public void AddingOnlyPermittedInTransaction&#40;&#41; &#123;&#125; [...]]]></description>
			<content:encoded><![CDATA[<p>We spend a lot of time writing test cases and they sure serve us good. Wouldn&#8217;t it be nice if we could use the tests as a specification of the capabilities of the tested object? </p>
<p>Let&#8217;s say we have a test that looks something like</p>
<div class="codecolorer-container csharp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000;">&#91;</span>TestFixture<span style="color: #000000;">&#93;</span><br />
<span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> MyCoolGizmoFixture<br />
<span style="color: #000000;">&#123;</span><br />
<span style="color: #000000;">&#91;</span>Test<span style="color: #000000;">&#93;</span><br />
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> AddingOnlyPermittedInTransaction<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span><span style="color: #000000;">&#125;</span><br />
<span style="color: #000000;">&#91;</span>Test<span style="color: #000000;">&#93;</span><br />
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> InvokingAddAddsItemToList<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span><span style="color: #000000;">&#125;</span><br />
<span style="color: #000000;">&#91;</span>Test<span style="color: #000000;">&#93;</span><br />
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> InvokingExecuteRunsExecuteOnAllItems<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span><span style="color: #000000;">&#125;</span><br />
...<br />
<span style="color: #000000;">&#125;</span></div></div>
<p>In essence, the tests spell out the specs for MyCoolGizmo! It has the following capabilities<br />
* Adding Only Permitted In Transaction<br />
* Invoking Add AddsItemToList<br />
* InvokingExecuteRunsExecute On All Items<br />
* &#8230;</p>
<p>Since that&#8217;s exactly how we named the tests (what a coincidence <img src='http://magpie.sytes.net/jesperhogstrom/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ) all we need to do is extract that from the code in some way. My first choice is always reflection in situations like this.</p>
<p>Here goes:</p>
<p>First, create a command line application.</p>
<div class="codecolorer-container csharp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0600FF;">private</span> <span style="color: #0600FF;">static</span> <span style="color: #0600FF;">void</span> Main<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span><span style="color: #000000;">&#91;</span><span style="color: #000000;">&#93;</span> args<span style="color: #000000;">&#41;</span><br />
<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; var files = <span style="color: #008000;">new</span> List&lt;string&gt;<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; var mode = OutputMode.<span style="color: #0000FF;">Text</span>;<br />
&nbsp; &nbsp; var outputName = <span style="color: #808080;">&quot;testdescriptions.txt&quot;</span>;<br />
&nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span>var arg <span style="color: #0600FF;">in</span> args<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CheckParam<span style="color: #000000;">&#40;</span>arg, <span style="color: #808080;">&quot;file&quot;</span>, files.<span style="color: #0000FF;">Add</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; CheckParam<span style="color: #000000;">&#40;</span>arg, <span style="color: #808080;">&quot;mode&quot;</span>, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s =&gt; mode = <span style="color: #000000;">&#40;</span>OutputMode<span style="color: #000000;">&#41;</span> <span style="color: #FF0000;">Enum</span>.<span style="color: #0000FF;">Parse</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span> <span style="color: #000000;">&#40;</span>OutputMode<span style="color: #000000;">&#41;</span>, s, <span style="color: #0600FF;">true</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; CheckParam<span style="color: #000000;">&#40;</span>arg, <span style="color: #808080;">&quot;outputname&quot;</span>, s =&gt; outputName = s<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; var scanner = <span style="color: #008000;">new</span> Scanner<span style="color: #000000;">&#40;</span>files, CreateGenerator<span style="color: #000000;">&#40;</span>mode<span style="color: #000000;">&#41;</span>, outputName<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; scanner.<span style="color: #0000FF;">Scan</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; scanner.<span style="color: #0000FF;">SaveResult</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
<span style="color: #000000;">&#125;</span></div></div>
<p>Add some supporting functions and definitions</p>
<div class="codecolorer-container csharp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0600FF;">internal</span> <span style="color: #FF0000;">enum</span> OutputMode <span style="color: #000000;">&#123;</span> Text, Html <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">static</span> <span style="color: #0600FF;">readonly</span> Dictionary&lt;OutputMode, Type&gt; Generators = <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #008000;">new</span> Dictionary&lt;OutputMode, Type&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span> OutputMode.<span style="color: #0000FF;">Html</span>, <span style="color: #008000;">typeof</span> <span style="color: #000000;">&#40;</span>ResultGeneratorHtml<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#125;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span> OutputMode.<span style="color: #0000FF;">Text</span>, <span style="color: #008000;">typeof</span> <span style="color: #000000;">&#40;</span>ResultGeneratorText<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000;">&#125;</span>;<br />
<span style="color: #0600FF;">private</span> <span style="color: #0600FF;">static</span> IResultGenerator CreateGenerator<span style="color: #000000;">&#40;</span>OutputMode mode<span style="color: #000000;">&#41;</span><br />
<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">return</span> <span style="color: #000000;">&#40;</span>IResultGenerator<span style="color: #000000;">&#41;</span> Activator.<span style="color: #0000FF;">CreateInstance</span><span style="color: #000000;">&#40;</span>Generators<span style="color: #000000;">&#91;</span>mode<span style="color: #000000;">&#93;</span><span style="color: #000000;">&#41;</span>;<br />
<span style="color: #000000;">&#125;</span><br />
<br />
<span style="color: #0600FF;">private</span> <span style="color: #0600FF;">static</span> <span style="color: #0600FF;">void</span> CheckParam<span style="color: #000000;">&#40;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #FF0000;">string</span> arg, <br />
&nbsp; &nbsp; &nbsp;<span style="color: #FF0000;">string</span> argName, <br />
&nbsp; &nbsp; &nbsp;Action&lt;string&gt; action<span style="color: #000000;">&#41;</span><br />
<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; var paramSwitch = <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Format</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;/{0}:&quot;</span>, argName<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>arg.<span style="color: #0000FF;">StartsWith</span><span style="color: #000000;">&#40;</span>paramSwitch, StringComparison.<span style="color: #0000FF;">OrdinalIgnoreCase</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; action<span style="color: #000000;">&#40;</span>arg.<span style="color: #0000FF;">Substring</span><span style="color: #000000;">&#40;</span>argName.<span style="color: #0000FF;">Length</span> + <span style="color: #FF0000;">2</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;<br />
<span style="color: #000000;">&#125;</span></div></div>
<p>We&#8217;ll also need to define the interface for the generators and a class to store the logged items in.</p>
<div class="codecolorer-container csharp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"> &nbsp; &nbsp;<span style="color: #0600FF;">internal</span> <span style="color: #FF0000;">interface</span> IResultGenerator<br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #FF0000;">string</span> GenerateResults<span style="color: #000000;">&#40;</span>List&lt;Entry&gt; entries<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">internal</span> <span style="color: #FF0000;">class</span> Entry<br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> Line <span style="color: #000000;">&#123;</span> get; <span style="color: #0600FF;">private</span> set; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">int</span> Level <span style="color: #000000;">&#123;</span> get; <span style="color: #0600FF;">private</span> set; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">public</span> Entry<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> line, <span style="color: #FF0000;">int</span> level<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Line = line;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Level = level;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span></div></div>
<p>The scanner turns out to be quite straight forward</p>
<div class="codecolorer-container csharp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0600FF;">internal</span> <span style="color: #FF0000;">class</span> Scanner<br />
<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">readonly</span> List&lt;string&gt; _files;<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">readonly</span> IResultGenerator _generator;<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">readonly</span> <span style="color: #FF0000;">string</span> _outputName;<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">readonly</span> List&lt;Entry&gt; _log = <span style="color: #008000;">new</span> List&lt;Entry&gt;<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> Scanner<span style="color: #000000;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; List&lt;string&gt; files, <br />
&nbsp; &nbsp; &nbsp; &nbsp; IResultGenerator generator, <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #FF0000;">string</span> outputName<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; _files = files;<br />
&nbsp; &nbsp; &nbsp; &nbsp; _generator = generator;<br />
&nbsp; &nbsp; &nbsp; &nbsp; _outputName = outputName;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> SaveResult<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>File.<span style="color: #0000FF;">Exists</span><span style="color: #000000;">&#40;</span>_outputName<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; File.<span style="color: #0000FF;">Delete</span><span style="color: #000000;">&#40;</span>_outputName<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; File.<span style="color: #0000FF;">AppendAllText</span><span style="color: #000000;">&#40;</span>_outputName, _generator.<span style="color: #0000FF;">GenerateResults</span><span style="color: #000000;">&#40;</span>_log<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> PrintResult<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Console.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span>_generator.<span style="color: #0000FF;">GenerateResults</span><span style="color: #000000;">&#40;</span>_log<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> Scan<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">const</span> <span style="color: #FF0000;">int</span> level = <span style="color: #FF0000;">-1</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span>var assembly <span style="color: #0600FF;">in</span> AllAssemblies<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ScanAssembly<span style="color: #000000;">&#40;</span>assembly, level + <span style="color: #FF0000;">1</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> IEnumerable&lt;Assembly&gt; AllAssemblies<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> AllFiles<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #0000FF;">Select</span><span style="color: #000000;">&#40;</span>LoadAssembly<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #0000FF;">Where</span><span style="color: #000000;">&#40;</span>assembly =&gt; assembly != <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">void</span> ScanAssembly<span style="color: #000000;">&#40;</span>Assembly assembly, <span style="color: #FF0000;">int</span> level<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Console.<span style="color: #0000FF;">Write</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">'.'</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; _log.<span style="color: #0000FF;">Add</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">new</span> Entry<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Format</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;Area: {0}&quot;</span>, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; assembly.<span style="color: #0000FF;">FullName</span><span style="color: #000000;">&#41;</span>, level<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">try</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var t <span style="color: #0600FF;">in</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; assembly.<span style="color: #0000FF;">GetExportedTypes</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">Where</span><span style="color: #000000;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t =&gt; t.<span style="color: #0000FF;">GetCustomAttributes</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span> <span style="color: #000000;">&#40;</span>TestFixtureAttribute<span style="color: #000000;">&#41;</span>, <span style="color: #0600FF;">true</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">Count</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> &gt; <span style="color: #FF0000;">0</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ScanType<span style="color: #000000;">&#40;</span>t, level + <span style="color: #FF0000;">1</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">catch</span> <span style="color: #000000;">&#40;</span>Exception e<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _log.<span style="color: #0000FF;">Add</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">new</span> Entry<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Format</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;Unable to scan assembly {0}: {1}&quot;</span>, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; assembly.<span style="color: #0000FF;">FullName</span>, e.<span style="color: #0000FF;">Message</span><span style="color: #000000;">&#41;</span>, <span style="color: #FF0000;">-1</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">void</span> ScanType<span style="color: #000000;">&#40;</span>Type type, <span style="color: #FF0000;">int</span> level<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; _log.<span style="color: #0000FF;">Add</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">new</span> Entry<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Format</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;Fixture: {0}&quot;</span>, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;BreakApart<span style="color: #000000;">&#40;</span>type.<span style="color: #0000FF;">Name</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>, level<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var m <span style="color: #0600FF;">in</span> type.<span style="color: #0000FF;">GetMethods</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #0000FF;">Where</span><span style="color: #000000;">&#40;</span>t =&gt; t.<span style="color: #0000FF;">GetCustomAttributes</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span><span style="color: #000000;">&#40;</span>TestAttribute<span style="color: #000000;">&#41;</span>, <span style="color: #0600FF;">true</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">Count</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> &gt; <span style="color: #FF0000;">0</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ScanMethod<span style="color: #000000;">&#40;</span>m, level + <span style="color: #FF0000;">1</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">void</span> ScanMethod<span style="color: #000000;">&#40;</span>MethodInfo methodInfo, <span style="color: #FF0000;">int</span> level<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; _log.<span style="color: #0000FF;">Add</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">new</span> Entry<span style="color: #000000;">&#40;</span>BreakApart<span style="color: #000000;">&#40;</span>methodInfo.<span style="color: #0000FF;">Name</span><span style="color: #000000;">&#41;</span>, level<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">static</span> <span style="color: #FF0000;">string</span> BreakApart<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> name<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; var result = <span style="color: #008000;">new</span> StringBuilder<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #FF0000;">char</span> prev = <span style="color: #808080;">' '</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span>var c <span style="color: #0600FF;">in</span> name<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>c == <span style="color: #808080;">'_'</span><span style="color: #000000;">&#41;</span> <span style="color: #0600FF;">continue</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">char</span>.<span style="color: #0000FF;">IsUpper</span><span style="color: #000000;">&#40;</span>c<span style="color: #000000;">&#41;</span> &amp;&amp; !<span style="color: #FF0000;">char</span>.<span style="color: #0000FF;">IsUpper</span><span style="color: #000000;">&#40;</span>prev<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result.<span style="color: #0000FF;">Append</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">' '</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result.<span style="color: #0000FF;">Append</span><span style="color: #000000;">&#40;</span>c<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; prev = c;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> result.<span style="color: #0000FF;">ToString</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">Trim</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> Assembly LoadAssembly<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> filename<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">try</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> Assembly.<span style="color: #0000FF;">LoadFrom</span><span style="color: #000000;">&#40;</span>filename<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">catch</span> <span style="color: #000000;">&#40;</span>Exception e<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _log.<span style="color: #0000FF;">Add</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">new</span> Entry<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Format</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;Unable to load {0}: {1}&quot;</span>, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; filename, e.<span style="color: #0000FF;">Message</span><span style="color: #000000;">&#41;</span>, <span style="color: #FF0000;">-1</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <span style="color: #0600FF;">null</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> IEnumerable&lt;string&gt; AllFiles<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span>var filePattern <span style="color: #0600FF;">in</span> _files<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #FF0000;">string</span> directoryName = Path.<span style="color: #0000FF;">GetDirectoryName</span><span style="color: #000000;">&#40;</span>filePattern<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #FF0000;">string</span> searchPattern = Path.<span style="color: #0000FF;">GetFileName</span><span style="color: #000000;">&#40;</span>filePattern<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var files = Directory.<span style="color: #0000FF;">GetFiles</span><span style="color: #000000;">&#40;</span>directoryName, searchPattern<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span>var file <span style="color: #0600FF;">in</span> files<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yield <span style="color: #0600FF;">return</span> file;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<span style="color: #000000;">&#125;</span></div></div>
<p>The only remaining this is to define the result generators, which can of course be changed to suit your needs to produce other formats should that be desired.</p>
<div class="codecolorer-container csharp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0600FF;">internal</span> <span style="color: #FF0000;">class</span> ResultGeneratorText : IResultGenerator<br />
<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> GenerateResults<span style="color: #000000;">&#40;</span>List&lt;Entry&gt; entries<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; var result = <span style="color: #008000;">new</span> StringBuilder<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span>var entry <span style="color: #0600FF;">in</span> entries<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result.<span style="color: #0000FF;">AppendFormat</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;{0}{1}{2}&quot;</span>, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">new</span> <span style="color: #FF0000;">string</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">'<span style="color: #008080; font-weight: bold;">\t</span>'</span>, entry.<span style="color: #0000FF;">Level</span><span style="color: #000000;">&#41;</span>, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; entry.<span style="color: #0000FF;">Line</span>, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Environment.<span style="color: #0000FF;">NewLine</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> result.<span style="color: #0000FF;">ToString</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<span style="color: #000000;">&#125;</span><br />
<br />
<span style="color: #0600FF;">internal</span> <span style="color: #FF0000;">class</span> ResultGeneratorHtml : IResultGenerator<br />
<span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> GenerateResults<span style="color: #000000;">&#40;</span>List&lt;Entry&gt; entries<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; var result = <span style="color: #008000;">new</span> StringBuilder<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; result.<span style="color: #0000FF;">AppendLine</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;&lt;html&gt;&quot;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; result.<span style="color: #0000FF;">AppendLine</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;&lt;body&gt;&quot;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; result.<span style="color: #0000FF;">AppendFormat</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;&lt;B&gt;Report generated {0} {1}&lt;B&gt;&lt;P&gt;{2}&quot;</span>, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DateTime.<span style="color: #0000FF;">Now</span>.<span style="color: #0000FF;">ToShortDateString</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DateTime.<span style="color: #0000FF;">Now</span>.<span style="color: #0000FF;">ToShortTimeString</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Environment.<span style="color: #0000FF;">NewLine</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span>var entry <span style="color: #0600FF;">in</span> entries<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var inList = <span style="color: #0600FF;">false</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #FF0000;">string</span> opentag;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #FF0000;">string</span> endtag;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">switch</span> <span style="color: #000000;">&#40;</span>entry.<span style="color: #0000FF;">Level</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">case</span> <span style="color: #FF0000;">-1</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; opentag = <span style="color: #808080;">&quot;&lt;I&gt;&quot;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; endtag = <span style="color: #808080;">&quot;&lt;/I&gt;&quot;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">case</span> <span style="color: #FF0000;">0</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; opentag = <span style="color: #808080;">&quot;&lt;H1&gt;&quot;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; endtag = <span style="color: #808080;">&quot;&lt;/H1&gt;&quot;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">case</span> <span style="color: #FF0000;">1</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; opentag = <span style="color: #808080;">&quot;&lt;H2&gt;&quot;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; endtag = <span style="color: #808080;">&quot;&lt;/H2&gt;&quot;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">case</span> <span style="color: #FF0000;">2</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; inList = <span style="color: #0600FF;">true</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; opentag = <span style="color: #808080;">&quot;&lt;LI&gt;&quot;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; endtag = <span style="color: #808080;">&quot;&lt;/LI&gt;&quot;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">default</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; opentag = <span style="color: #808080;">&quot;&lt;I&gt;&quot;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; endtag = <span style="color: #808080;">&quot;&lt;/I&gt;&quot;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>entry.<span style="color: #0000FF;">Level</span> == <span style="color: #FF0000;">2</span> &amp;&amp; !inList<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result.<span style="color: #0000FF;">Append</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;&lt;OL&gt;&quot;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result.<span style="color: #0000FF;">AppendFormat</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;{0}{1}{2}{3}&quot;</span>, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;opentag, entry.<span style="color: #0000FF;">Line</span>, endtag, Environment.<span style="color: #0000FF;">NewLine</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>entry.<span style="color: #0000FF;">Level</span> != <span style="color: #FF0000;">2</span> &amp;&amp; inList<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result.<span style="color: #0000FF;">Append</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;&lt;/OL&gt;&quot;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; result.<span style="color: #0000FF;">AppendLine</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;&lt;/html&gt;&quot;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; result.<span style="color: #0000FF;">AppendLine</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;&lt;/body&gt;&quot;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> result.<span style="color: #0000FF;">ToString</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<span style="color: #000000;">&#125;</span></div></div>
<p>To compile you&#8217;ll need to add a reference to nUnit. Then run it with appropriate switches, something like</p>
<div class="codecolorer-container dos default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">SpecsFromTest /file:C:\dev\stage\debug\*Test.dll /mode:Html /outputname:c:\dev\stage\reports\testresult.html</div></div>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fmagpie.sytes.net%2Fjesperhogstrom%2F2011%2F01%2Fusing-unit-test-names-as-specifications%2F&amp;title=Using%20unit%20test%20names%20as%20specifications"><img src="http://magpie.sytes.net/jesperhogstrom/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://magpie.sytes.net/jesperhogstrom/2011/01/using-unit-test-names-as-specifications/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Writing msbuild tasks declaratively</title>
		<link>http://magpie.sytes.net/jesperhogstrom/2010/12/writing-msbuild-tasks-declaratively/</link>
		<comments>http://magpie.sytes.net/jesperhogstrom/2010/12/writing-msbuild-tasks-declaratively/#comments</comments>
		<pubDate>Sun, 12 Dec 2010 23:18:01 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[development infrastructure]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[build system]]></category>
		<category><![CDATA[msbuild]]></category>

		<guid isPermaLink="false">http://magpie.sytes.net/jesperhogstrom/?p=525</guid>
		<description><![CDATA[It comes a time in every build admins life when writing custom msbuild tasks can no longer be avoided. I myself is no stranger to writing my own tasks. However, when it&#8217;s time to tidy up all those pesky &#8216;Command Exec=&#8221;&#8230;&#8221;&#8216; it seems there must be a better way than subclassing ToolTask and construct the [...]]]></description>
			<content:encoded><![CDATA[<p>It comes a time in every build admins life when writing custom msbuild tasks can no longer be avoided. I myself is no stranger to <a href="http://magpie.sytes.net/jesperhogstrom/2010/12/sending-mail-from-msbuild/">writing my own tasks</a>. However, when it&#8217;s time to tidy up all those pesky &#8216;Command Exec=&#8221;&#8230;&#8221;&#8216; it seems there must be a better way than subclassing ToolTask and construct the command line manually by overriding GenerateCommandLineCommands.</p>
<p>What I set out to do was to have a declarative way to define how parameters are constructed, all driven by an engine in a superclass. Declarative means attributes.</p>
<p>As an example, I want to wrap <a href="http://www.samba.org/ftp/rsync/rsync.html">rsync</a> in a task class. rsync has a great number of parameters, and I want to write something like</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Target</span> <span style="color: #000066;">Name</span>=<span style="color: #ff0000;">&quot;foo&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;RSync</span> <span style="color: #000066;">Source</span>=<span style="color: #ff0000;">&quot;$(server)&quot;</span> <br />
&nbsp; &nbsp; &nbsp;<span style="color: #000066;">Target</span>=<span style="color: #ff0000;">&quot;$(targetdir)&quot;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #000066;">Recursive</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <br />
&nbsp; &nbsp; &nbsp;<span style="color: #000066;">ToolPath</span>=<span style="color: #ff0000;">&quot;C:\cygwin\bin&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span><br />
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Target<span style="font-weight: bold; color: black;">&gt;</span></span></span></div></div>
<p>I also envision that I will have to write more wrappers of command line tools, and I don&#8217;t want to write a command line generator for all of them.</p>
<p>There are only a few types of parameters to pass to command line tools:<br />
* Existence of a parameter, like &#8220;&#8211;recursive&#8221;.<br />
* A switch with a value, like &#8220;&#8211;password-file=FILE&#8221;.</p>
<p>Now, if you&#8217;re not familiar with rsync, too bad for you! However, the reasoning holds for any executable you want to wrap in a task instead of using Exec.</p>
<p>Thus, in my subclass, I would like to specify this as something like</p>
<div class="codecolorer-container csharp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"> &nbsp;<span style="color: #000000;">&#91;</span>ParameterString<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;{Recursive} {Quiet} {Verbose} {Progress} {Passwordfile} {Source} {Target}&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> RSync : CmdTask<br />
&nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Parameter<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;--recursive&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> Recursive <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Parameter<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;--progress&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> Progress <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Parameter<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;--verbose&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> Verbose <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Parameter<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;--quiet&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> Quiet <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Parameter<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;--passwordfile={0}&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> Passwordfile <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span> &nbsp; &nbsp;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Parameter<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;{0}&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> Source <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Parameter<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;{0}&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> Target <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">override</span> <span style="color: #FF0000;">string</span> ToolName<br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; get <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> <span style="color: #808080;">&quot;rsync.exe&quot;</span>; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; <span style="color: #000000;">&#125;</span></div></div>
<p>The way to go is to first define a couple of simple attributes.</p>
<div class="codecolorer-container csharp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"> &nbsp;<span style="color: #000000;">&#91;</span>AttributeUsage<span style="color: #000000;">&#40;</span>AttributeTargets.<span style="color: #0000FF;">Property</span>, AllowMultiple = <span style="color: #0600FF;">false</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">sealed</span> <span style="color: #FF0000;">class</span> ParameterAttribute : Attribute<br />
&nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> Parameter <span style="color: #000000;">&#123;</span> get; <span style="color: #0600FF;">private</span> set; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> ParameterAttribute<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> parameter<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; Parameter = parameter;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; <span style="color: #000000;">&#91;</span>AttributeUsage<span style="color: #000000;">&#40;</span>AttributeTargets.<span style="color: #FF0000;">Class</span>, AllowMultiple = <span style="color: #0600FF;">false</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">sealed</span> <span style="color: #FF0000;">class</span> ParameterStringAttribute : Attribute<br />
&nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> ParameterString <span style="color: #000000;">&#123;</span> get; <span style="color: #0600FF;">private</span> set; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> ParameterStringAttribute<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> parameterString<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; ParameterString = parameterString;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; <span style="color: #000000;">&#125;</span></div></div>
<p>Now we need an intermediate class to operate on these attributes. The most fundamental level is to construct the path to the tool.</p>
<div class="codecolorer-container csharp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"> &nbsp;<span style="color: #0600FF;">public</span> abstract <span style="color: #FF0000;">class</span> CmdTask : ToolTask<br />
&nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">override</span> <span style="color: #FF0000;">string</span> GenerateFullPathToTool<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">IsNullOrEmpty</span><span style="color: #000000;">&#40;</span>ToolPath<span style="color: #000000;">&#41;</span> ? ToolName : Path.<span style="color: #0000FF;">Combine</span><span style="color: #000000;">&#40;</span>ToolPath, ToolName<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; <span style="color: #000000;">&#125;</span></div></div>
<p>This makes sure you can set the toolpath if you want to.</p>
<p>As you notice, I subclass ToolTask, as the msbuild team as done a great job of some parts of the infrastructure.</p>
<p>The key part is to make magic in the virtual GenerateCommandLineCommands.</p>
<div class="codecolorer-container csharp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"> &nbsp; &nbsp;<span style="color: #0600FF;">private</span> <span style="color: #0600FF;">readonly</span> Dictionary&lt;string, string&gt; _parameters = <span style="color: #008000;">new</span> Dictionary&lt;string, string&gt;<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #FF0000;">string</span> _parameterTemplate;<br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">override</span> <span style="color: #FF0000;">string</span> GenerateCommandLineCommands<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; CollectParameters<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> ExpandTemplate<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #FF0000;">string</span> ExpandTemplate<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; var paramTemplate = <span style="color: #008000;">new</span> StringBuilder<span style="color: #000000;">&#40;</span>_parameterTemplate<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span>var parameter <span style="color: #0600FF;">in</span> _parameters.<span style="color: #0000FF;">Keys</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; paramTemplate.<span style="color: #0000FF;">Replace</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Format</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;{{{0}}}&quot;</span>, parameter<span style="color: #000000;">&#41;</span>, _parameters<span style="color: #000000;">&#91;</span>parameter<span style="color: #000000;">&#93;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> paramTemplate.<span style="color: #0000FF;">ToString</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">void</span> CollectParameters<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; var parameterString =<br />
&nbsp; &nbsp; &nbsp; &nbsp; GetType<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #0000FF;">GetCustomAttributes</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span> <span style="color: #000000;">&#40;</span>ParameterStringAttribute<span style="color: #000000;">&#41;</span>, <span style="color: #0600FF;">true</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #0000FF;">Cast</span>&lt;ParameterStringAttribute&gt;<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #0000FF;">FirstOrDefault</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; _parameterTemplate = parameterString != <span style="color: #0600FF;">null</span> ? parameterString.<span style="color: #0000FF;">ParameterString</span> : <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Empty</span>;<br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span>var prop <span style="color: #0600FF;">in</span> GetType<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">GetProperties</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; var parameter = prop.<span style="color: #0000FF;">GetCustomAttributes</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span> <span style="color: #000000;">&#40;</span>ParameterAttribute<span style="color: #000000;">&#41;</span>, <span style="color: #0600FF;">true</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #0000FF;">Cast</span>&lt;ParameterAttribute&gt;<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #0000FF;">FirstOrDefault</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>parameter == <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">continue</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; _parameters.<span style="color: #0000FF;">Add</span><span style="color: #000000;">&#40;</span>prop.<span style="color: #0000FF;">Name</span>, GetParameterValue<span style="color: #000000;">&#40;</span>prop, parameter<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #FF0000;">string</span> GetParameterValue<span style="color: #000000;">&#40;</span>PropertyInfo prop, ParameterAttribute parameter<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; var v = prop.<span style="color: #0000FF;">GetValue</span><span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>, <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>prop.<span style="color: #0000FF;">PropertyType</span> == <span style="color: #008000;">typeof</span> <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">bool</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">bool</span><span style="color: #000000;">&#41;</span> v ? parameter.<span style="color: #0000FF;">Parameter</span> : <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Empty</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>prop.<span style="color: #0000FF;">PropertyType</span> == <span style="color: #008000;">typeof</span> <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">IsNullOrEmpty</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span><span style="color: #000000;">&#41;</span> v<span style="color: #000000;">&#41;</span> ? <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Empty</span> : <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Format</span><span style="color: #000000;">&#40;</span>parameter.<span style="color: #0000FF;">Parameter</span>, v<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> v == <span style="color: #0600FF;">null</span> ? <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Empty</span> : <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Format</span><span style="color: #000000;">&#40;</span>parameter.<span style="color: #0000FF;">Parameter</span>, v<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span></div></div>
<p>The above, rather simple code, achieves the main objective. Boolean attributes cause a switch to appear or not appear, omission of an attribute prevents a nonsensical switch to appear.</p>
<p>For debugging purposes, let&#8217;s add a DryRun option. This should print out the command line, but not execute anything.</p>
<div class="codecolorer-container csharp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"> &nbsp; &nbsp;<span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> DryRun <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> <span style="color: #FF0000;">bool</span> Execute<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>DryRun<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Log.<span style="color: #0000FF;">LogMessage</span><span style="color: #000000;">&#40;</span>MessageImportance.<span style="color: #0000FF;">High</span>, <span style="color: #808080;">&quot;Command line that will be executed:&quot;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Log.<span style="color: #0000FF;">LogMessage</span><span style="color: #000000;">&#40;</span>MessageImportance.<span style="color: #0000FF;">High</span>, <span style="color: #808080;">&quot;{0} {1}&quot;</span>, GenerateFullPathToTool<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>, GenerateCommandLineCommands<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <span style="color: #0600FF;">false</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">Execute</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span></div></div>
<p>At this point you&#8217;ll notice that the output is not shown unless you increase the loglevel to msbuild. Why not make that declarative too?</p>
<div class="codecolorer-container csharp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"> &nbsp; &nbsp;<span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">override</span> MessageImportance StandardOutputLoggingImportance<br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; get<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; MessageImportance importance;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #FF0000;">Enum</span>.<span style="color: #0000FF;">TryParse</span><span style="color: #000000;">&#40;</span>OutputImportance, <span style="color: #0600FF;">true</span>, <span style="color: #0600FF;">out</span> importance<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> importance;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> OutputImportance <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span></div></div>
<p>This allows you to specify if the output of your tools when should show up.</p>
<p>In some cases you probably want a different default value than the .net defaults. Luckily there is already an attribute defined for this: <a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.defaultvalueattribute.aspx">DefaultValueAttribute</a>.</p>
<p>In the rsync case, we might want to set recursive as default, specified as something like</p>
<div class="codecolorer-container csharp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"> &nbsp;<span style="color: #000000;">&#91;</span>ParameterString<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;{Recursive} {Quiet} {Verbose} {Progress} {Passwordfile} {Source} {Target}&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> RSync : CmdTask<br />
&nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>DefaultValue<span style="color: #000000;">&#40;</span><span style="color: #0600FF;">true</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Parameter<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;--recursive&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> Recursive <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; ...<br />
&nbsp; <span style="color: #000000;">&#125;</span></div></div>
<p>Add to our base class the following code</p>
<div class="codecolorer-container csharp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"> &nbsp; &nbsp;<span style="color: #0600FF;">protected</span> CmdTask<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; SetDefaults<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">void</span> SetDefaults<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span>var prop <span style="color: #0600FF;">in</span> GetType<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">GetProperties</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; var attr = prop.<span style="color: #0000FF;">GetCustomAttributes</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span> <span style="color: #000000;">&#40;</span>DefaultValueAttribute<span style="color: #000000;">&#41;</span>, <span style="color: #0600FF;">true</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #0000FF;">Cast</span>&lt;DefaultValueAttribute&gt;<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #0000FF;">FirstOrDefault</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>attr == <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">continue</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; prop.<span style="color: #0000FF;">SetValue</span><span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>, attr.<span style="color: #0000FF;">Value</span>, <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span></div></div>
<p>As much as we all love writing documentation, we know that the others won&#8217;t read it. Why not make our tasks self documenting? What if we could add &#8220;ShowHelp=&#8217;true&#8217;&#8221; to our msbuild script and get the meaning of each parameter explained?</p>
<p>Again, we make use of an existing attribute, <a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.descriptionattribute.aspx">DescriptionAttribute</a>.</p>
<p>Add it as follows in your subclass:</p>
<div class="codecolorer-container csharp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"> &nbsp;<span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> RSync : CmdTask<br />
&nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>DefaultValue<span style="color: #000000;">&#40;</span><span style="color: #0600FF;">true</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Description<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;recurse into directories&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Parameter<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;--recursive&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> Recursive <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span></div></div>
<p>and add the following to the base class:</p>
<div class="codecolorer-container csharp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"> &nbsp; &nbsp;<span style="color: #0600FF;">private</span> <span style="color: #0600FF;">readonly</span> Dictionary&lt;string, PropertyInfo&gt; _parameterInfo = <span style="color: #008000;">new</span> Dictionary&lt;string, PropertyInfo&gt;<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> <span style="color: #FF0000;">bool</span> Execute<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>DryRun<span style="color: #000000;">&#41;</span> ...<br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>ShowHelp<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; GenerateCommandLineCommands<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Log.<span style="color: #0000FF;">LogMessage</span><span style="color: #000000;">&#40;</span>MessageImportance.<span style="color: #0000FF;">High</span>, <span style="color: #808080;">&quot;Available options for task {0}:&quot;</span>, GetType<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">Name</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span>var parameter <span style="color: #0600FF;">in</span> _parameterInfo<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Log.<span style="color: #0000FF;">LogMessage</span><span style="color: #000000;">&#40;</span>MessageImportance.<span style="color: #0000FF;">High</span>, <span style="color: #808080;">&quot;{0}: {1}{2}&quot;</span>, parameter.<span style="color: #0000FF;">Key</span>, parameter.<span style="color: #0000FF;">Value</span>.<span style="color: #0000FF;">PropertyType</span>.<span style="color: #0000FF;">Name</span>, GetDescription<span style="color: #000000;">&#40;</span>parameter.<span style="color: #0000FF;">Value</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <span style="color: #0600FF;">false</span>; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">Execute</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">static</span> <span style="color: #FF0000;">string</span> GetDescription<span style="color: #000000;">&#40;</span>PropertyInfo propertyInfo<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; var desc = propertyInfo.<span style="color: #0000FF;">GetCustomAttributes</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span> <span style="color: #000000;">&#40;</span>DescriptionAttribute<span style="color: #000000;">&#41;</span>, <span style="color: #0600FF;">true</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">Cast</span>&lt;DescriptionAttribute&gt;<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">FirstOrDefault</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>desc == <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Empty</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Format</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot; - {0}&quot;</span>, desc.<span style="color: #0000FF;">Description</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">void</span> CollectParameters<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; ...<br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span>var prop <span style="color: #0600FF;">in</span> GetType<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">GetProperties</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;...<br />
&nbsp; &nbsp; &nbsp; &nbsp; _parameterInfo.<span style="color: #0000FF;">Add</span><span style="color: #000000;">&#40;</span>prop.<span style="color: #0000FF;">Name</span>, prop<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span></div></div>
<p>This will yield an output similar to</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"> &nbsp;Available options for task RSync:<br />
&nbsp; Recursive: Boolean - recurse into directories<br />
&nbsp; ...</div></div>
<p>The full code for the base class:</p>
<div class="codecolorer-container csharp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"> &nbsp;<span style="color: #0600FF;">public</span> abstract <span style="color: #FF0000;">class</span> CmdTask : ToolTask<br />
&nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">readonly</span> Dictionary&lt;string, string&gt; _parameters = <span style="color: #008000;">new</span> Dictionary&lt;string, string&gt;<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">readonly</span> Dictionary&lt;string, PropertyInfo&gt; _parameterInfo = <span style="color: #008000;">new</span> Dictionary&lt;string, PropertyInfo&gt;<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #FF0000;">string</span> _parameterTemplate;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> DryRun <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> ShowHelp <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">protected</span> CmdTask<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; SetDefaults<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">void</span> SetDefaults<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span>var prop <span style="color: #0600FF;">in</span> GetType<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">GetProperties</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; var attr = prop.<span style="color: #0000FF;">GetCustomAttributes</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span> <span style="color: #000000;">&#40;</span>DefaultValueAttribute<span style="color: #000000;">&#41;</span>, <span style="color: #0600FF;">true</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #0000FF;">Cast</span>&lt;DefaultValueAttribute&gt;<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #0000FF;">FirstOrDefault</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>attr == <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">continue</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; prop.<span style="color: #0000FF;">SetValue</span><span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>, attr.<span style="color: #0000FF;">Value</span>, <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">override</span> <span style="color: #FF0000;">string</span> GenerateFullPathToTool<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">IsNullOrEmpty</span><span style="color: #000000;">&#40;</span>ToolPath<span style="color: #000000;">&#41;</span> ? ToolName : Path.<span style="color: #0000FF;">Combine</span><span style="color: #000000;">&#40;</span>ToolPath, ToolName<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> <span style="color: #FF0000;">bool</span> Execute<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>DryRun<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Log.<span style="color: #0000FF;">LogMessage</span><span style="color: #000000;">&#40;</span>MessageImportance.<span style="color: #0000FF;">High</span>, <span style="color: #808080;">&quot;Command line that will be executed:&quot;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Log.<span style="color: #0000FF;">LogMessage</span><span style="color: #000000;">&#40;</span>MessageImportance.<span style="color: #0000FF;">High</span>, <span style="color: #808080;">&quot;{0} {1}&quot;</span>, GenerateFullPathToTool<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>, GenerateCommandLineCommands<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <span style="color: #0600FF;">false</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>ShowHelp<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; GenerateCommandLineCommands<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Log.<span style="color: #0000FF;">LogMessage</span><span style="color: #000000;">&#40;</span>MessageImportance.<span style="color: #0000FF;">High</span>, <span style="color: #808080;">&quot;Available options for task {0}:&quot;</span>, GetType<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">Name</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span>var parameter <span style="color: #0600FF;">in</span> _parameterInfo<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Log.<span style="color: #0000FF;">LogMessage</span><span style="color: #000000;">&#40;</span>MessageImportance.<span style="color: #0000FF;">High</span>, <span style="color: #808080;">&quot;{0}: {1}{2}&quot;</span>, parameter.<span style="color: #0000FF;">Key</span>, parameter.<span style="color: #0000FF;">Value</span>.<span style="color: #0000FF;">PropertyType</span>.<span style="color: #0000FF;">Name</span>, GetDescription<span style="color: #000000;">&#40;</span>parameter.<span style="color: #0000FF;">Value</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <span style="color: #0600FF;">false</span>; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">Execute</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">static</span> <span style="color: #FF0000;">string</span> GetDescription<span style="color: #000000;">&#40;</span>PropertyInfo propertyInfo<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; var desc = propertyInfo.<span style="color: #0000FF;">GetCustomAttributes</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span> <span style="color: #000000;">&#40;</span>DescriptionAttribute<span style="color: #000000;">&#41;</span>, <span style="color: #0600FF;">true</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">Cast</span>&lt;DescriptionAttribute&gt;<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">FirstOrDefault</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>desc == <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Empty</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Format</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot; - {0}&quot;</span>, desc.<span style="color: #0000FF;">Description</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">override</span> <span style="color: #FF0000;">string</span> GenerateCommandLineCommands<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; CollectParameters<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> ExpandTemplate<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #FF0000;">string</span> ExpandTemplate<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; var paramTemplate = <span style="color: #008000;">new</span> StringBuilder<span style="color: #000000;">&#40;</span>_parameterTemplate<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span>var parameter <span style="color: #0600FF;">in</span> _parameters.<span style="color: #0000FF;">Keys</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; paramTemplate.<span style="color: #0000FF;">Replace</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Format</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;{{{0}}}&quot;</span>, parameter<span style="color: #000000;">&#41;</span>, _parameters<span style="color: #000000;">&#91;</span>parameter<span style="color: #000000;">&#93;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> paramTemplate.<span style="color: #0000FF;">ToString</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">void</span> CollectParameters<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; var parameterString =<br />
&nbsp; &nbsp; &nbsp; &nbsp; GetType<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #0000FF;">GetCustomAttributes</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span> <span style="color: #000000;">&#40;</span>ParameterStringAttribute<span style="color: #000000;">&#41;</span>, <span style="color: #0600FF;">true</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #0000FF;">Cast</span>&lt;ParameterStringAttribute&gt;<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #0000FF;">FirstOrDefault</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; _parameterTemplate = parameterString != <span style="color: #0600FF;">null</span> ? parameterString.<span style="color: #0000FF;">ParameterString</span> : <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Empty</span>;<br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span>var prop <span style="color: #0600FF;">in</span> GetType<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">GetProperties</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; var parameter = prop.<span style="color: #0000FF;">GetCustomAttributes</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span> <span style="color: #000000;">&#40;</span>ParameterAttribute<span style="color: #000000;">&#41;</span>, <span style="color: #0600FF;">true</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #0000FF;">Cast</span>&lt;ParameterAttribute&gt;<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #0000FF;">FirstOrDefault</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>parameter == <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">continue</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; _parameters.<span style="color: #0000FF;">Add</span><span style="color: #000000;">&#40;</span>prop.<span style="color: #0000FF;">Name</span>, GetParameterValue<span style="color: #000000;">&#40;</span>prop, parameter<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; _parameterInfo.<span style="color: #0000FF;">Add</span><span style="color: #000000;">&#40;</span>prop.<span style="color: #0000FF;">Name</span>, prop<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> <span style="color: #FF0000;">string</span> GetParameterValue<span style="color: #000000;">&#40;</span>PropertyInfo prop, ParameterAttribute parameter<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; var v = prop.<span style="color: #0000FF;">GetValue</span><span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>, <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>prop.<span style="color: #0000FF;">PropertyType</span> == <span style="color: #008000;">typeof</span> <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">bool</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">bool</span><span style="color: #000000;">&#41;</span> v ? parameter.<span style="color: #0000FF;">Parameter</span> : <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Empty</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>prop.<span style="color: #0000FF;">PropertyType</span> == <span style="color: #008000;">typeof</span> <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">IsNullOrEmpty</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span><span style="color: #000000;">&#41;</span> v<span style="color: #000000;">&#41;</span> ? <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Empty</span> : <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Format</span><span style="color: #000000;">&#40;</span>parameter.<span style="color: #0000FF;">Parameter</span>, v<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> v == <span style="color: #0600FF;">null</span> ? <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Empty</span> : <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Format</span><span style="color: #000000;">&#40;</span>parameter.<span style="color: #0000FF;">Parameter</span>, v<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">override</span> MessageImportance StandardOutputLoggingImportance<br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; get<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; MessageImportance importance;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #FF0000;">Enum</span>.<span style="color: #0000FF;">TryParse</span><span style="color: #000000;">&#40;</span>OutputImportance, <span style="color: #0600FF;">true</span>, <span style="color: #0600FF;">out</span> importance<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> importance;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>DefaultValue<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;low&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> OutputImportance <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span><br />
&nbsp; <span style="color: #000000;">&#125;</span></div></div>
<p>A sparse implementation of rsync:</p>
<div class="codecolorer-container csharp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"> &nbsp;<span style="color: #000000;">&#91;</span>ParameterString<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;{Recursive} {Quiet} {Verbose} {Progress} {Passwordfile} {Source} {Target}&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> RSync : CmdTask<br />
&nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>DefaultValue<span style="color: #000000;">&#40;</span><span style="color: #0600FF;">true</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Description<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;recurse into directories&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Parameter<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;--recursive&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> Recursive <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Parameter<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;--progress&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> Progress <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Parameter<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;--verbose&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> Verbose <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Parameter<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;--quiet&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> Quiet <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Parameter<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;--passwordfile={0}&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> Passwordfile <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span> &nbsp; &nbsp;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Parameter<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;{0}&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> Source <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Parameter<span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;{0}&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> Target <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span> &nbsp; &nbsp;<br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">override</span> <span style="color: #FF0000;">string</span> ToolName<br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; get <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> <span style="color: #808080;">&quot;rsync.exe&quot;</span>; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; <span style="color: #000000;">&#125;</span></div></div>
<p>As you can see, there is no code &#8211; other than the declarative parts &#8211; required to wrap a command line excutable into an msbuild command, regardless of the number of parameters it needs.</p>
<p>Happy building!</p>
<p>&#8211;Jesper Hogstrom</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fmagpie.sytes.net%2Fjesperhogstrom%2F2010%2F12%2Fwriting-msbuild-tasks-declaratively%2F&amp;title=Writing%20msbuild%20tasks%20declaratively"><img src="http://magpie.sytes.net/jesperhogstrom/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://magpie.sytes.net/jesperhogstrom/2010/12/writing-msbuild-tasks-declaratively/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Chilispetsat glöggrecept</title>
		<link>http://magpie.sytes.net/jesperhogstrom/2010/12/chilispetsat-gloggrecept/</link>
		<comments>http://magpie.sytes.net/jesperhogstrom/2010/12/chilispetsat-gloggrecept/#comments</comments>
		<pubDate>Fri, 10 Dec 2010 23:47:11 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[personligt]]></category>
		<category><![CDATA[svenska]]></category>
		<category><![CDATA[glögg]]></category>
		<category><![CDATA[recept]]></category>

		<guid isPermaLink="false">http://magpie.sytes.net/jesperhogstrom/?p=523</guid>
		<description><![CDATA[Efter en höst med god skörd av äppelvin har det bu blivit dags att göra glögg. Efter lite experimenterande har jag kommit fram till följande: Ta en påse Santa Maria Glöggkryddor och lägg i ett kärl. Ta två skivor (3-4mm) ingefära och lägg i samma kärl. Klipp ner ringar (2-3mm) av en halv thai chilifrukt [...]]]></description>
			<content:encoded><![CDATA[<p>Efter en höst med god skörd av äppelvin har det bu blivit dags att göra glögg. Efter lite experimenterande har jag kommit fram till följande:</p>
<p>Ta en påse Santa Maria Glöggkryddor och lägg i ett kärl.<br />
Ta två skivor (3-4mm) ingefära och lägg i samma kärl.<br />
Klipp ner ringar (2-3mm) av en halv thai chilifrukt i ovan nämnda kärl.<br />
Häll över ca 1.5-2 dl vit sprit, vodka e dyl.</p>
<p>Vänta i ett dygn  (det är den svåraste delen <img src='http://magpie.sytes.net/jesperhogstrom/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ).</p>
<p>Häll ner alltihop i en gryta, häll ner 1 flaska halvtorrt vitt vin (jag tar naturligtvis mitt eget äppelvin!).<br />
Tillsätt ca 1.5dl <a href="http://www.dansukker.com/Default.aspx?ID=1137">muscavadosocker</a>. Öka i förhållande till vinets torrhet!<br />
Koka upp under varsam omrörning.</p>
<p>Stäng av plattan och häll ner 0.5-1 dl enkel whiskey (inte rökig singlemalt!) och en skvätt gin. Om du har lite sherry eller portvin så häll på en skvätt av det med. Det mjukar upp smaken.</p>
<p>Rör om och vänta ett par minuter. Häll upp i muggar &#8211; jag menar glöggkoppar och njut!</p>
<p>Som tillbehör använder jag <a href="http://www.dansukker.com/Default.aspx?ID=90&#038;ProductPage=1&#038;ProductID=96&#038;GroupID=7">kandisocker</a>, mest för att i efterhand kunna balansera sötman i drycken. Lagom sött = inget kandi! Aningen för torrt &#8211; 1-2 kandi-bitar. Och så vidare.</p>
<p>Chilin ger glöggen en eldighet som värmer gott i vintermörkret.</p>
<p>När allt tagit slut kan du ta vara på kryddorna, lägga tillbaka dem i kärlet och hälla på ny sprit. Imorgon kvaäll kan du börja om. Då och då kan du lägga i mer av antingen kanelstång, ingefära eller nejlika.</p>
<p>&#8211;Jesper</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fmagpie.sytes.net%2Fjesperhogstrom%2F2010%2F12%2Fchilispetsat-gloggrecept%2F&amp;title=Chilispetsat%20gl%C3%B6ggrecept"><img src="http://magpie.sytes.net/jesperhogstrom/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://magpie.sytes.net/jesperhogstrom/2010/12/chilispetsat-gloggrecept/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sending mail from msbuild</title>
		<link>http://magpie.sytes.net/jesperhogstrom/2010/12/sending-mail-from-msbuild/</link>
		<comments>http://magpie.sytes.net/jesperhogstrom/2010/12/sending-mail-from-msbuild/#comments</comments>
		<pubDate>Sat, 04 Dec 2010 18:02:13 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[development infrastructure]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[build system]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[msbuild]]></category>

		<guid isPermaLink="false">http://magpie.sytes.net/jesperhogstrom/?p=519</guid>
		<description><![CDATA[Any decent build system must be able to call out for help or just send happy little progress messages. On other OSs than windows it&#8217;s typically as easy as piping something via sendmail. Here, not so easy. Luckily, it&#8217;s not incredibly hard. I wrote myself a little msbuild task that does the job. Here goes: [...]]]></description>
			<content:encoded><![CDATA[<p>Any decent build system must be able to call out for help or just send happy little progress messages. On other OSs than windows it&#8217;s typically as easy as piping something via sendmail. Here, not so easy.</p>
<p>Luckily, it&#8217;s not incredibly hard. I wrote myself a little msbuild task that does the job. Here goes:</p>
<div class="codecolorer-container csharp default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0600FF;">using</span> <span style="color: #000000;">System</span>;<br />
<span style="color: #0600FF;">using</span> <span style="color: #000000;">System</span>.<span style="color: #0000FF;">Globalization</span>;<br />
<span style="color: #0600FF;">using</span> <span style="color: #000000;">System</span>.<span style="color: #0000FF;">Linq</span>;<br />
<span style="color: #0600FF;">using</span> <span style="color: #000000;">System</span>.<span style="color: #0000FF;">Net</span>.<span style="color: #0000FF;">Mail</span>;<br />
<span style="color: #0600FF;">using</span> <span style="color: #000000;">System</span>.<span style="color: #0000FF;">Text</span>;<br />
<span style="color: #0600FF;">using</span> Microsoft.<span style="color: #0000FF;">Build</span>.<span style="color: #0000FF;">Framework</span>;<br />
<span style="color: #0600FF;">using</span> Microsoft.<span style="color: #0000FF;">Build</span>.<span style="color: #0000FF;">Utilities</span>;<br />
<br />
<span style="color: #0600FF;">namespace</span> Jesper.<span style="color: #0000FF;">MsbuildTasks</span><br />
<span style="color: #000000;">&#123;</span><br />
&nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> SendMail: Task<br />
&nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Required<span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> ITaskItem<span style="color: #000000;">&#91;</span><span style="color: #000000;">&#93;</span> To <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> ITaskItem<span style="color: #000000;">&#91;</span><span style="color: #000000;">&#93;</span> Contents <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> Subject <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#91;</span>Required<span style="color: #000000;">&#93;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> Host <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> Port <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> From <span style="color: #000000;">&#123;</span> get; set; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> StringBuilder CreateContents<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; var result = <span style="color: #008000;">new</span> StringBuilder<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; result.<span style="color: #0000FF;">AppendLine</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;[[Sent from fxCop]]&quot;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>Contents != <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span>var content <span style="color: #0600FF;">in</span> Contents<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result.<span style="color: #0000FF;">AppendLine</span><span style="color: #000000;">&#40;</span>content.<span style="color: #0000FF;">ItemSpec</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; Log.<span style="color: #0000FF;">LogMessage</span><span style="color: #000000;">&#40;</span>MessageImportance.<span style="color: #0000FF;">Low</span>, <span style="color: #808080;">&quot;Message contents: {0}&quot;</span>, result<span style="color: #000000;">&#41;</span>;<br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> result;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> <span style="color: #FF0000;">bool</span> Execute<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; var client = <span style="color: #008000;">new</span> SmtpClient<span style="color: #000000;">&#40;</span>Host, ActualPort<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>DeliveryMethod = SmtpDeliveryMethod.<span style="color: #0000FF;">Network</span><span style="color: #000000;">&#125;</span>;<br />
<br />
&nbsp; &nbsp; &nbsp; Log.<span style="color: #0000FF;">LogMessage</span><span style="color: #000000;">&#40;</span>MessageImportance.<span style="color: #0000FF;">Normal</span>, <span style="color: #808080;">&quot;Sending via {0}:{1}&quot;</span>, Host, ActualPort<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">try</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; client.<span style="color: #0000FF;">Send</span><span style="color: #000000;">&#40;</span>CreateMessage<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <span style="color: #0600FF;">true</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">catch</span> <span style="color: #000000;">&#40;</span>Exception e<span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Log.<span style="color: #0000FF;">LogErrorFromException</span><span style="color: #000000;">&#40;</span>e<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <span style="color: #0600FF;">false</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">protected</span> <span style="color: #FF0000;">int</span> ActualPort<br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; get <br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #FF0000;">int</span> port;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> <span style="color: #FF0000;">int</span>.<span style="color: #0000FF;">TryParse</span><span style="color: #000000;">&#40;</span>Port, NumberStyles.<span style="color: #0000FF;">Integer</span>, CultureInfo.<span style="color: #0000FF;">InvariantCulture</span>, <span style="color: #0600FF;">out</span> port<span style="color: #000000;">&#41;</span> ? port : <span style="color: #FF0000;">25</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">private</span> MailMessage CreateMessage<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; var result = <span style="color: #008000;">new</span> MailMessage <span style="color: #000000;">&#123;</span>From = <span style="color: #008000;">new</span> MailAddress<span style="color: #000000;">&#40;</span>From<span style="color: #000000;">&#41;</span>, Body = CreateContents<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">ToString</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>, Subject = ActualSubject<span style="color: #000000;">&#125;</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span>var r <span style="color: #0600FF;">in</span> To.<span style="color: #0000FF;">Select</span><span style="color: #000000;">&#40;</span>recipient =&gt; <span style="color: #008000;">new</span> MailAddress<span style="color: #000000;">&#40;</span>recipient.<span style="color: #0000FF;">ItemSpec</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Log.<span style="color: #0000FF;">LogMessage</span><span style="color: #000000;">&#40;</span>MessageImportance.<span style="color: #0000FF;">Normal</span>, <span style="color: #808080;">&quot;Sending to {0}&quot;</span>, r<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; result.<span style="color: #0000FF;">To</span>.<span style="color: #0000FF;">Add</span><span style="color: #000000;">&#40;</span>r<span style="color: #000000;">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> result;<br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #0600FF;">protected</span> <span style="color: #FF0000;">string</span> ActualSubject<br />
&nbsp; &nbsp; <span style="color: #000000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; get <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> Subject ?? <span style="color: #808080;">&quot;Sent from fxcop&quot;</span>; <span style="color: #000000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000;">&#125;</span><br />
&nbsp; <span style="color: #000000;">&#125;</span><br />
<span style="color: #000000;">&#125;</span></div></div>
<p>Using it in a script might look something like:</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;UsingTask</span> <span style="color: #000066;">TaskName</span>=<span style="color: #ff0000;">&quot;SendMail&quot;</span> <span style="color: #000066;">AssemblyFile</span>=<span style="color: #ff0000;">&quot;Jesper.MsBuildTasks.dll&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span><br />
<br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;Target</span> <span style="color: #000066;">Name</span>=<span style="color: #ff0000;">&quot;foo&quot;</span><span style="font-weight: bold; color: black;">&gt;</span></span>&nbsp;<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;SendMail</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #000066;">To</span>=<span style="color: #ff0000;">&quot;jesper@somewhere.else;jayone@elsewhere.net&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000066;">From</span>=<span style="color: #ff0000;">&quot;jesper@buildmachine.home&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000066;">Host</span>=<span style="color: #ff0000;">&quot;smtphost.home&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000066;">Contents</span>=<span style="color: #ff0000;">&quot;@(SomeDataToSend)&quot;</span><span style="font-weight: bold; color: black;">/&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/Target<span style="font-weight: bold; color: black;">&gt;</span></span></span></div></div>
<p>Once I had that written and tested, I decided to check if either the <a href="http://msbuildtasks.tigris.org/">tigris community tasks</a> or the <a href="http://msbuildextensionpack.codeplex.com/">microsoft extension pack</a> included something similar.</p>
<p>Yes they do. Both of them. However, it was a nice exercise in writing msbuild tasks and a reminder to first check what is available out there <img src='http://magpie.sytes.net/jesperhogstrom/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>&#8211;Jesper</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fmagpie.sytes.net%2Fjesperhogstrom%2F2010%2F12%2Fsending-mail-from-msbuild%2F&amp;title=Sending%20mail%20from%20msbuild"><img src="http://magpie.sytes.net/jesperhogstrom/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://magpie.sytes.net/jesperhogstrom/2010/12/sending-mail-from-msbuild/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>More visible tabs in firefox</title>
		<link>http://magpie.sytes.net/jesperhogstrom/2010/11/more-visible-tabs-in-firefox/</link>
		<comments>http://magpie.sytes.net/jesperhogstrom/2010/11/more-visible-tabs-in-firefox/#comments</comments>
		<pubDate>Wed, 24 Nov 2010 10:06:40 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Computer tricks]]></category>
		<category><![CDATA[Leisure]]></category>
		<category><![CDATA[browing]]></category>
		<category><![CDATA[firefox]]></category>

		<guid isPermaLink="false">http://magpie.sytes.net/jesperhogstrom/?p=509</guid>
		<description><![CDATA[I tend to use a lot of open tabs in my firefox sessions. There&#8217;s the gmail tab, build server, bug tracker &#8211; usually a few of them, a couple of blog entries I intend to read soon, daily news and some interesting links sent to me that I&#8217;ll get to soon. It&#8217;s like a combined [...]]]></description>
			<content:encoded><![CDATA[<p>I tend to use a lot of open tabs in my firefox sessions. There&#8217;s the gmail tab, build server, bug tracker &#8211; usually a few of them, a couple of blog entries I intend to read soon, daily news and some interesting links sent to me that I&#8217;ll get to soon. It&#8217;s like a combined to-do list and status dashboard.</p>
<p>The problem is that the tabs very soon spans the available space and scrolling becomes necessary.</p>
<p><img src="file:///C:/Users/JHOGST%7E1/AppData/Local/Temp/moz-screenshot-1.png" alt="" /><a href="http://magpie.sytes.net/jesperhogstrom/wp-content/uploads/2010/11/firefox-wide-tabs2.png"><img class="alignnone size-full wp-image-513" title="firefox wide tabs" src="http://magpie.sytes.net/jesperhogstrom/wp-content/uploads/2010/11/firefox-wide-tabs2.png" alt="" width="340" height="86" /></a></p>
<p>To the rescue is the firefox settings.</p>
<p>Type in &#8220;about:config&#8221; in the address field. Acknowledge that you know what you&#8217;re doing.</p>
<p>Filter the rather large (and very interesting!) list of things possible to change by typing &#8220;width&#8221; in the filter-field.</p>
<p><a href="http://magpie.sytes.net/jesperhogstrom/wp-content/uploads/2010/11/firefox-filter.png"><img class="alignnone size-full wp-image-514" title="firefox filter" src="http://magpie.sytes.net/jesperhogstrom/wp-content/uploads/2010/11/firefox-filter.png" alt="" width="470" height="130" /></a></p>
<p>Change 100 to 16 and restart firefox.</p>
<p>Now, your tabs will shrink down to 16 pixels, enough to keep the favicon visible, and you can see many more before scrolling kicks in.</p>
<p><a href="http://magpie.sytes.net/jesperhogstrom/wp-content/uploads/2010/11/firefox-small-tabs.png"><img class="alignnone size-full wp-image-516" title="firefox small tabs" src="http://magpie.sytes.net/jesperhogstrom/wp-content/uploads/2010/11/firefox-small-tabs.png" alt="" width="427" height="28" /></a></p>
<p>Happy browsing!</p>
<p>&#8211;Jesper Hogstrom</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fmagpie.sytes.net%2Fjesperhogstrom%2F2010%2F11%2Fmore-visible-tabs-in-firefox%2F&amp;title=More%20visible%20tabs%20in%20firefox"><img src="http://magpie.sytes.net/jesperhogstrom/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://magpie.sytes.net/jesperhogstrom/2010/11/more-visible-tabs-in-firefox/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

