﻿<?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>Just A Programmer</title>
	<atom:link href="http://www.justaprogrammer.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.justaprogrammer.net</link>
	<description>We're Just Programmers...</description>
	<lastBuildDate>Tue, 10 Jan 2012 03:59:18 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Using PowerShell to represent Base 26 as the uppercase English Alphabet</title>
		<link>http://www.justaprogrammer.net/2012/01/09/using-powershell-to-represent-base-26-as-the-uppercase-english-alphabet/</link>
		<comments>http://www.justaprogrammer.net/2012/01/09/using-powershell-to-represent-base-26-as-the-uppercase-english-alphabet/#comments</comments>
		<pubDate>Tue, 10 Jan 2012 03:59:18 +0000</pubDate>
		<dc:creator>Justin</dc:creator>
				<category><![CDATA[Just A Programmer]]></category>
		<category><![CDATA[Algorithims]]></category>
		<category><![CDATA[Math]]></category>
		<category><![CDATA[PowerShell]]></category>

		<guid isPermaLink="false">http://www.justaprogrammer.net/?p=1214</guid>
		<description><![CDATA[Today I was asked to do something that seemed simple, until I actually had to do it. A coworker had a database with two fields he wanted renamed in a specific way. For our example, lets call them ProductNumber and ProductName. He wanted ProductNumber to be sequential (1, 2, 3 . . .) and the [...]]]></description>
			<content:encoded><![CDATA[
<p>Today I was asked to do something that seemed simple, until I actually had to do it. A coworker had a database with two fields he wanted renamed in a specific way. For our example, lets call them ProductNumber and ProductName. He wanted ProductNumber to be sequential (1, 2, 3 . . .) and the ProductName fields to be called &#8220;Product A&#8221;, &#8220;Product B&#8221; . . . &#8220;Product Z&#8221;, &#8220;Product AA&#8221; etc. So this suddenly became a non-trivial problem if you had more than 26 rows, which of course I did.</p>
<p>So I rolled up my sleeve, got a fresh cup of coffee, and got to work. Populating ProductNumber was easy enough using a <a href="http://msdn.microsoft.com/en-us/library/ms190766.aspx">Common Table Expression (CTE)</a> with a <a href="http://msdn.microsoft.com/en-us/library/ms186734.aspx">ROW_NUMBER()</a>. Then I realized I could think of the English alphabet as symbols for a base 26 number system, with AA following Z and so on. The only problem was I couldn&#8217;t express that in a set based way for a clean T-SQL implementation. No problem, I&#8217;d just generate the T-SQL to make a giant mapping table in PowerShell!</p>
<p>I am ashamed to admit I had to look up the algorithim for converting from base 10 to another number. I was also surprised to discover that the first result google returned me was <a href="http://rachel5nj.tripod.com/NOTC/cb2.html">this tripod page</a>.</p>
<p>The algorithm is as follows.</p>
<ol>
<li>Start with an empty string which becomes the return value</li>
<li>While the value is greater than the base get the remainder of the value divided by the base. Convert that to its letter and prepend that to the return value</li>
<li>Repeat step 2 with the quotient of the value over the base.</li>
<li>When the quotient is less than the base, prepend that to the string instead.</li>
</ol>
<p>It seemed simple enough, but there were some headaches.</p>
<p>The first thing I discovered was that when you divide integers in PowerShell, you get a float as a result. Also casting it back to an int rounds instead of truncating the results. I was expecting the opposite in both cases, because that is how C# behaves. I ended up using the unwieldy combination of <a href="http://msdn.microsoft.com/en-us/library/e0b5f0xb.aspx">Math.Floor()</a> and a cast in the form <code>[int][math]::Floor($currVal / 26)</code> to resolve this. The MSDN technet has <a href="http://technet.microsoft.com/en-us/library/ee176879.aspx">an article</a> that recommends the more unwieldy <code>[Math]::floor([int] $currVal / [int] 26)</code>, but I <a href="https://gist.github.com/1586729">proved</a> that my terser method gives the same results.</p>
<p>Then I had problems with how to display powers of 26. The way it was supposed to work was that 1 = A, 24 = X, 25 = Y, 26 = Z and 27 = AA. However, depending on how I did it I ended up with 26 = AZ or 27 = BA. I could not account for this edge case, nor compensate for it with special conditions.</p>
<p>Then it dawned on me, A needed to be equal to zero not one. A base 10 system deals with the digits 0-9. Base 2 deals with 0 and 1. Base 16 deals with 0-F and F is 15. Once I rewrote my script to work that way, edge cases disappeared, and things just worked.</p>
<h3>The script</h3>
<pre><pre class="brush: powershell; title: ; notranslate">
	function Convert-ToLetters ([parameter(Mandatory=$true,ValueFromPipeline=$true)][int] $value)  {
		$currVal = $value;
		$returnVal = '';
		while ($currVal -ge 26) {
			$returnVal = [char](($currVal) % 26 + 65) + $returnVal;
			$currVal =  [int][math]::Floor($currVal / 26)
		}
		$returnVal = [char](($currVal) + 64) + $returnVal;

		return $returnVal
	}
</pre></pre>
<p>If its not clear how I generated upper case letters, the <a href="http://www.asciitable.com/">ASCII codes</a> for A through Z are 65 through 90, and casting an integer to a char converts it to its ASCII code. Ergo, the expression <code>[char]65</code> evaluates to &#8220;A&#8221;.</p>
<p>So now here&#8217;s the function in action:</p>
<pre><pre class="brush: powershell; title: ; notranslate">1 .. 100 | ForEach-Object {
	$_ | Convert-ToLetters
}</pre>
</pre>
<p>Happy Scripting!</p>

]]></content:encoded>
			<wfw:commentRss>http://www.justaprogrammer.net/2012/01/09/using-powershell-to-represent-base-26-as-the-uppercase-english-alphabet/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Making an RDP connection to a server you just rebooted with powershell</title>
		<link>http://www.justaprogrammer.net/2012/01/07/making-an-rdp-connection-to-a-server-you-just-rebooted-with-powershell/</link>
		<comments>http://www.justaprogrammer.net/2012/01/07/making-an-rdp-connection-to-a-server-you-just-rebooted-with-powershell/#comments</comments>
		<pubDate>Sun, 08 Jan 2012 01:35:50 +0000</pubDate>
		<dc:creator>Justin</dc:creator>
				<category><![CDATA[Just A Programmer]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Remote Desktop]]></category>
		<category><![CDATA[System Administration]]></category>

		<guid isPermaLink="false">http://www.justaprogrammer.net/?p=1194</guid>
		<description><![CDATA[It&#8217;s an all to familiar story. You  need to reboot a server, and then you need to start a remote desktop connection into it. So what do you do? You open up a command prompt, type ping -t &#60;HOSTNAME&#62; and wait until the server responds to pings. When that happens, you keep trying to connect via remote [...]]]></description>
			<content:encoded><![CDATA[
<p>It&#8217;s an all to familiar story. You  need to reboot a server, and then you need to start a remote desktop connection into it. So what do you do? You open up a command prompt, type <code>ping -t &lt;HOSTNAME&gt;</code> and wait until the server responds to pings. When that happens, you keep trying to connect via remote desktop, until it works. There&#8217;s got to be an easier way. You should write a PowerShell script to automate the process. However, its one of those things that not quite annoying enough to get you to actually take action and write the script. Luckily, thanks to the power of twitter, I reached a tipping point this week, and wrote the script. It all started out with some innocent whining:</p>
<style type="text/css">.ditto155068373691150337{background: #C0DEED url(http://a0.twimg.com/images/themes/theme1/bg.png) no-repeat;padding: 20px;} .ditto155068373691150337 a { color: #0084B4;} p.dittoTweet{background: #fff;padding: 10px 12px 10px 50px;margin: 0;min-height: 48px;color: #000;font-size: 18px !important;line-height: 22px;-moz-border-radius: 5px;-webkit-border-radius: 5px;} p.dittoTweet span.metadata {display: block;width: 100%;clear: both;margin-top: 8px;padding-top: 12px;height: 65px;} p.dittoTweet span.metadata span.author {line-height: 22px;color: #666;font-family: Arial, Helvetica, sans-serif;} .mainlink {font-family: Arial, Helvetica, sans-serif;font-size: 26px;color: #1F98C7;text-decoration: none;} .mainlink: hover {color: #1F98C7;text-decoration: underline;} .tweet {font-size: 24px;} p.dittoTweet span.metadata span.author img {float: left; margin: 0px 7px 0px 0px;} p.dittoTweet a:hover {text-decoration: underline;} p.dittoTweet span.timestamp {font-size: 12px;display: block;color: #999;} p.dittoTweet span.timestamp a {color: #999;text-decoration: none;}</style>
<div class="ditto155068373691150337">
<p class="dittoTweet"><span class="metadata"><span class="author"><a href="http://twitter.com/zippy1981"><img src="http://a3.twimg.com/profile_images/1672673440/Gravatar_normal.png"/></a><strong><a href="http://twitter.com/zippy1981" class="mainlink">@zippy1981</a></strong><br />Justin Dearing</span></span>You know what I need in an RDP client. I need an &#8220;&#8221;I just rebooted so ping it for me and autoreconnect&#8221;.<span class="timestamp"><a href="http://www.twitter.com"><img src="http://images.ientrymail.com/socialditto/twitter-bird.png" border="0" align="absmiddle" /></a> <a href="http://twitter.com/#!/zippy1981/status/155068373691150337" title="Thu Jan 05 23:29:15 +0000 2012">2 days ago</a>  via web&nbsp;&middot;&nbsp;powered by <a href="http://www.socialditto.com">@socialditto</a></span></p>
</div>
<p>Then <a href="https://twitter.com/#!/d0tk0m">d0tk0m</a> and <a href="https://twitter.com/#!/YanniRobel/status/155069020763201536">Yanni Robel</a> retweeted my whining. They say necessity is the mother of invention. In this case the commiseration off two tweeps was the father. So I spent a Saturday with PowerGUI, and came up with a script to solve the problem.</p>
<h3>Planing stage</h3>
<p>I wanted my script to automate what I already did. From the perspective a system administrator that wants to reboot a server and then remote desktop into it, the following happens.</p>
<ol>
<li>All the processes, including the remote desktop service (termsrv.dll) are shut down. When that happens the remote desktop port (default 3389) no longer has anything listening on it.</li>
<li>Eventually the network adapter is shutdown and it will stop responding to <a href="http://en.wikipedia.org/wiki/Ping">ICMP echo requests, or pings</a>.</li>
<li>The server will finish shutting down, the BIOS will <a href="http://en.wikipedia.org/wiki/Power-on_self-test">POST</a>, and Windows will begin booting</li>
<li>Eventually the network adapter will come up and start responding to pings.</li>
<li>The remote desktop service will start and bind to the remote desktop port.</li>
</ol>
<p>Therefore, I made my script to do the following.</p>
<ol>
<li>Ping the server until it answered five successive ping requests. Yes this might be naive and optimistic in many cases. However, it worked in my use case. I used the <a href="http://msdn.microsoft.com/en-us/library/7hzczzed.aspx">Send()</a> method of the .NET <a href="http://msdn.microsoft.com/en-us/library/system.net.networkinformation.ping.aspx">System.Net.NetworkInformation.Ping</a> class to do this.</li>
<li>Once I was sure the host was up, I&#8217;d try to connect to it on port 3389, or another port if I passed a different port as a parameter. To do this I used the <a href="http://msdn.microsoft.com/en-us/library/System.Net.Sockets.TcpClient.aspx">System.Net.Sockets.TcpClient</a> class.</li>
<li>After this it was simply a matter of passing the right parameters to the remote desktop client, <a href="http://technet.microsoft.com/en-us/library/cc753907(WS.10).aspx">mstsc.exe</a>. I initially attempted to use the simple <code>&#038; mstsc &lt;Arguments&gt;</code>. However, that didn&#8217;t work to well so I ended up resorting to <a href="http://technet.microsoft.com/en-us/library/dd347550.aspx">Invoke-Expression</a>.</li>
</ol>
<h3>The script</h3>
<p>Below is the current version of the script, hosted on <a href="http://poshcode.org">poshcode.org</a>. The current version is stored in <a href="https://bitly.com/mstsc-Ac">gist repository</a>. While you are free to post changes to poshcode.org (or anywhere), in accordance  with the license, I&#8217;d prefer if you notified me of any changes so that they may be placed in the gist git repo.</p>
<p><script type="text/javascript" src="http://PoshCode.org/embed/3154"></script></p>

]]></content:encoded>
			<wfw:commentRss>http://www.justaprogrammer.net/2012/01/07/making-an-rdp-connection-to-a-server-you-just-rebooted-with-powershell/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>What #SQLFamily means to me.</title>
		<link>http://www.justaprogrammer.net/2011/12/28/what-sqlfamily-means-to-me/</link>
		<comments>http://www.justaprogrammer.net/2011/12/28/what-sqlfamily-means-to-me/#comments</comments>
		<pubDate>Thu, 29 Dec 2011 02:25:02 +0000</pubDate>
		<dc:creator>Justin</dc:creator>
				<category><![CDATA[Just A Programmer]]></category>
		<category><![CDATA[#sqlfamily]]></category>

		<guid isPermaLink="false">http://www.justaprogrammer.net/?p=1183</guid>
		<description><![CDATA[Warning folks, this is a non-technical post. Recently, a post on the official SQL Server blog stated that for each of the first 400 &#8220;what #SQLFamily means to me&#8221; stories submitted to sqlfamilysubmission@live.com, $50 would be donated to The Pragmatic Works Foundation to train veterans in IT skills. I just submitted my entry, which I have reproduced [...]]]></description>
			<content:encoded><![CDATA[
<p>Warning folks, this is a non-technical post.</p>
<p>Recently, <a href="http://blogs.technet.com/b/dataplatforminsider/archive/2011/12/08/help-the-sqlfamily-give-back.aspx">a post</a> on <a href="http://blogs.technet.com/b/dataplatforminsider/">the official SQL Server blog</a> stated that for each of the first 400 &#8220;what #SQLFamily means to me&#8221; stories submitted to <a href="mailto:sqlfamilysubmission@live.com">sqlfamilysubmission@live.com</a>, $50 would be donated to <a href="http://pragmaticworks.com/foundation/">The Pragmatic Works Foundation</a> to train veterans in IT skills. I just submitted my entry, which I have reproduced below.</p>
<p>My name is Justin Dearing, and I have worked in various capacities in the IT industry since December 2002. This is my #SQLFamily story. it is a story of learning my manners and receiving forgiveness.</p>
<blockquote>
<div><a href="https://twitter.com/paulrandal">Paul Randal</a> and <a href="https://twitter.com/#!/KimberlyLTripp">Kimberly Tripp</a> recently decided to increase the community marketing of their <a href="http://sqlskills.com/">SQLSkills</a> consulting company. They offered to send anyone a SQLSkills sticker that sent them a mailing address. I decided to sign up for this. I was a bit surprised there was no automated form, and that I had to send this request in prose via email. <a href="http://sqlskills.us2.list-manage1.com/subscribe?u=729526cc5ec7737666e0a1893&amp;id=d509eaaebc">Note that there is now a web form for this.</a>.</div>
<div></div>
<div>Well I did not say please or thank you, or generally acknowledge that a fellow homo sapien would be receiving the request at the end. Well, a very unique and talented homo sapien that I respect very much (Paul Randal himself) did indeed read my response, and sent the following twitter message:</div>
<div><a href="https://twitter.com/#!/PaulRandal/status/57592320060686336"><em>Amazing number of people that sign up for our mailing list and ask for sticker without please or thank you at all. Internet = no manners <img src='http://www.justaprogrammer.net/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' /> </em></a></div>
<div>I hung my head in shame for about a week while fretting over what to do because I knew right away I was the offender. Eventually I decided to simply send an email to Paul saying I realized I was the one that offended him and apologizing. He accepted the apology and sent me the sticker. Like a functional family, when forgiveness was sought it was quickly given, the incident was forgotten, and I&#8217;d like to think I&#8217;ve been a little more polite and considerate both on and off the internet as a result.</div>
</blockquote>

]]></content:encoded>
			<wfw:commentRss>http://www.justaprogrammer.net/2011/12/28/what-sqlfamily-means-to-me/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>EZ-Pass Data Integrity and security fail</title>
		<link>http://www.justaprogrammer.net/2011/11/26/ez-pass-data-integrity-and-security-fail/</link>
		<comments>http://www.justaprogrammer.net/2011/11/26/ez-pass-data-integrity-and-security-fail/#comments</comments>
		<pubDate>Sun, 27 Nov 2011 00:39:14 +0000</pubDate>
		<dc:creator>Justin</dc:creator>
				<category><![CDATA[Just A Programmer]]></category>
		<category><![CDATA[EZ-Pass]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://www.justaprogrammer.net/?p=1163</guid>
		<description><![CDATA[On October 29th 2011, I entered an EZ-Pass lane of the Brooklyn Battery Tunnel toll plaza and, to make a long story short, learned my EZ-Pass was broken. On November 19th 2011, I went to the Newark, NJ EZ-Pass Customer Service Center to rectify the matter. I was given another external EZ-Pass tag, and told it would [...]]]></description>
			<content:encoded><![CDATA[
<p>On October 29th 2011, I entered an <a href="http://en.wikipedia.org/wiki/E-ZPass">EZ-Pass</a> lane of the <a href="http://www.mta.info/bandt/html/bbt.html">Brooklyn Battery Tunnel</a> toll plaza and, to make a long story short, learned my EZ-Pass was broken. On November 19th 2011, I went to the <a href="http://www.yelp.com/biz/nj-ez-pass-newark">Newark, NJ EZ-Pass Customer Service Center</a> to rectify the matter. I was given another external EZ-Pass tag, and told it would cost me $33 dollars. I was not asked for payment, and assumed it would come  out of my account. I went out, mounted the new EZ-Pass tag to my front licence plate (with the old screws, because the new screws were one way security screws) and went on my merry way (through several tollbooths). That&#8217;s when the real fun began.</p>
<p>My old EZ-Pass would not be detected by a toll lane at all. It had developed a crack, and I assume the circuitry malfunctioned. The new one on the other hand caused the toll booths to say  &#8221;toll unpaid call EZ-Pass.&#8221; I assumed at the time it would take a while for the tag to be associated with my account. This assumption was supported by the fact that he woman at the service center wrote the serial number of my tag on a <strong>paper form</strong>. This form incidently stated it was for accounting of the internal tags only. I assumed that the process of associating tags with accounts was not instantaneous.</p>
<p>Then November 24th came around, and I needed to travel to participate in not one, but two feasts of slaughtered turkeys for an American Holiday called Thanksgiving. My tag failed to work. Obviously something was amiss, and I took action on <a href="http://en.wikipedia.org/wiki/Personally_identifiable_information">Black Friday</a>. I logged into my account and only saw the old tag number. So I went to my car, got my new tag number off my tag, and called EZ-Pass. While I was waiting to talk to someone I made a horrible discovery.</p>
<p>So let&#8217;s backup here a little, because this is my second horrible EZ-Pass discovery. Before I got my new EZ-Pass tag, I only interacted with EZ-Pass via the EZ-Pass NJ website. To log into the site, you need either your account number or your tag number, and a pin. The pin is an all numeric password. I will come out and make the confession that at the time I made it, its was the same as my ATM pin. That is no longer my ATM pin, because this was years ago.</p>
<p>So I shared passwords across accounts, but that&#8217;s not a discovery. I always knew this. The discovery was this. When I was at the customer service center, I was asked for my pin to verify my account. I gave it to the woman, and she did not type it into her computer. She looked at her screen to make sure what I said matched what was displayed. So pins are stored unencrypted. Mind you, an EZ-Pass account contains a lot of <a href="http://en.wikipedia.org/wiki/Personally_identifiable_information">personally identifiable information (PII)</a>. In addition to credit card numbers and your address, it contains license plate numbers, and places you&#8217;ve been. With this discovery, it seems that a lot of low paid clerks, living in the same state as the tag holder can access this information with just a persons name. Remind me never to anger an EZ-Pass employee.</p>
<p>Ok so that&#8217;s terrible, but hardly worth writing a blog post about. I mean I&#8217;ve seen plenty of data security sins of that caliber, none of which have inspired a written tirade. However, something sent me over the top here.</p>
<p>So what sent me over the top you might ask? Well when I first logged in I used my old tag number, because that&#8217;s the number I know and use to log in to my account. However, while waiting on hold, I said to myself, &#8220;let me use the new tag number and my pin to log in.&#8221; I did this and I saw not my account,  but the account of a complete stranger. I explain the situation to the person on the phone and the outcome is I have to mail in both tags (at my own cost), and a new tag will be sent to me (at which point I will be charged $33). There is no record of my original visit to the EZ-Pass center. I have a feeling if they look hard enough in the other person&#8217;s account, they will find it. I&#8217;d like to know what transpired while the guy put me on hold.</p>
<p>I will likely have a lot of headaches to sort out once this is all said and done. I regret not writing down the name of the person whose account my second tag was assigned to, or the name of the clerk in Newark or phone operator I dealt with.  If there are any further developments, I&#8217;ll report them here.</p>

]]></content:encoded>
			<wfw:commentRss>http://www.justaprogrammer.net/2011/11/26/ez-pass-data-integrity-and-security-fail/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Editing elements with periods in the name in PowerShell</title>
		<link>http://www.justaprogrammer.net/2011/11/06/editing-elements-with-periods-in-the-name-in-powershell/</link>
		<comments>http://www.justaprogrammer.net/2011/11/06/editing-elements-with-periods-in-the-name-in-powershell/#comments</comments>
		<pubDate>Mon, 07 Nov 2011 01:59:18 +0000</pubDate>
		<dc:creator>Justin</dc:creator>
				<category><![CDATA[Just A Programmer]]></category>

		<guid isPermaLink="false">http://www.justaprogrammer.net/?p=1150</guid>
		<description><![CDATA[Recently, a coworker asked me about a problem he was having with a PowerShell script that edited an app.config file. It was a simple enough fix for an experienced PowerShell programmer, but worth sharing the solution for those not as experienced. For this article, I&#8217;ll use a very small example web.config that demonstrates the problem. [...]]]></description>
			<content:encoded><![CDATA[
<p>Recently, a coworker asked me about a problem he was having with a PowerShell script that edited an app.config file. It was a simple enough fix for an experienced PowerShell programmer, but worth sharing the solution for those not as experienced.</p>
<p>For this article, I&#8217;ll use a very small example web.config that demonstrates the problem.</p>
<pre><pre class="brush: xml; title: ; notranslate">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
&lt;configuration&gt;
  &lt;appSettings&gt;
    &lt;add key=&quot;verbose&quot; value=&quot;true&quot;/&gt;
  &lt;/appSettings&gt;
  &lt;system.web&gt;
    &lt;compilation debug=&quot;true&quot; /&gt;
  &lt;/system.web&gt;
&lt;/configuration&gt;</pre></pre>
<p>The script my coworker was using worked something like this:</p>
<pre><pre class="brush: powershell; title: ; notranslate">$scriptPath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptPath

$configFile = 1(Get-Content &quot;$($dir)\web.config&quot;)
'Before: ' + $configFile.configuration.appSettings.OuterXml
$configFile.configuration.appSettings.add.value = 'false'
'After:  ' + $configFile.configuration.appSettings.OuterXml</pre></pre>
<p>Which of course prints out the following output:</p>
<pre><pre class="brush: plain; title: ; notranslate">Before: &lt;appSettings&gt;&lt;add key=&quot;verbose&quot; value=&quot;true&quot; /&gt;&lt;/appSettings&gt;
After:  &lt;appSettings&gt;&lt;add key=&quot;verbose&quot; value=&quot;false&quot; /&gt;&lt;/appSettings&gt;</pre></pre>
<p>The actual script saved the configuration file and didn&#8217;t print anything to the screen, but that&#8217;s irrelevant to the problem. The problem was he needed to edit the &lt;compilation/&gt; element inside the &lt;system.web&gt; element. He tried this first:</p>
<pre><pre class="brush: powershell; title: ; notranslate">$configFile = 1(Get-Content &quot;$($dir)\web.config&quot;)
'Before: ' + $configFile.configuration.system.web.OuterXml
$configFile.configuration.system.web.compilation.debug = 'false'
'After:  ' + $configFile.configuration.system.web.OuterXml</pre></pre>
<p>Which got him the following: </p>
<pre><pre class="brush: plain; title: ; notranslate">Before:
Property 'debug' cannot be found on this object; make sure it exists and is settable.
At C:\Users\zippy\Documents\deleteme\posh.config\editConfig.ps1:3 char:50
+ $configFile.configuration.system.web.compilation. &lt;&lt;&lt;&lt; debug = 'false'
    + CategoryInfo          : InvalidOperation: (debug:String) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFound

After:</pre></pre>
<p>The problem was the dot in <b>system.web</b>. PowerShell uses a period to separate an object from its members. However, all is not lost, because there is an alternate notation.</p>
<pre>'Before: ' + $configFile.configuration['system.web'].OuterXml
$configFile.configuration['system.web'].compilation.debug = 'false'
'After:  ' + $configFile.configuration['system.web'].OuterXml</pre>
<p>As you can see, we can reach into an xml element with indexer notation. Please note that you will get an error if you put a period before the opening square bracket, but a period is required after the closing square bracket. If you would like some more in depth knowledge of how indexers work, see <a href="http://msdn.microsoft.com/en-us/library/6x16t2tx.aspx">this MSDN page</a>. While that article is written from a C# perspective, the concepts can be applies to PowerShell as well.</p>

]]></content:encoded>
			<wfw:commentRss>http://www.justaprogrammer.net/2011/11/06/editing-elements-with-periods-in-the-name-in-powershell/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Continuous Integration with TFS2010, MSDeploy &amp; VSDBCMD</title>
		<link>http://www.justaprogrammer.net/2011/10/27/continuous-integration-with-tfs2010-msdeploy-vsdbcmd/</link>
		<comments>http://www.justaprogrammer.net/2011/10/27/continuous-integration-with-tfs2010-msdeploy-vsdbcmd/#comments</comments>
		<pubDate>Fri, 28 Oct 2011 01:18:03 +0000</pubDate>
		<dc:creator>Stanley</dc:creator>
				<category><![CDATA[Just A Programmer]]></category>
		<category><![CDATA[MS Web Deploy]]></category>
		<category><![CDATA[Team Foundation Server]]></category>
		<category><![CDATA[Visual Studio]]></category>
		<category><![CDATA[VSDBCMD]]></category>

		<guid isPermaLink="false">http://www.justaprogrammer.net/?p=965</guid>
		<description><![CDATA[After I created an account at Cytanium, I quickly discovered the glory of One-Click Publish. After setting up my source control in TFS. All I could think of, was getting TFS to do the same thing for me, but even I knew that wouldn&#8217;t be enough. I wanted TFS to deploy my database changes as [...]]]></description>
			<content:encoded><![CDATA[
<p>After I created an account at <a href="http://www.cytanium.com/" title="Cytanium" target="_blank">Cytanium</a>, I quickly discovered the glory of One-Click Publish. After setting up my source control in TFS. All I could think of, was getting TFS to do the same thing for me, but even I knew that wouldn&#8217;t be enough. I wanted TFS to deploy my database changes as well. Well, there is that Schema Compare utility in Visual Studio, I know it can figure out and deploy changes to a database. I figured if Visual Studio can do all of these things, I should be able to as well&#8230; shouldn&#8217;t I?</p>
<h4>Custom Build Process Templates</h4>
<p>Very soon after you start to ask these kinds of questions, you find yourself looking at TFS Build Process Templates. The templates are designed in Windows Workflow and thanks to a few good blogs out there this is a rather approachable topic. Most of my starting information came from this blog sequence: <a href="http://www.ewaldhofman.nl/post/2010/04/20/Customize-Team-Build-2010-e28093-Part-1-Introduction.aspx" title="Ewald Hofman's - Customize Team Build 2010" target="_blank">Ewald Hofman&#8217;s &#8211; Customize Team Build 2010</a>.</p>
<p>Before you start, save yourself the pain, take Ewald&#8217;s advice and <a title="Customize Team Build 2010 – Part 11: Speed up opening my build process template" href="http://www.ewaldhofman.nl/post/2010/10/01/Customize-Team-Build-2010-e28093-Part-11-Speed-up-opening-my-build-process-template.aspx" target="_blank">add the Team Foundation Build Activities to your Toolbox</a>. This <strong>will</strong> shave 15 seconds off the time to open every template.</p>
<h5>Exposing Arguments and Providing Metadata</h5>
<p>More lessons from Ewald on <a href="http://www.ewaldhofman.nl/post/2010/04/27/Customize-Team-Build-2010-e28093-Part-2-Add-arguments-and-variables.aspx" title="Add arguments and variables" target="_blank">adding arguments</a> and <a href="http://www.ewaldhofman.nl/post/2010/04/28/Customize-Team-Build-2010-e28093-Part-3-Use-more-complex-arguments.aspx" title="Use more complex arguments" target="_blank">adding more complex arguments</a>. We will use them and see how the values are supplied a bit later on.</p>
<ul>
<li>Continuous Integration Database Deployment
<ul>
<li><strong>ciVSDBCMDConnectionString</strong>: &#8220;Database Connection String&#8221;</li>
<li><strong>ciVSDBCMDManifestFile</strong>: &#8220;Database Manifest File&#8221;</li>
<li><strong>ciVSDBCMDTargetDatabase</strong>: &#8220;Target Database&#8221;</li>
</ul>
</li>
<li>Continuous Integration Website Deployment
<ul>
<li><strong>ciMSDeployWebProject</strong>: &#8220;Web Project&#8221;</li>
<li><strong>ciMSDeployUsername</strong>: &#8220;MSDeploy Credentials: Username&#8221;</li>
<li><strong>ciMSDeployPassword</strong>: &#8220;MSDeploy Credentials: Password&#8221;</li>
<li><strong>ciMSDeployWebService</strong>: &#8220;MSDeploy Web Service Url&#8221;</li>
<li><strong>ciMSDeployWebApplication</strong>: &#8220;Web Application Name&#8221;</li>
</ul>
</li>
</ul>
<p><a href="http://www.justaprogrammer.net/wp-content/uploads/2011/10/2011-10-26_2015.png"><img src="http://www.justaprogrammer.net/wp-content/uploads/2011/10/2011-10-26_2015-300x189.png" alt="" title="Build Process Template Variables" width="300" height="189" class="aligncenter size-medium wp-image-1055" /></a></p>
<h5>Customizing the Template</h5>
<p>Under your Team Project, go to the folder BuildProcessTemplates, and branch DefaultTemplate.xaml to ContinuousIntegrationTemplate.xaml.<br />
<a href="http://www.justaprogrammer.net/wp-content/uploads/2011/10/2011-10-25_2309.png"><img src="http://www.justaprogrammer.net/wp-content/uploads/2011/10/2011-10-25_2309.png" alt="" title="Branch Default Build Process Template" width="491" height="105" class="aligncenter size-full wp-image-1013" /></a></p>
<p>Open it up and and take a look around. It will help if you take a top down approach, Collapse All, using the controls in the top right. Locate the AgentScope Activity named &#8220;Run On Agent&#8221; and expand it. Now look for the open space after the &#8220;Try Compile, Test, and Associate Work Item&#8221; Sequence Activity; this is where we will start adding our custom functionality.</p>
<p>In this space add a If Activity and name it: &#8220;If Build and Test Succeeded&#8221;. In its condition we are going to add the following VB statement:</p>
<pre><pre class="brush: vb; title: ; notranslate">BuildDetail.CompilationStatus = BuildPhaseStatus.Succeeded And
    (BuildDetail.TestStatus = BuildPhaseStatus.Succeeded Or
        BuildDetail.TestStatus = BuildPhaseStatus.Unknown)</pre></pre>
<p>In the Then clause we drop a sequence named: &#8220;Deploy Database and Website&#8221;. Inside that sequence, go ahead and create a &#8220;Deploy Database&#8221; Sequence and a &#8220;Deploy Website&#8221; Sequence. In the else clause we can create a WriteBuildWarning with the message: &#8220;Deployment Skipped&#8221;. It should all look like this in the end&#8230;<br />
<a href="http://www.justaprogrammer.net/wp-content/uploads/2011/10/2011-10-26_1845.png"><img src="http://www.justaprogrammer.net/wp-content/uploads/2011/10/2011-10-26_1845.png" alt="" title="If Build and Test Succeeded" width="455" height="793" class="aligncenter size-full wp-image-1003" /></a></p>
<h5>Deploy Database</h5>
<p>A large part of my introduction to VSDBCMD (not to mention a large part of this idea) came from this <a href="http://msdn.microsoft.com/en-us/library/ff805001.aspx#checkintemplate" title="Visual Studio Walkthrough" target="_blank">Visual Studio Walkthrough</a> on the topic. If you are willing to work through the <a href="https://connect.microsoft.com/VisualStudio/feedback/details/575383/datadude-valid-sqlcmd-syntax-throws-error-at-build-time" target="_blank">various</a> <a href="http://connect.microsoft.com/VisualStudio/feedback/details/424035/visual-studio-2008-database-edition-gdr-finer-grain-control-of-user-schema-permission-scripting" target="_blank">issues</a> with using Database Deployment, it is worth it.</p>
<p>I happen to have Visual Studio installed on my TFS Server, if you dont, copy this application from your Visual Studio install to all your TFS Build Agents.</p>
<blockquote><p>C:\Program Files (x86)\Microsoft Visual Studio 10.0\VSTSDB\Deploy\</p></blockquote>
<p>We are going to use an InvokeProcess Activity to call VSDMCMD.exe with the following code for arguments property. The manifest file will contain the Database name and Connection String that was configured in the project, but chances are you are going to want to override this per environment.</p>
<pre><pre class="brush: vb; title: ; wrap-lines: true; notranslate">String.Format(&quot;/a:Deploy /dd+ /dsp:Sql&quot; _
     &amp; &quot; /manifest:&quot;&quot;{0}\{1}&quot;&quot;&quot; _
     &amp; &quot; /p:TargetDatabase=&quot;&quot;{2}&quot;&quot; /cs:&quot;&quot;{3}&quot;&quot;&quot;, _
     BuildDetail.DropLocation, ciVSDBCMDManifestFile, _
     ciVSDBCMDTargetDatabase, ciVSDBCMDConnectionString)</pre></pre>
<p>Be sure to properly name the InvokeProcess Activity, as well as provide WriteBuildMessage and WriteBuildError Actvities for the standard and error output.</p>
<p><a href="http://www.justaprogrammer.net/wp-content/uploads/2011/10/2011-10-26_2036.png"><img src="http://www.justaprogrammer.net/wp-content/uploads/2011/10/2011-10-26_2036.png" alt="" title="Deploy Database Sequence" width="268" height="336" class="aligncenter size-full wp-image-1064" /></a></p>
<h5>Deploy Website</h5>
<p>Deploying databases was actually a lot easier than I expected, which is fortunate, because deploying websites was a lot more challenging. </p>
<p>Lets add a few variables to the Deploy Website Sequence:</p>
<ul>
<li>Name: websitePublishDirectoryPath</li>
<li>Variable type: String</li>
<li>Default:
<pre><pre class="brush: vb; title: ; notranslate">String.Format(&quot;{0}\Website Deployment&quot;, BinariesDirectory)</pre></pre>
</li>
</ul>
<ul>
<li>Name: msDeployManifestFilePath</li>
<li>Variable type: String</li>
<li>Default:
<pre><pre class="brush: vb; title: ; notranslate">String.Format(&quot;{0}\{1}.manifest&quot;, websitePublishDirectoryPath, ciMSDeployWebProject)</pre></pre>
</li>
</ul>
</li>
<p>As we will continue by defining a Sequence named &#8220;Prepare Deployment&#8221;. This sequence is responsible for preparing a folder to publish. So we have to create the directory copy the output to it and perform any Web.config transformations. First lets declare a variable in this scope:</p>
<ul>
<li>Name: platformConfiguration</li>
<li>Variable type: Microsoft.TeamFoundation.Build.Workflow.Activities.PlatformConfiguration</li>
<li>Default:
<pre><pre class="brush: vb; title: ; notranslate">BuildSettings.PlatformConfigurations.First</pre></pre>
</li>
</ul>
<ul>
<li>Name: websiteSourceDirectory</li>
<li>Variable type: String</li>
<li>Default:
<pre><pre class="brush: vb; title: ; notranslate">String.Format(&quot;{0}\_PublishedWebsites\{1}&quot;, BinariesDirectory, ciMSDeployWebProject)</pre></pre>
</li>
</ul>
<ul>
<li>Name: websiteDestinationDirectory</li>
<li>Variable type: Microsoft.TeamFoundation.Build.Workflow.Activities.PlatformConfiguration</li>
<li>Default:
<pre><pre class="brush: vb; title: ; notranslate">String.Format(&quot;{0}\{1}&quot;, websitePublishDirectoryPath, ciMSDeployWebProject)</pre></pre>
</li>
</ul>
<p>One CreateDirectory Activity to create the folder named in variable `websitePublishDirectory`, one CopyDirectory Activity to copy `websiteSourceDirectory` to `websiteDestinationDirectory` and an additonal Sequence named &#8220;Find and Transform Web.config Files&#8221;</p>
<div id="attachment_1105" class="wp-caption alignright" style="width: 232px"><a href="http://www.justaprogrammer.net/wp-content/uploads/2011/10/Find-and-Transform-Web.config-Files-Full.jpg"><img src="http://www.justaprogrammer.net/wp-content/uploads/2011/10/Find-and-Transform-Web.config-Files-Mini.jpg" alt="" title="Find and Transform Web.config Files Mini" width="222" height="237" class="size-full wp-image-1105" /></a><p class="wp-caption-text">Click for the full workflow</p></div>
<h6>Yet Another Web.config Transform</h6>
<p>There seems to be <a href="http://msdn.microsoft.com/en-us/library/dd465318.aspx" title="How to: Transform Web.config When Deploying a Web Application Project" target="_blank">a lot</a> <a href="http://geekswithblogs.net/EltonStoneman/archive/2010/08/20/using-msbuild-4.0-web.config-transformation-to-generate-any-config-file.aspx" title="Using MSBuild 4.0 web.config Transformation to Generate Any Config File" target="_blank">of places</a> <a href="http://blog.foxxtrot.net/2011/01/using-vs2010-webconfig-transforms-without-vs2010-web-deployment.html" title="Using VS2010 Web.Config Transforms Without VS2010 Web Deployment" target="_blank">to find</a> <a href="http://rachelappel.com/deployment/keeping-configurations-consistent-with-web-config-transformations/" title="Keeping Configurations Consistent with web.config Transformations" target="_blank">good information</a> on the <a href="http://www.leniel.net/2011/06/replace-webconfig-appsetting-transform.html" title="Replacing Web.config settings with Transforms" target="_blank">Web.config</a><br />
<a href="http://www.hanselman.com/blog/SlowCheetahWebconfigTransformationSyntaxNowGeneralizedForAnyXMLConfigurationFile.aspx" title="SlowCheetah - Web.config Transformation Syntax now generalized for any XML configuration file " target="_blank">transformation</a> <a href="http://stackoverflow.com/search?q=web.config+transform+transformation" title="StackOverflow" target="_blank">topic</a>. So I&#8217;m not reinventing anything here. Generally I looked for web.config files and any matching transformation files. An MSBuild Activity is used to perform the transformation. Finally delete all transform files, and continue. It&#8217;s important, but rather boring&#8230; and this blog post is long enough already.</p>
<h6 style='clear:both;'>Web Deploy 2.0</h6>
<p>Hopefully you can have someone else configure Web Deploy 2.0 for you, but since you are reading this, I doubt that is the case. On learn.iis.net, I found the best set of tutorials to <a href="http://learn.iis.net/page.aspx/421/installing-web-deploy/" title="Installing Web Deploy" target="_blank">install</a>, <a href="http://learn.iis.net/page.aspx/516/configure-the-web-deployment-handler/" title="Configure the Web Deployment Handler" target="_blank">configure</a>, (and most importantly) <a href="http://blogs.iis.net/msdeploy/archive/2010/09/24/debugging-delegation-rules-for-web-deploy.aspx" title="Debugging Delegation Rules for Web Deploy" target="_blank">debug</a>. If you are having problems with the setup, don&#8217;t hesitate to enable tracing of failed requests. Once you are able to deploy with Visual Studio you are ready to continue&#8230; right? I mean, the MSDeploy command doesn&#8217;t seem too intimidating. After a day and change, I was ready to scream uncle. Until I found this <a href="http://stackoverflow.com/questions/6296669/msdeploy-how-can-i-access-the-command-generated-by-visual-studio" target="_blank">StackOverflow Question</a>, I was unable to figure out the arguments of the command that Visual Studio used to initiate the deployment.</p>
<p>First we have to generate a msdeploy manifest file. An InvokeMethod Activity to call `System.IO.File.WriteAllText` with the following expression</p>
<pre><pre class="brush: vb; title: ; notranslate">String.Format(&quot;&lt;?xml version=&quot;&quot;1.0&quot;&quot; encoding=&quot;&quot;utf-8&quot;&quot;?&gt;&quot; _
    &amp; &quot;&lt;sitemanifest&gt;&quot; _
        &amp; &quot;&lt;contentPath path=&quot;&quot;{0}\{1}&quot;&quot; /&gt;&quot; _
        &amp; &quot;&lt;setAcl path=&quot;&quot;{0}\{1}&quot;&quot; setAclResourceType=&quot;&quot;Directory&quot;&quot; /&gt;&quot; _
        &amp; &quot;&lt;setAcl path=&quot;&quot;{0}\{1}&quot;&quot; setAclUser=&quot;&quot;anonymousAuthenticationUser&quot;&quot; &quot; _
            &amp; &quot;setAclResourceType=&quot;&quot;Directory&quot;&quot; /&gt;&quot; _
    &amp;&quot;&lt;/sitemanifest&gt;&quot;, _
    websitePublishDirectoryPath, ciMSDeployWebProject)</pre></pre>
<p>Finally we can execute MSDeploy with an InvokeProcess Activity and the following arguments.</p>
<pre><pre class="brush: vb; title: ; notranslate">String.Format(&quot;-source:manifest='{0}'&quot; _
              &amp; &quot; -dest:auto,ComputerName='{1}?site={2}',UserName='{3}',Password='{4}',IncludeAcls='False',AuthType='Basic'&quot; _
              &amp; &quot; -verb:sync -disableLink:AppPoolExtension -disableLink:ContentExtension -disableLink:CertificateExtension&quot; _
              &amp; &quot; -setParam:kind='ProviderPath',scope='contentPath',match='^{5}\\{6}$',value='{2}'&quot; _
              &amp; &quot; -setParam:kind='ProviderPath',scope='setAcl',match='^{5}\\{6}$',value='{2}' -allowUntrusted&quot;, _
              msDeployManifestFilePath, ciMSDeployWebService, ciMSDeployWebApplicationName, _
              ciMSDeployUsername, ciMSDeployPassword, _
              websitePublishDirectoryPath.Replace(&quot;\&quot;, &quot;\\&quot;).Replace(&quot; &quot;, &quot;\ &quot;).Replace(&quot;.&quot;, &quot;\.&quot;), _
              ciMSDeployWebProject.Replace(&quot; &quot;, &quot;\ &quot;).Replace(&quot;.&quot;, &quot;\.&quot;))</pre></pre>
<h5>Configure and Queue the Build</h5>
<p>We can finally see the light at the end of the tunnel here. Since we provided the metadata for our arguments, we get a rather impressive display of customization.</p>
<p><a href="http://www.justaprogrammer.net/wp-content/uploads/2011/10/2011-10-27_2058.png"><img src="http://www.justaprogrammer.net/wp-content/uploads/2011/10/2011-10-27_2058-300x257.png" alt="" title="Build Process Parameters" width="300" height="257" class="aligncenter size-medium wp-image-1128" /></a></p>
<p>Queue up your build and hopefully you wont have to do too much debugging to get this to work for yourself.</p>
<h5>Conclusion</h5>
<p>After seeing this work, it was all worth it. Of course, this is all very custom, I have my xaml attached here as an example, but you will have to be prepared to work with it to make it work for you. Drop me a line, I&#8217;ll help you out if I can.</p>
<p><a href="http://www.mediafire.com/file/uvd8kcaa0pm8gro/ContinuousIntegrationTemplate.zip" title="ContinuousIntegrationTemplate.zip" target="_blank">ContinuousIntegrationTemplate.zip</a></p>

]]></content:encoded>
			<wfw:commentRss>http://www.justaprogrammer.net/2011/10/27/continuous-integration-with-tfs2010-msdeploy-vsdbcmd/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Synchronously Await an Async Workflow Using Observable.guard</title>
		<link>http://www.justaprogrammer.net/2011/10/15/synchronously-await-an-async-workflow-using-observable-guard/</link>
		<comments>http://www.justaprogrammer.net/2011/10/15/synchronously-await-an-async-workflow-using-observable-guard/#comments</comments>
		<pubDate>Sat, 15 Oct 2011 15:50:41 +0000</pubDate>
		<dc:creator>Stanley</dc:creator>
				<category><![CDATA[Just A Programmer]]></category>
		<category><![CDATA[Async Workflow]]></category>
		<category><![CDATA[f#]]></category>
		<category><![CDATA[fsharpx]]></category>

		<guid isPermaLink="false">http://www.justaprogrammer.net/?p=943</guid>
		<description><![CDATA[The other day, I couldn&#8217;t figure out how to Synchronously wait for an Async workflow to complete. I was pretty sure I needed to use Observable.guard, I just couldn&#8217;t wrap my head around how to use it. This morning I was on a mission to figure it out. This bit of code produces the most [...]]]></description>
			<content:encoded><![CDATA[
<p>The other day, I couldn&#8217;t figure out how to Synchronously wait for an Async workflow to complete. I was pretty sure I needed to use Observable.guard, I just couldn&#8217;t wrap my head around how to use it. This morning I was on a mission to figure it out.</p>
<pre>
<pre class="brush: fsharp; title: ; notranslate">
open System
open FSharp.Control

let event = new Event&lt;_&gt;()

let createObservableByExecutingAsync asyncToExecute =
    event.Publish
    |&gt; Observable.guard(fun _ -&gt; 

        let asyncOperation = async {
            asyncToExecute
            |&gt; Async.RunSynchronously

            event.Trigger(())
        }

        printfn &quot;Start Executing Async Operation&quot;

        Async.Start asyncOperation

        printfn &quot;End Executing Async Operation&quot;
    )

let someAsyncOperation = async {
        printfn &quot;Async Operation&quot;
    }

let asyncWorker = createObservableByExecutingAsync someAsyncOperation

printfn &quot;Start Waiting for Async Result&quot;

Async.AwaitObservable asyncWorker
|&gt; Async.RunSynchronously

printfn &quot;End Waiting for Async Result&quot;

Console.ReadLine()
|&gt; ignore
</pre>
</pre>
<p>This bit of code produces the most beautiful output of&#8230;</p>
<pre>
<pre class="brush: plain; title: ; notranslate">
Start Waiting for Async Result
Start Executing Async Operation
End Executing Async Operation
Async Operation
End Waiting for Async Result
</pre>
</pre>
<p>Figuring that out makes me feel better, but the bigger realization was that I didn&#8217;t need Observable.guard at all. I needed Async.AwaitObservable.</p>
<pre>
<pre class="brush: fsharp; title: ; notranslate">
open System
open FSharp.Control
open RateLimiting

type Messages =
    | Message of string

type Responses =
    | Response of string

let operationFunction (message: Messages) =
    match message with
    | Message(input) -&gt; Response(sprintf &quot;Response: %s&quot; input)

let agent =
    RateLimitedAgent(operationFunction, 4, 1000)

let event = new Event&lt;_&gt;()

let someAsyncOperation (response:Responses) = async {
        printfn &quot;Async Response&quot;
        event.Trigger(())
    }

agent.QueueItem({payload = Message(&quot;Awaited Payload&quot;) ; response = Some(someAsyncOperation)})
|&gt; Async.Start

printfn &quot;Start Waiting for Async Result&quot;

Async.AwaitObservable event.Publish
|&gt; Async.RunSynchronously

printfn &quot;End Waiting for Async Result&quot;

Console.ReadLine()
|&gt; ignore
</pre>
</pre>
<pre>
<pre class="brush: plain; title: ; notranslate">
Start Waiting for Async Result
Async Response
End Waiting for Async Result
</pre>
</pre>
<p>I love watching this stuff work.</p>
<p><a href="http://fssnip.net/8s" title="Async Wait Operation" target="_blank">Async Wait Operation</a></p>

]]></content:encoded>
			<wfw:commentRss>http://www.justaprogrammer.net/2011/10/15/synchronously-await-an-async-workflow-using-observable-guard/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Rate Limiting a Function with Async Workflows</title>
		<link>http://www.justaprogrammer.net/2011/10/14/rate-limiting-a-function-with-async-workflows/</link>
		<comments>http://www.justaprogrammer.net/2011/10/14/rate-limiting-a-function-with-async-workflows/#comments</comments>
		<pubDate>Fri, 14 Oct 2011 05:28:05 +0000</pubDate>
		<dc:creator>Stanley</dc:creator>
				<category><![CDATA[Just A Programmer]]></category>
		<category><![CDATA[Async Workflow]]></category>
		<category><![CDATA[f#]]></category>
		<category><![CDATA[fsharpx]]></category>

		<guid isPermaLink="false">http://www.justaprogrammer.net/?p=905</guid>
		<description><![CDATA[So I am trying to deal with an API that says I cannot make more than 4 requests per second. This is a really good use for F# since it has such great support for Asynchronous Workflows. I took a little inspiration from this post by Luca Bolognese. RateLimitedAgent Messages are passed in through a [...]]]></description>
			<content:encoded><![CDATA[
<p>So I am trying to deal with an API that says I cannot make more than 4 requests per second. This is a really good use for F# since it has such great support for Asynchronous Workflows. I took a little inspiration from this <a href="http://blogs.msdn.com/b/lucabol/archive/2010/02/12/a-simpler-f-mailboxprocessor.aspx" title="post" target="_blank">post</a> by Luca Bolognese.</p>
<pre>
<pre class="brush: fsharp; title: ; notranslate">
module RateLimiting

open System
open FSharp.Control

type RateLimitedMessage&lt;'a,'b&gt; = {payload: 'a ; response: ('b -&gt; Async&lt;unit&gt;) option}

type RateLimitedAgent&lt;'a,'b&gt;(
                                operation: 'a -&gt; 'b,
                                workerCount,
                                ?minExecutionTime: int,
                                ?errorHandler: Exception -&gt; 'a -&gt; Async&lt;unit&gt;
                            ) = class
    let blockingQueue = new BlockingQueueAgent&lt;RateLimitedMessage&lt;'a, 'b&gt;&gt;(workerCount)
    let semaphore = new System.Threading.Semaphore(workerCount, workerCount)

    let errorHandler = defaultArg errorHandler (fun _ _ -&gt; async{()})
    let minExecutionTime = defaultArg minExecutionTime -1

    let createWorker () =
        async {
            while true do
                semaphore.WaitOne()
                |&gt; ignore

                let! message = blockingQueue.AsyncGet()

                let messageProcessor =
                    async {
                            try
                                let response = operation message.payload
                                if message.response.IsSome then
                                    do! message.response.Value response
                            with
                            | ex -&gt;
                                errorHandler ex message.payload
                                |&gt; Async.Start
                        }

                seq {
                        yield messageProcessor
                        yield async {
                                do! Async.Sleep(minExecutionTime)
                                semaphore.Release()
                                    |&gt; ignore
                            }
                    }
                |&gt; Async.Parallel
                |&gt; Async.Ignore
                |&gt; Async.Start
            }

    do
        (fun _ -&gt; createWorker ())
        |&gt; Seq.init workerCount
        |&gt; Async.Parallel
        |&gt; Async.Ignore
        |&gt; Async.Start

    member x.QueueItem item =
        blockingQueue.AsyncAdd item
end
</pre>
</pre>
<p><a href="http://fssnip.net/8p" title="RateLimitedAgent" target="_blank">RateLimitedAgent</a></p>
<p>Messages are passed in through a BlockingQueueAgent from <a href="https://github.com/fsharp/fsharpx#readme" title="fsharp/fsharpx ReadMe" target="_blank">fsharpx&#8217;s Agent Library</a>. This allows users to choose whether or not they wait until messages are picked up for processing.</p>
<p>Here is an example of where we don&#8217;t wait at all. Although, we throw in some random exceptions for some fun.</p>
<pre>
<pre class="brush: fsharp; title: ; notranslate">
open System
open System.Diagnostics
open System.Threading
open FSharp.Control
open RateLimiting

let counterCreationData name ctype = new CounterCreationData(name, &quot;&quot;, ctype)

let counterCategoryName = &quot;Test Rate Limiter&quot;
let requestsProcessedPerSecondCounterItem = &quot;Requests Processed per second&quot;
let requestsQueuedPerSecondCounterItem = &quot;Requests Queued per second&quot;
let requestsQueuedCounterItem = &quot;Number of Items Queued&quot;

let performanceCounters = [|
        counterCreationData requestsProcessedPerSecondCounterItem PerformanceCounterType.RateOfCountsPerSecond32
        counterCreationData requestsQueuedPerSecondCounterItem PerformanceCounterType.RateOfCountsPerSecond32 ;
        counterCreationData requestsQueuedCounterItem PerformanceCounterType.NumberOfItems32
    |]

let removeCounters () = PerformanceCounterCategory.Delete(counterCategoryName)

let installCounters () =
    if PerformanceCounterCategory.Exists(counterCategoryName)
    then
        removeCounters ()

    PerformanceCounterCategory.Create(counterCategoryName, &quot;&quot;, PerformanceCounterCategoryType.SingleInstance, new CounterCreationDataCollection(performanceCounters))
    |&gt; ignore 

installCounters()

let createCounter name =
    let curProc = Process.GetCurrentProcess()
    new PerformanceCounter(counterCategoryName, name, false)

let requestProcessedSpeedCounter = createCounter requestsProcessedPerSecondCounterItem
let requestQueuedSpeedCounter = createCounter requestsQueuedPerSecondCounterItem

let queueCounter = createCounter requestsQueuedCounterItem
queueCounter.RawValue &lt;- 0L

let rndSeed = new Random()

type Messages =
    | Message of string

type Responses =
    | Response of string

let operationFunction (message: Messages) =
    match rndSeed.Next(10) with
    | x when x = 1 -&gt; failwith &quot;Error&quot;
    | _ -&gt;
        match message with
        | Message(input) -&gt; Response(sprintf &quot;Response: %s&quot; input)

let errorHandler (ex:Exception) message = async {
                                    requestProcessedSpeedCounter.Increment()
                                    |&gt; ignore

                                    queueCounter.Decrement()
                                    |&gt; ignore

                                    printfn &quot;Error&quot;
                                }

let agent =
    RateLimitedAgent(operationFunction, 4, 1000, errorHandler)

let responseFunction (someArg:Responses) = async{
    match someArg with
    | Response(response) -&gt;
        requestProcessedSpeedCounter.Increment()
        |&gt; ignore

        queueCounter.Decrement()
        |&gt; ignore

        printfn &quot;Responded: %s&quot; response
    }

let createDisposable name =
    let x = ref 1
    let rnd = new Random(rndSeed.Next())

    async {
        while true do
            agent.QueueItem({payload = Message(sprintf &quot;%s Request %i&quot; name (!x)) ; response = Some(responseFunction)})
            |&gt; Async.Start

            requestQueuedSpeedCounter.Increment()
            |&gt; ignore

            queueCounter.Increment()
            |&gt; ignore

            x := !x + 1

            do! Async.Sleep(550)
        }
    |&gt; Async.StartDisposable

let disposable1 = createDisposable &quot;Automatic 1&quot;
let disposable2 = createDisposable &quot;Automatic 2&quot;
let disposable3 = createDisposable &quot;Automatic 3&quot;
let disposable4 = createDisposable &quot;Automatic 4&quot;

Console.ReadLine()
|&gt; ignore

disposable1.Dispose()
disposable2.Dispose()
disposable3.Dispose()
disposable4.Dispose()

Console.ReadLine()
|&gt; ignore
</pre>
</pre>
<p><a href="http://content.screencast.com/users/StanleyGoldman/folders/Jing/media/21b5da5b-c7da-46d9-b135-d0d86f5b0c60/2011-10-14_0101.png"><img alt="" src="http://content.screencast.com/users/StanleyGoldman/folders/Jing/media/21b5da5b-c7da-46d9-b135-d0d86f5b0c60/2011-10-14_0101.png" title="Performance Monitor" class="aligncenter" width="430" height="425" /></a></p>
<p>So this is just about what I was looking for. I say just about because apparently I can get spikes where I go over limit. I have a strong belief this is a calculation error within Performance Monitor, but if we were really concerned about it, we could increase the worker cooldown time to 1.1s.</p>
<p>Because it&#8217;s fun, I&#8217;ve toyed some with the operation function to include a random delay, just to see the results.</p>
<pre>
<pre class="brush: fsharp; title: ; notranslate">
let operationFunction (message: Messages) =
    Thread.Sleep(rndSeed.Next(50,2500))
    match rndSeed.Next(10) with
    | x when x = 1 -&gt; failwith &quot;Error&quot;
    | _ -&gt;
        match message with
        | Message(input) -&gt; Response(sprintf &quot;Response: %s&quot; input)
</pre>
</pre>
<p><a href="http://content.screencast.com/users/StanleyGoldman/folders/Jing/media/64132db3-4b94-42dc-b84b-8ce44803341b/2011-10-14_0122.png"><img alt="" src="http://content.screencast.com/users/StanleyGoldman/folders/Jing/media/64132db3-4b94-42dc-b84b-8ce44803341b/2011-10-14_0122.png" title="Performance Monitor" class="aligncenter" width="430" height="425" /></a></p>
<p>Not too shabby..</p>
<p>Messages are bundled with an optional Async response. This allows the caller to provide an Async function to handle the response. If a user were interested, I&#8217;m pretty sure this is a more likely and useful target to block your Async Workflow for.</p>
<p>I&#8217;m sure I have to use Observable.guard like Thomas Petricek reffered to <a href="http://stackoverflow.com/questions/2649161/need-help-regarding-async-and-fsi#answer-2658530" title="Need help regarding Async and fsi" target="_blank">here</a> and <a href="http://stackoverflow.com/questions/3845110/observable-from-sequence-in-f#answer-3846621" title="Observable from Sequence in F#" target="_blank">here</a>.</p>
<p>So, create an Async Workflow, make it throw an event, add the message to the agent, then wait until the event is observed. Sounds simple enough, but I just can&#8217;t wrap my head around the mechanics of it at this point. I think I&#8217;m going to ask Thomas to help me out.</p>
<p><em><strong>Edited 10/17/2011</strong></em><br />
As per comments below</p>

]]></content:encoded>
			<wfw:commentRss>http://www.justaprogrammer.net/2011/10/14/rate-limiting-a-function-with-async-workflows/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>HashTables and New-Object -Property in Powershell</title>
		<link>http://www.justaprogrammer.net/2011/10/09/hashtables-and-new-object-property-in-powershell/</link>
		<comments>http://www.justaprogrammer.net/2011/10/09/hashtables-and-new-object-property-in-powershell/#comments</comments>
		<pubDate>Sun, 09 Oct 2011 20:42:55 +0000</pubDate>
		<dc:creator>Justin</dc:creator>
				<category><![CDATA[Just A Programmer]]></category>

		<guid isPermaLink="false">http://www.justaprogrammer.net/?p=864</guid>
		<description><![CDATA[There are many uses for the New-Object cmdlet. One of the more obvious uses is to transform a HashTable to a PSObject, perhaps to be pipelined into Format-Table. That is a convenient output formatting trick because you can then pass it to an Out-* or Format-* cmdlet. However, this trick has uses beyond formatting. For example, lets say you [...]]]></description>
			<content:encoded><![CDATA[
<p>There are many uses for the <a href="http://technet.microsoft.com/en-us/library/dd315334.aspx">New-Object cmdlet</a>. One of the more obvious uses is to transform a HashTable to a <a href="http://msdn.microsoft.com/en-us/library/system.management.automation.psobject(v=vs.85).aspx">PSObject</a>, perhaps to be pipelined into <a href="http://technet.microsoft.com/en-us/library/dd315255.aspx">Format-Table</a>.</p>
<pre><pre class="brush: powershell; title: ; notranslate">
New-Object PSObject -Property @{
    Name = &quot;Justin Dearing&quot;;
    Occupation = &quot;.NET Developer&quot;
}
</pre></pre>
<p>That is a convenient output formatting trick because you can then pass it to an Out-* or Format-* cmdlet. However, this trick has uses beyond formatting. For example, lets say you encapsulated web service calls into a PowerShell module via the <a href="http://technet.microsoft.com/en-us/library/dd315258.aspx">New-WebServiceProxy cmdlet</a>. If the parameters of the service methods of the object in question aren&#8217;t .NET primitives like strings and ints, you will need to figure out how your wrapper functions will take those parameters. Once again New-Object -Property and a HashTable. Consider this contrived example:</p>
<pre><pre class="brush: powershell; title: ; notranslate">$service = New-WebServiceProxy http://somedomain/webservices/something.svc?wsdl  -Namespace SomeService

function Get-Something ([HashTable]$SomethingRequest) {
    $request = New-Object SomeService.GetSomethingRequest -Property $SomethingRequest;
    return $service.GetSomethingRequest($SomethingRequest);
}</pre></pre>
<p>Note that you might want to use <a href="http://stackoverflow.com/questions/1767219/mutually-exclusive-powershell-parameters">Parameter Sets</a> to allow the user of your module to pass either a HashTable or the native request object in production.</p>
<p>One final note, you need to be aware that New-Object&#8217;s -Property parameter doesn&#8217;t handle nested HashTable&#8217;s. To Illustrate, consider the following PowerShell snippet:</p>
<pre><pre class="brush: powershell; title: ; notranslate">Add-Type -TypeDefinition @&quot;

public class Child {
	string name;
	public string Name {
		get { return name; }
		set { name = value; }
	}

	string email;
	public string Email {
		get { return email; }
		set { email = value; }
	}
}

public class Container {
	string name;
	public string Name {
		get { return name; }
		set { name = value; }
	}

	private Child myChild;
	public Child MyChild {
	 	get { return myChild; }
		set { myChild = value; }
	}
}
&quot;@

$container = New-Object Container -Property @{
	Name = 'My Container'
	MyChild = @{
		Name = 'Justin Dearing'
		Email = 'justin@dearing.com'
	}
}</pre></pre>
<p>This will return the following error:</p>
<pre><span style="color: #ff0000;">New-Object : The value supplied is not valid, or the property is read-only. Change the value, and then try again.</span>
<span style="color: #ff0000;">At C:\Users\jdearing\AppData\Local\Temp\e072a665-0543-4b85-9489-e843b9b932e5.ps1:32 char:24</span>
<span style="color: #ff0000;">+ $container = New-Object &lt;&lt;&lt;&lt; Container -Property @{</span>
<span style="color: #ff0000;"> + CategoryInfo : InvalidData: (:) [New-Object], Exception</span>
<span style="color: #ff0000;"> + FullyQualifiedErrorId : InvalidValue,Microsoft.PowerShell.Commands.NewObjectCommand</span></pre>
<p>The workaround for this is you have to call New-Object on $container.MyChild first as follows:</p>
<pre><pre class="brush: powershell; title: ; notranslate">Add-Type -TypeDefinition @&quot;

public class Child {
	string name;
	public string Name {
		get { return name; }
		set { name = value; }
	}

	string email;
	public string Email {
		get { return email; }
		set { email = value; }
	}
}

public class Container {
	string name;
	public string Name {
		get { return name; }
		set { name = value; }
	}

	private Child myChild;
	public Child MyChild {
	 	get { return myChild; }
		set { myChild = value; }
	}
}
&quot;@

$container = @{
	Name = 'My Container'
	MyChild = @{
		Name = 'Justin Dearing'
		Email = 'justin@dearing.com'
	}
}

$container.MyChild = New-Object Child -Property $container.MyChild;
$container = New-Object Container -Property $container;</pre></pre>
<p>Naturally, your code can get very verbose if your class is very complicated. You could probably write a script that reflects on the object type and handles nested HashTables. I&#8217;ll leave that as an exercise to the reader.</p>
<p>These three examples should help you gain a better understanding of the New-Object cmdlet and HashTable&#8217;s in PowerShell.</p>

]]></content:encoded>
			<wfw:commentRss>http://www.justaprogrammer.net/2011/10/09/hashtables-and-new-object-property-in-powershell/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>YUI&#8217;s CompressorTask with MSBuild and Visual Studio</title>
		<link>http://www.justaprogrammer.net/2011/09/24/yuis-compressortask-with-msbuild-and-visual-studio/</link>
		<comments>http://www.justaprogrammer.net/2011/09/24/yuis-compressortask-with-msbuild-and-visual-studio/#comments</comments>
		<pubDate>Sat, 24 Sep 2011 07:25:21 +0000</pubDate>
		<dc:creator>Stanley</dc:creator>
				<category><![CDATA[Just A Programmer]]></category>
		<category><![CDATA[MSBuild]]></category>
		<category><![CDATA[Visual Studio]]></category>
		<category><![CDATA[YUICompressor]]></category>

		<guid isPermaLink="false">http://www.justaprogrammer.net/?p=872</guid>
		<description><![CDATA[While trying to integrate YUI Compressor as a build task in my current project&#8230; http://yuicompressor.codeplex.com/documentation Post Build Event: I got the error: It seems that the spaces in the folder path are preventing me from enjoying YUI Compressor. Quite the same problem this person is having: MSDN Forums: Unable to correctly pass parameters to MS [...]]]></description>
			<content:encoded><![CDATA[
<p>While trying to integrate YUI Compressor as a build task in my current project&#8230;</p>
<p><a href="http://yuicompressor.codeplex.com/documentation" target="_blank">http://yuicompressor.codeplex.com/documentation</a></p>
<p>Post Build Event:</p>
<pre>
<pre class="brush: plain; title: ; notranslate">
$(MSBuildBinPath)\msbuild.exe &quot;$(SolutionDir)MinificationSettings.xml&quot; /property:SourceLocation=$(ProjectDir) /p:JavaScriptOutputFile=$(ProjectDir)ContentMin\Scripts\Example.min.js /p:CssOutputFile=$(ProjectDir)ContentMin\CSS\Site.min.css
</pre>
</pre>
<p>I got the error:</p>
<pre>
<pre class="brush: plain; title: ; notranslate">
MSBUILD : error MSB1008: Only one project can be specified.

C:\Windows\Microsoft.NET\Framework\v4.0.30319\msbuild.exe &quot;c:\users\spade\documents\visual studio 2010\Projects\ExampleYUICompressorTask\MinificationSettings.xml&quot;
    /p:SourceLocation=c:\users\spade\documents\visual studio 2010\Projects\ExampleYUICompressorTask\MVCExample\
    /p:JavaScriptOutputFile=c:\users\spade\documents\visual studio 2010\Projects\ExampleYUICompressorTask\MVCExample\ContentMin\Scripts\Example.min.js
    /p:CssOutputFile=c:\users\spade\documents\visual studio 2010\Projects\ExampleYUICompressorTask\MVCExample\ContentMin\CSS\Site.min.css
</pre>
</pre>
<p>It seems that the spaces in the folder path are preventing me from enjoying YUI Compressor. Quite the same problem this person is having: <a href="http://social.msdn.microsoft.com/Forums/en-AU/msbuild/thread/8f4418dc-92e0-4b9c-b6ff-a9503049c413" title="MSDN Forums: Unable to correctly pass parameters to MS build" target="_blank">MSDN Forums: Unable to correctly pass parameters to MS build</a>. Although I suspect he gave up a bit too early.</p>
<p>I tried adding quotes around the value of the parameters, you would think this is going to work, it doesn&#8217;t.</p>
<p>Looking for a way to replace the spaces, I came across <a href="http://blogs.msdn.com/b/msbuild/archive/2010/04/02/msbuild-property-functions.aspx" title="MS Build Property Functions" target="_blank">MS Build Property Functions</a>.</p>
<p>With Build Property Functions, it becomes possible to run the simple replace command in all the spots where I need to, my first guess was to replace space with &#8216;%20&#8242;. That had mixed results, so I was left with choosing an arbitrary token for replacement.</p>
<p>Post Build Event:</p>
<pre>
<pre class="brush: plain; title: ; notranslate">
$(MSBuildBinPath)\msbuild.exe &quot;$(SolutionDir)MinificationSettings.xml&quot;
    /p:SourceLocation=$(ProjectDir.Replace(&quot; &quot;, &quot;[[REPLACESPACE]])
    /p:JavaScriptOutputFile=$(ProjectDir.Replace(&quot; &quot;, &quot;[[REPLACESPACE]])ContentMin\Scripts\Example.min.js
    /p:CssOutputFile=$(ProjectDir.Replace(&quot; &quot;, &quot;[[REPLACESPACE]])ContentMin\CSS\Site.min.css
</pre>
</pre>
<p>MinificationSettings.Xml:</p>
<pre>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;Project xmlns=&quot;http://schemas.microsoft.com/developer/MsBuild/2003&quot;&gt;
  &lt;UsingTask
      TaskName=&quot;CompressorTask&quot;
      AssemblyFile=&quot;packages\YUICompressor.NET-MsBuild-Task.1.6.0.2\lib\NET35\Yahoo.Yui.Compressor.MsBuildTask.dll&quot; /&gt;

  &lt;PropertyGroup&gt;
    &lt;CssOutputFile Condition=&quot; '$(CssOutputFile)'=='' &quot;&gt;SylesSheetFinal.css&lt;/CssOutputFile&gt;
    &lt;JavaScriptOutputFile Condition=&quot; '$(JavaScriptOutputFile)'=='' &quot;&gt;JavaScriptFinal.js&lt;/JavaScriptOutputFile&gt;
  &lt;/PropertyGroup&gt;

  &lt;PropertyGroup&gt;
    &lt;CssOutputFileFix&gt;$(CssOutputFile.Replace('[[REPLACESPACE]]', ' '))&lt;/CssOutputFileFix&gt;
    &lt;JavaScriptOutputFileFix&gt;$(JavaScriptOutputFile.Replace('[[REPLACESPACE]]', ' '))&lt;/JavaScriptOutputFileFix&gt;
  &lt;/PropertyGroup&gt;

  &lt;Target Name=&quot;MyTaskTarget&quot;&gt;
    &lt;ItemGroup&gt;

      &lt;JavaScriptFiles Include=&quot;$(SourceLocation.Replace('[[REPLACESPACE]]', ' '))Content\Scripts\Example.js&quot;/&gt;
	  &lt;CssFiles Include=&quot;$(SourceLocation.Replace('[[REPLACESPACE]]', ' '))Content\CSS\Site.css&quot;/&gt;

    &lt;/ItemGroup&gt;
    &lt;CompressorTask
        CssFiles=&quot;@(CssFiles)&quot;
        DeleteCssFiles=&quot;false&quot;
        CssOutputFile=&quot;$(CssOutputFileFix)&quot;
        CssCompressionType=&quot;YuiStockCompression&quot;
        JavaScriptFiles=&quot;@(JavaScriptFiles)&quot;
        ObfuscateJavaScript=&quot;True&quot;
        PreserveAllSemicolons=&quot;False&quot;
        DisableOptimizations=&quot;Nope&quot;
        EncodingType=&quot;Default&quot;
        DeleteJavaScriptFiles=&quot;false&quot;
        LineBreakPosition=&quot;-1&quot;
        JavaScriptOutputFile=&quot;$(JavaScriptOutputFileFix)&quot;
        LoggingType=&quot;ALittleBit&quot;
        ThreadCulture=&quot;en-au&quot;
        IsEvalIgnored=&quot;false&quot;
            /&gt;
  &lt;/Target&gt;
&lt;/Project&gt;
</pre>
</pre>
<p><a href="http://www.mediafire.com/file/ir5937a6r6ejpa6/ExampleYUICompressorTask.zip" title="Source: Example YUI CompressorTask" target="_blank">Source Code</a></p>

]]></content:encoded>
			<wfw:commentRss>http://www.justaprogrammer.net/2011/09/24/yuis-compressortask-with-msbuild-and-visual-studio/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

