<?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>David Woods</title>
	<atom:link href="http://www.haveyougotwoods.ca/feed" rel="self" type="application/rss+xml" />
	<link>http://www.haveyougotwoods.ca</link>
	<description>Security, Tip, Tricks, Beer</description>
	<lastBuildDate>Thu, 13 Sep 2012 19:11:35 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Source Of Truth</title>
		<link>http://www.haveyougotwoods.ca/2012/09/13/source-of-truth</link>
		<comments>http://www.haveyougotwoods.ca/2012/09/13/source-of-truth#comments</comments>
		<pubDate>Thu, 13 Sep 2012 19:11:35 +0000</pubDate>
		<dc:creator>david.woods</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.haveyougotwoods.ca/?p=354</guid>
		<description><![CDATA[Sometimes, you get spoiled by how things are done in organizations. I am having one of those moments today so I figured I should write about it. A good development environment needs a source of truth and a clear separation of concerns. 1) Source control is your source of truth. Anything not in source control did not [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes, you get spoiled by how things are done in organizations. I am having one of those moments today so I figured I should write about it. A good development environment needs a source of truth and a clear separation of concerns.</p>
<p>1) Source control is your source of truth. Anything not in source control did not happen. If you make a live edit to a file on the production server it is gone with the next update. This should never be allowed to happen. This is why I do a lot of deployments out of my  continuous integration server. The only way to deploy is for the server to get the latest version from source control and install it on the server. If it was not important to put into source control it was not important.</p>
<p>2) Be careful managing your database(s). I usually recommend each developer runs a local database. This way changes to the dev database don&#8217;t break other peoples code until you check your source code in. Having a system where change scripts are checked in an run can be troublesome to implement but it is worth it. The benefit being that when you migrate to your different environments you have a suite of scripts already written. Ensure these are in source control</p>
<p>3) Verification is a time consuming process. Having to diff filesystems and databases to find the truth is a time consuming process that is fraught with errors. One project I am inherited has source in four (or more) locations so establishing which is the most current is a frightening process.</p>
<p>4) Establish the different environments very clearly and limit access where appropriate. If you have a mess of servers with some running production and test and development you are going to hit points of confusion or have inadvertent updates to applications. It is simple enough to accidentally update the production database by accident if they are on the same server as your development database. I have always felt that developers should have almost zero access to the production system where possible. Yes, it makes it easier to debug but there are ways to allow developers to debug without making changes (e.g. access to the event log, read only access to the database / filesystem, etc.). I avoid even that due to security implications but if you need to then there are better options than admin rights to the production server.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.haveyougotwoods.ca/2012/09/13/source-of-truth/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Security Is Security</title>
		<link>http://www.haveyougotwoods.ca/2012/08/24/security-is-security</link>
		<comments>http://www.haveyougotwoods.ca/2012/08/24/security-is-security#comments</comments>
		<pubDate>Fri, 24 Aug 2012 14:31:45 +0000</pubDate>
		<dc:creator>david.woods</dc:creator>
				<category><![CDATA[Rants]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://www.haveyougotwoods.ca/?p=350</guid>
		<description><![CDATA[Something the past few days that has been irking me and seems to be a growing trend in the security space are comments like this: &#8220;This attack is irrelevant because doing Y is cheaper/easier&#8221; You are right. If I were an attacker I would try the simplest method first. If that fails do I go [...]]]></description>
			<content:encoded><![CDATA[<p>Something the past few days that has been irking me and seems to be a growing trend in the security space are comments like this:</p>
<p>&#8220;This attack is irrelevant because doing Y is cheaper/easier&#8221;</p>
<p>You are right. If I were an attacker I would try the simplest method first. If that fails do I go home and watch My Little Pony reruns because I could not telnet to your server with a blank password? No, I try increasingly more complex attacks until I get in.</p>
<p>Security is Security. Just because someone can set the data center on fire does not mean you should not secure the machines within it.</p>
<p>/rant</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.haveyougotwoods.ca/2012/08/24/security-is-security/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Local Build Using/Incrementing Team City Version Number</title>
		<link>http://www.haveyougotwoods.ca/2012/06/18/local-build-usingincrementing-team-city-version-number</link>
		<comments>http://www.haveyougotwoods.ca/2012/06/18/local-build-usingincrementing-team-city-version-number#comments</comments>
		<pubDate>Mon, 18 Jun 2012 16:21:12 +0000</pubDate>
		<dc:creator>david.woods</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.haveyougotwoods.ca/?p=347</guid>
		<description><![CDATA[On my current project we have a problem in that one of the assemblies we use requires an expensive license that is per computer so our build server would need it&#8217;s own license which we are not doing at this point. Now I need to run our publish deploy script locally which means manually increasing [...]]]></description>
			<content:encoded><![CDATA[<p>On my current project we have a problem in that one of the assemblies we use requires an expensive license that is per computer so our build server would need it&#8217;s own license which we are not doing at this point. Now I need to run our publish deploy script locally which means manually increasing the version number on each build. Something that has been missed before causing a new version to overwrite an old version&#8230; which is bad&#8230; very bad.</p>
<p>To combat this I started digging and found a way to have my build script use and change the TeamCity build counter remotely using their REST API.</p>
<p>First open up <a href="http://iisbackup.solidhouse.com:8080/httpAuth/app/rest/projects/id:project2">http://[Server]/httpAuth/app/rest/projects/</a> and find your project you want to work with.</p>
<p>Then open up <a href="http://iisbackup.solidhouse.com:8080/httpAuth/app/rest/projects/id:project2">http://[Server]/httpAuth/app/rest/projects/id:project2</a> and find the configuration you want to work with.</p>
<p>Then open up <a href="http://iisbackup.solidhouse.com:8080/httpAuth/app/rest/buildTypes/bt5/settings/buildNumberCounter">http://[Server]/httpAuth/app/rest/buildTypes/bt5/settings/buildNumberCounter</a> to get the current build counter</p>
<p>Here is the C# code I use</p>
<div>    public class TeamCityVersionIncrementer</div>
<div>    {</div>
<div>        private readonly string _buildCounterUri;</div>
<div>        private readonly NetworkCredential _credentials;</div>
<div></div>
<div>        public TeamCityVersionIncrementer()</div>
<div>        {</div>
<div>            _buildCounterUri = &#8220;http://[server]/httpAuth/app/rest/buildTypes/bt5/settings/buildNumberCounter&#8221;;</div>
<div>            _credentials = new NetworkCredential(&#8220;[user]&#8220;, &#8220;[pass]&#8220;);</div>
<div>        }</div>
<div></div>
<div>        public int Increment()</div>
<div>        {</div>
<div>            int originalCounter = GetBuildCounterFromTeamCity();</div>
<div>            UpdateCounter(originalCounter + 1);</div>
<div>            int counterAfterIncrement = GetBuildCounterFromTeamCity();</div>
<div>            if (counterAfterIncrement != originalCounter + 1)</div>
<div>            {</div>
<div>                throw new ApplicationException(&#8220;Expected build to be incremented to &#8221; + (originalCounter + 1) + &#8220;but was &#8221; + counterAfterIncrement);</div>
<div>            }</div>
<div>            return counterAfterIncrement;</div>
<div>        }</div>
<div></div>
<div>        private int GetBuildCounterFromTeamCity()</div>
<div>        {</div>
<div>            WebRequest webrequest = WebRequest.Create(_buildCounterUri);</div>
<div>            webrequest.Credentials = _credentials;</div>
<div>            webrequest.Method = &#8220;GET&#8221;;</div>
<div>            WebResponse webResponse = webrequest.GetResponse();</div>
<div>            using (var reader = new StreamReader(webResponse.GetResponseStream()))</div>
<div>            {</div>
<div>                string readToEnd = reader.ReadToEnd();</div>
<div>                return int.Parse(readToEnd);</div>
<div>            }</div>
<div>        }</div>
<div></div>
<div></div>
<div>        private void UpdateCounter(int number)</div>
<div>        {</div>
<div>            byte[] arr = Encoding.UTF8.GetBytes(number.ToString());</div>
<div>            var request = (HttpWebRequest)WebRequest.Create(_buildCounterUri);</div>
<div></div>
<div>            request.Method = &#8220;PUT&#8221;;</div>
<div>            request.ContentType = &#8220;text/xml&#8221;;</div>
<div>            request.ContentLength = arr.Length;</div>
<div>            request.Credentials = _credentials;</div>
<div>            Stream dataStream = request.GetRequestStream();</div>
<div>            dataStream.Write(arr, 0, arr.Length);</div>
<div>            dataStream.Close();</div>
<div>            var response = (HttpWebResponse)request.GetResponse();</div>
<div>            if (response.StatusCode != HttpStatusCode.NoContent)</div>
<div>                throw new ApplicationException(&#8220;Unexepected status code: &#8221; + response.StatusCode);</div>
<div>        }</div>
<div>    }</div>
<div></div>
<p>Hope that helps someone in this rare situation!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.haveyougotwoods.ca/2012/06/18/local-build-usingincrementing-team-city-version-number/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>LinkedIn Hashes Leaked</title>
		<link>http://www.haveyougotwoods.ca/2012/06/06/linkedin-hashes-leaked</link>
		<comments>http://www.haveyougotwoods.ca/2012/06/06/linkedin-hashes-leaked#comments</comments>
		<pubDate>Wed, 06 Jun 2012 16:48:47 +0000</pubDate>
		<dc:creator>david.woods</dc:creator>
				<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://www.haveyougotwoods.ca/?p=344</guid>
		<description><![CDATA[Today it is being reported that LinkedIn has 6.5 million hashes leaked. It is good to see that the passwords were hashed. Unfortunately, it was done in a poor fashion. The main issue is that salts were not used. Salts add random data per password and then are hashed. This makes things drastically harder to crack. [...]]]></description>
			<content:encoded><![CDATA[<p>Today it is being reported that LinkedIn has 6.5 million hashes leaked. It is good to see that the passwords were hashed. Unfortunately, it was done in a poor fashion.</p>
<p>The main issue is that salts were not used. Salts add random data per password and then are hashed. This makes things drastically harder to crack. Why? Well in attacking a database of hashes (without salts) the procedure is:</p>
<ol>
<li>Generate a password</li>
<li>Hash the password</li>
<li>Compare the hash to all items in the database</li>
</ol>
<p>This means that we generate one hash and check it against every account. If we add salts to the mix we have to work on a password at a time</p>
<ol>
<li>Load hash and salt from database</li>
<li>Generate a password</li>
<li>Hash the password + salt</li>
<li>Compare the generated hash to the one record</li>
</ol>
<p>For this scenario we have to crack a user at a time which is a huge time increase. Also, we don&#8217;t know how the salt was used internally. It could be:</p>
<ul>
<li>password + salt</li>
<li>salt + password</li>
<li>salt + password + salt</li>
<li>FirstHalfOfSalt + password + LastHalfOfSalt</li>
<li>etc.</li>
</ul>
<p>&nbsp;</p>
<p>Lack of salting is a big failure here and I don&#8217;t see why it was not done. The other issue is the use of SHA-1 as the hashing algorithm which is no longer recommended. SHA-1 is fairly strong but has some collision weaknesses (two words generate the same hash which reduces the amount of time to generate all hashes). It is recommended to use SHA-256 or higher to avoid this issue.</p>
<p>While this may have been an oversight of the developers involved it is more likely a case of hash/crypto phobia. It is scary dealing with hashes and crypto as if you screw up data could be irreversibly lost. As developers we always want recoverability and not to mess with things that are working. Unfortunately for this sort of data we have to face the problem.</p>
<p>Now the big issue people face is migrating hashes from one scheme to another. Most leave it as is because hashes are one way so we can&#8217;t reverse the hash to upgrade it to a new format. It is quite easy to do though in a way that allows a seamless migration:</p>
<ul>
<li>Add in new fields to store the new format into your database</li>
<li>When a user successfully logs in, take the password they typed in (which would be the plain text version) and run it through the new algorithm.</li>
<li>Store the output into the new database fields</li>
<li>Remove the original hash (the one we are replacing) from the database</li>
</ul>
<p>As users login they get upgraded to the new scheme. It takes very little logic and time to implement this. The more users that login the stronger the database store gets.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.haveyougotwoods.ca/2012/06/06/linkedin-hashes-leaked/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Syncing Facebook/Meetup/Google Calendar On My phone</title>
		<link>http://www.haveyougotwoods.ca/2012/06/05/syncing-facebookmeetupgoogle-calendar-on-my-phone</link>
		<comments>http://www.haveyougotwoods.ca/2012/06/05/syncing-facebookmeetupgoogle-calendar-on-my-phone#comments</comments>
		<pubDate>Tue, 05 Jun 2012 19:11:29 +0000</pubDate>
		<dc:creator>david.woods</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.haveyougotwoods.ca/?p=341</guid>
		<description><![CDATA[One issue I have been running into is not adding my facebook/meetup events onto my phone. I then miss these events or forget until the last minute. I thought there must be a way to automate this and after a bit of tinkering I got it to work. I am on an iPhone that uses [...]]]></description>
			<content:encoded><![CDATA[<p>One issue I have been running into is not adding my facebook/meetup events onto my phone. I then miss these events or forget until the last minute. I thought there must be a way to automate this and after a bit of tinkering I got it to work.</p>
<p>I am on an iPhone that uses Google Calendar as it&#8217;s calendar provider. I assume that the steps will be the same for any device that supports Google Calendar:</p>
<p><strong>Facebook</strong></p>
<ol>
<li>Click events on the left</li>
<li>click export events</li>
<li>copy the url</li>
<li>login to google calendar</li>
<li>under other calendars click &#8220;add by url&#8221;</li>
<li>paste in the url for your fb calendar</li>
</ol>
<p><strong>Meetup</strong></p>
<ol>
<li>On the main page click the &#8220;add to&#8221; right above the calendar</li>
<li>Click the Google Calendar icon</li>
<li>It will open up the google calendar website and prompt you to add it</li>
</ol>
<p>Once this is done the calendars did not appear on my phone. Some people posted to add them by visiting: https://www.google.com/calendar/iphoneselect which did nothing for me.</p>
<p>After a bit more reading I found that if I opened http://m.google.com/sync on my phone I could check off the calendars I wanted to snyc and viola there they were.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.haveyougotwoods.ca/2012/06/05/syncing-facebookmeetupgoogle-calendar-on-my-phone/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Announcing FluentBuild.UI</title>
		<link>http://www.haveyougotwoods.ca/2012/05/23/announcing-fluentbuild-ui</link>
		<comments>http://www.haveyougotwoods.ca/2012/05/23/announcing-fluentbuild-ui#comments</comments>
		<pubDate>Wed, 23 May 2012 16:01:55 +0000</pubDate>
		<dc:creator>david.woods</dc:creator>
				<category><![CDATA[FluentBuild]]></category>

		<guid isPermaLink="false">http://www.haveyougotwoods.ca/?p=336</guid>
		<description><![CDATA[One of my pet peeves has always been how hard it is to read the output of a build in a dos window. It is hard to navigate and with lots of output it is easy to loose content. To that end I decided to create a windows UI for FluentBuild that I just committed [...]]]></description>
			<content:encoded><![CDATA[<p>One of my pet peeves has always been how hard it is to read the output of a build in a dos window. It is hard to navigate and with lots of output it is easy to loose content. To that end I decided to create a windows UI for FluentBuild that I just committed to source.</p>
<p>It still needs some work but it is there for any early adopters (click for a bigger screenshot):</p>
<p style="text-align: center;"><a href="http://www.haveyougotwoods.ca/wp-content/uploads/2012/05/FB.UI_.jpg"><img class="aligncenter  wp-image-337" title="FluentBuild UI" src="http://www.haveyougotwoods.ca/wp-content/uploads/2012/05/FB.UI_.jpg" alt="" width="560" height="327" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.haveyougotwoods.ca/2012/05/23/announcing-fluentbuild-ui/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>FluentBuild &#8211; 1.1 Beta</title>
		<link>http://www.haveyougotwoods.ca/2012/05/19/fluentbuild-1-1-beta</link>
		<comments>http://www.haveyougotwoods.ca/2012/05/19/fluentbuild-1-1-beta#comments</comments>
		<pubDate>Sun, 20 May 2012 00:47:05 +0000</pubDate>
		<dc:creator>david.woods</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.haveyougotwoods.ca/?p=334</guid>
		<description><![CDATA[I have published the FB 1.1 Beta (http://code.google.com/p/fluent-build/downloads/list). This release contains some big changes. Task Syntax Gone are things like Run.[option].[option].Execute() and they have been replaced with Task.Run.Nunit(options=&#62;options.specific.to.runner). This removes the need to remember to use .Execute() all the time (I was constantly forgetting and I wrote the thing). I am fairly happy with it [...]]]></description>
			<content:encoded><![CDATA[<p>I have published the FB 1.1 Beta (<a href="http://code.google.com/p/fluent-build/downloads/list">http://code.google.com/p/fluent-build/downloads/list</a>).</p>
<p>This release contains some big changes.</p>
<p><strong>Task Syntax</strong></p>
<p>Gone are things like Run.[option].[option].Execute() and they have been replaced with Task.Run.Nunit(options=&gt;options.specific.to.runner). This removes the need to remember to use .Execute() all the time (I was constantly forgetting and I wrote the thing). I am fairly happy with it so far.</p>
<p>Exampes:</p>
<p>Task.Build.Csc.Target.Library(compiler =&gt; compiler.AddSources(sourceFiles)<br />
.AddRefences(thirdparty_rhino, thirdparty_nunit)<br />
.OutputFileTo(assembly_FluentBuild_Tests));</p>
<p>Task.Run.UnitTestFramework.Nunit(nUnitRunner=&gt;nUnitRunner.FileToTest(assembly_FluentBuild));</p>
<p>Task.Run.Zip(x=&gt;x.Compress</p>
<p>.SourceFolder(directory_compile)<br />
.UsingCompressionLevel.Nine<br />
.To(directory_release.File(&#8220;release.zip&#8221;)));</p>
<p><strong>FTP Publishing</strong><br />
As I mentioned in a previous post I added some quick and dirty FTP publishing. It only publishes a file at a time currently so its not a full fledged FTP publishing tool.</p>
<p><strong>Errors</strong><br />
For a while I only had the error message publishing but I have switched that to include the full exception as it was problematic to find errors before. There have also been some internal changes to how return codes are handled from programs. If a third party program throws an error then FB will return an error code of 1, not the error code of the third part application.</p>
<p><strong>Logger</strong><br />
The message logger code has been simplified a lot and will probably get another round of cleanup soon. It has been moved to Defaults.Logger for now but will probably get moved right into the BuildFile class you inherit from as that makes more sense to me from a user point of view.</p>
<p><strong>Whats Next?</strong><br />
I am getting fairly happy with the application right now but I would like to do more testing before I release it. I will be tweaking a bit of code and adding some more functional tests to the build but I hope not to have any big changes for the next while.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.haveyougotwoods.ca/2012/05/19/fluentbuild-1-1-beta/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rudimentary FTP Support</title>
		<link>http://www.haveyougotwoods.ca/2012/05/15/rudimentary-ftp-support</link>
		<comments>http://www.haveyougotwoods.ca/2012/05/15/rudimentary-ftp-support#comments</comments>
		<pubDate>Wed, 16 May 2012 04:00:47 +0000</pubDate>
		<dc:creator>david.woods</dc:creator>
				<category><![CDATA[FluentBuild]]></category>

		<guid isPermaLink="false">http://www.haveyougotwoods.ca/?p=330</guid>
		<description><![CDATA[While it was planned as a feature in the future, necessity bumped it up for me on my current project so I added some rudimentary FTP support. Task.Publish.Ftp(x =&#62; x.Server(&#8220;ftp.server.com&#8221;) .UserName(&#8220;username&#8221;) .Password(&#8220;password&#8221;) .LocalFilePath(@&#8221;c:\temp\test.txt&#8221;) .Timeout(new TimeSpan(0,0,15,0)) .RemoteFilePath(&#8220;/html/&#8221;) ); It only supports one file at a time and re-authenticates per request for now so uploading a folder [...]]]></description>
			<content:encoded><![CDATA[<p>While it was planned as a feature in the future, necessity bumped it up for me on my current project so I added some rudimentary FTP support.</p>
<p>Task.Publish.Ftp(x =&gt; x.Server(&#8220;ftp.server.com&#8221;)<br />
.UserName(&#8220;username&#8221;)<br />
.Password(&#8220;password&#8221;)<br />
.LocalFilePath(@&#8221;c:\temp\test.txt&#8221;)<br />
.Timeout(new TimeSpan(0,0,15,0))<br />
.RemoteFilePath(&#8220;/html/&#8221;)<br />
);</p>
<p>It only supports one file at a time and re-authenticates per request for now so uploading a folder structure is not recommended at this point. A more full fledged solution will be coming.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.haveyougotwoods.ca/2012/05/15/rudimentary-ftp-support/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>New Run Syntax</title>
		<link>http://www.haveyougotwoods.ca/2012/04/17/new-run-syntax</link>
		<comments>http://www.haveyougotwoods.ca/2012/04/17/new-run-syntax#comments</comments>
		<pubDate>Tue, 17 Apr 2012 22:04:16 +0000</pubDate>
		<dc:creator>david.woods</dc:creator>
				<category><![CDATA[FluentBuild]]></category>

		<guid isPermaLink="false">http://www.haveyougotwoods.ca/?p=326</guid>
		<description><![CDATA[I came up with a new run syntax that I like: Task.Run.Zip(x=&#62;x.Compress.SourceFile(&#8220;test.dll&#8221;).OutputTo(&#8220;test.zip&#8221;)); Task.Run.Executable(x=&#62;x.PathToExecutable(&#8220;test.exe&#8221;)); Due to the scope of the change (and the fact that I have not switched to git yet), I have committed this code but there are still a lot more changes to be polished (and some namespace moves still to be done). I hope [...]]]></description>
			<content:encoded><![CDATA[<p>I came up with a new run syntax that I like:</p>
<p>Task.Run.Zip(x=&gt;x.Compress.SourceFile(&#8220;test.dll&#8221;).OutputTo(&#8220;test.zip&#8221;));<br />
Task.Run.Executable(x=&gt;x.PathToExecutable(&#8220;test.exe&#8221;));</p>
<p>Due to the scope of the change (and the fact that I have not switched to git yet), I have committed this code but there are still a lot more changes to be polished (and some namespace moves still to be done). I hope to have some time for further refinement and a ton of cleanup after this change in the coming week.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.haveyougotwoods.ca/2012/04/17/new-run-syntax/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Run Syntax Feedback</title>
		<link>http://www.haveyougotwoods.ca/2012/04/12/new-run-syntax-feedback</link>
		<comments>http://www.haveyougotwoods.ca/2012/04/12/new-run-syntax-feedback#comments</comments>
		<pubDate>Thu, 12 Apr 2012 13:58:02 +0000</pubDate>
		<dc:creator>david.woods</dc:creator>
				<category><![CDATA[FluentBuild]]></category>

		<guid isPermaLink="false">http://www.haveyougotwoods.ca/?p=322</guid>
		<description><![CDATA[I have completed the new build sytax of Task.Build(Using.[Compiler].[Options]); which I like way better than the old syntax. It is a bit annoying to have a few extra brackets but already makes it easier to use to me. I liked it so much that I started applying this to the Run syntax but that is [...]]]></description>
			<content:encoded><![CDATA[<p>I have completed the new build sytax of Task.Build(Using.[Compiler].[Options]); which I like way better than the old syntax. It is a bit annoying to have a few extra brackets but already makes it easier to use to me. I liked it so much that I started applying this to the Run syntax but that is where I found things did not work as well. I figured I would throw out the syntax ideas I had and see what people thought:</p>
<p>&nbsp;<br />
<strong>Option One: Generic run method</strong><br />
+simple to use<br />
+expandable<br />
-need to know what can be run (might be in one namespace)<br />
-how do you handle executable return codes? (or other result objects)</p>
<p>Task.Run(Zip.Compress.SourceFile(&#8220;tests.dll&#8221;).UsingCompressionLevel.Ten);<br />
Task.Run(Zip.Decompress.SourceFile(&#8220;tests.zip&#8221;));<br />
Task.Run(Executable.Path(&#8220;test.exe&#8221;));<br />
Task.Run(Debugger);<br />
Task.Run(Nunit.Assembly(&#8220;tests.dll&#8221;));<br />
Task.Run(MsTest.Assembly(&#8220;tests.dll&#8221;));</p>
<p><strong>Option Two: Run narrows down choices then builders are used as arguments</strong><br />
+simple to use<br />
+lets you know options available<br />
+Allows for return codes for items that require it (or other result objects)<br />
-much more language required to learn</p>
<p>Task.Run.Zip(Compress.SourceFile(&#8220;tests.dll&#8221;).UsingCompressionLevel.Ten);<br />
Task.Run.Zip(Decompress.SourceFile(&#8220;tests.zip&#8221;));<br />
Task.Run.Executable(Executable.Path(&#8220;test.exe&#8221;));<br />
Task.Run.Debugger();<br />
Task.Run.UnitTestFramework(Nunit.Assembly(&#8220;tests.dll&#8221;));<br />
Task.Run.UnitTestFramework(MsTest.Assembly(&#8220;tests.dll&#8221;));<br />
<strong>Option Three: Run narrows down choices to the most narrow point then builders are used as arguments</strong><br />
+simple to use<br />
+lets you know options available<br />
+Allows for return codes for items that require it (or other result objects)<br />
+Intellisense would only give you one option for the arg to pass in<br />
-Bit more verbose with the &#8220;Options&#8221; builders</p>
<p>Task.Run.Zip.Compress(CompressOptions.SourceFile(&#8220;tests.dll&#8221;).UsingCompressionLevel.Ten);<br />
Task.Run.Zip.Decompress(DecompressOptions.SourceFile(&#8220;tests.zip&#8221;));<br />
Task.Run.Executable(Executable.Path(&#8220;test.exe&#8221;));<br />
Task.Run.Debugger();<br />
Task.Run.UnitTestFramework.Nunit(NunitOptions.Assembly(&#8220;tests.dll&#8221;));<br />
Task.Run.UnitTestFramework.MsTest(MsTestOptions.Assembly(&#8220;tests.dll&#8221;));<br />
<strong>Option Four: Have a runners factory class that creates the builders</strong><br />
-need to know to do Runners.<br />
+always know where to start (once you know to use Runners.<br />
+simple syntax<br />
-How do you handle executable return codes? (or other result objects)</p>
<p>Task.Run(Runners.Zip.Compress.SourceFile(&#8220;tests.dll&#8221;).UsingCompressionLevel.Ten);<br />
Task.Run(Runners.Zip.Decompress.SourceFile(&#8220;tests.zip&#8221;));<br />
Task.Run(Runners.Executable.Path(&#8220;test.exe&#8221;));<br />
Task.Run(Runners.Debugger);<br />
Task.Run(Runners.Nunit.Assembly(&#8220;tests.dll&#8221;));<br />
Task.Run(Runners.MsTest.Assembly(&#8220;tests.dll&#8221;));</p>
<p>Let me know your thoughts or give me other options to make this simple and intuitive!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.haveyougotwoods.ca/2012/04/12/new-run-syntax-feedback/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
