﻿<?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 &#187; Justin</title>
	<atom:link href="http://www.justaprogrammer.net/author/justin/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[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fwww.justaprogrammer.net%252F2012%252F01%252F09%252Fusing-powershell-to-represent-base-26-as-the-uppercase-english-alphabet%252F%22%2C%20%22shorturl%22%3A%20%22http%3A%2F%2Fbit.ly%2Fxx06XH%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22Using%20PowerShell%20to%20represent%20Base%2026%20as%20the%20uppercase%20English%20Alphabet%22%20%7D);"></div>
<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[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fwww.justaprogrammer.net%252F2012%252F01%252F07%252Fmaking-an-rdp-connection-to-a-server-you-just-rebooted-with-powershell%252F%22%2C%20%22shorturl%22%3A%20%22http%3A%2F%2Fbit.ly%2FwGWonj%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22Making%20an%20RDP%20connection%20to%20a%20server%20you%20just%20rebooted%20with%20powershell%22%20%7D);"></div>
<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[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fwww.justaprogrammer.net%252F2011%252F12%252F28%252Fwhat-sqlfamily-means-to-me%252F%22%2C%20%22shorturl%22%3A%20%22http%3A%2F%2Fbit.ly%2FtjpsY7%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22What%20%23SQLFamily%20means%20to%20me.%22%20%7D);"></div>
<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[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fwww.justaprogrammer.net%252F2011%252F11%252F26%252Fez-pass-data-integrity-and-security-fail%252F%22%2C%20%22shorturl%22%3A%20%22http%3A%2F%2Fbit.ly%2FvddKyS%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22EZ-Pass%20Data%20Integrity%20and%20security%20fail%22%20%7D);"></div>
<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[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fwww.justaprogrammer.net%252F2011%252F11%252F06%252Fediting-elements-with-periods-in-the-name-in-powershell%252F%22%2C%20%22shorturl%22%3A%20%22http%3A%2F%2Fbit.ly%2Fvwrojj%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22Editing%20elements%20with%20periods%20in%20the%20name%20in%20PowerShell%22%20%7D);"></div>
<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>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[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fwww.justaprogrammer.net%252F2011%252F10%252F09%252Fhashtables-and-new-object-property-in-powershell%252F%22%2C%20%22shorturl%22%3A%20%22http%3A%2F%2Fbit.ly%2FpkzX9G%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22HashTables%20and%20New-Object%20-Property%20in%20Powershell%22%20%7D);"></div>
<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>Knowledge Quest: Reverse engineering unmanaged DLLs</title>
		<link>http://www.justaprogrammer.net/2011/08/28/knowledge-quest-reverse-engineering-unmanaged-dlls/</link>
		<comments>http://www.justaprogrammer.net/2011/08/28/knowledge-quest-reverse-engineering-unmanaged-dlls/#comments</comments>
		<pubDate>Mon, 29 Aug 2011 02:33:04 +0000</pubDate>
		<dc:creator>Justin</dc:creator>
				<category><![CDATA[Just A Programmer]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[dlls]]></category>
		<category><![CDATA[reverse engineering]]></category>

		<guid isPermaLink="false">http://www.justaprogrammer.net/?p=687</guid>
		<description><![CDATA[As a programmer person, I am always learning. I learn different thing in different ways, at different rates, and for different purposes. Usually, I write these blog posts about things I have learned recently. This post is about what I am currently learning. First, a little background. Around 2006 I was programming Windows CE devices, [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fwww.justaprogrammer.net%252F2011%252F08%252F28%252Fknowledge-quest-reverse-engineering-unmanaged-dlls%252F%22%2C%20%22shorturl%22%3A%20%22http%3A%2F%2Fbit.ly%2FoA4bQl%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22Knowledge%20Quest%3A%20Reverse%20engineering%20unmanaged%20DLLs%22%20%7D);"></div>
<p>As a <del>programmer</del> person, I am always learning. I learn different thing in different ways, at different rates, and for different purposes. Usually, I write these blog posts about things I have learned recently. This post is about what I am currently learning.</p>
<p>First, a little background. Around 2006 I was programming Windows CE devices, and syncing Pocket Access databases on them with a Microsoft Access database on a desktop via <a href="http://www.microsoft.com/download/en/details.aspx?id=15">ActiveSync</a>. Since I had no need for the Microsoft Access application, but I did need to be able to write SQL queries against the Access Database, I wrote <a href="http://plane-disaster.sf.net">PlaneDisaster.NET</a>.</p>
<p>Recently, I realized that PlaneDisaster.NET did not work on 64 bit machines. The simple fix was to compile it as a 32 bit executable. However, I wanted to make it work as a 64 bit executable. This became doubly important when I realized that I could not use <a href="http://msdn.microsoft.com/en-us/library/ms190312.aspx">OPENROWSET()</a> on a 64 bit instance of SQL server to connect to an Access database for the same reason that PlaneDisaster.NET would not work as a 64 bit process. Of course, doubly important was still not that important in the grand scheme of things.</p>
<p>Eventually, I did dust off PlaneDisaster.NET and got it to work as a 64 bit executable. Running PlaneDisaster.NET as a 64 bit process requires the 64 bit version of Microsoft Office 2010 or the <a href="http://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;id=13456">Microsoft Access Database Engine 2010 Redistributable</a> to be installed. However, even after doing this, I was unable to get two features of PlaneDisaster.NET to work., compacting and repairing Access databases.</p>
<p>PlaneDisaster.NET makes three calls to the unmanaged function <a href="SQLConfigDataSource()">SQLConfigDataSource()</a>. These three calls pass the commands CREATE_DB, COMPACT_DB, and REPAIR_DB respectively to the JetSQL Engine. The first one works fine with  the 64 bit driver. However,  I cannot get the second two to work. I cannot find any documentation on these calls except one <a href="http://support.microsoft.com/kb/126606">MSDN document last updated in 2001</a> which of course was written for the 32 bit driver.</p>
<p>So the question is, how do I plan on figuring out how to do this? My current plan involves using <a href="http://www.nirsoft.net/utils/dll_export_viewer.html">Nirsoft&#8217;s DLL Export Viewer</a> to get the addresses of the dll entry points of the unmanaged calls I am making. I will then use these addresses to step through assembly in the Visual Studio Debugger. I have only toyed with assembly. I don&#8217;t know if I will succeed in this task. However, I have already learned a lot, and I will continue to learn more. I might end up solving this problem via an alternative solution. I might simply learn enough to better articulate a question on StackOverflow that gets an answer. Or,  I might find that I am able to successfully step through the assembly and figure out this problem that way.</p>
<p>I will keep you all updated.</p>

]]></content:encoded>
			<wfw:commentRss>http://www.justaprogrammer.net/2011/08/28/knowledge-quest-reverse-engineering-unmanaged-dlls/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Creating an Access Database In Powershell without Access installed</title>
		<link>http://www.justaprogrammer.net/2011/08/25/creating-an-access-database-in-powershell-without-access-installed/</link>
		<comments>http://www.justaprogrammer.net/2011/08/25/creating-an-access-database-in-powershell-without-access-installed/#comments</comments>
		<pubDate>Thu, 25 Aug 2011 11:42:15 +0000</pubDate>
		<dc:creator>Justin</dc:creator>
				<category><![CDATA[Just A Programmer]]></category>

		<guid isPermaLink="false">http://www.justaprogrammer.net/?p=660</guid>
		<description><![CDATA[Recently I stumbled across a Hey, Scripting Guy! blog post titled &#8220;How Can I Use Windows PowerShell to Create an Office Access Database?&#8221; that demonstrated how to create a Microsoft Access database in powershell. The only problem with this script was it required Microsoft Access to be installed on the machine that it ran on. [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fwww.justaprogrammer.net%252F2011%252F08%252F25%252Fcreating-an-access-database-in-powershell-without-access-installed%252F%22%2C%20%22shorturl%22%3A%20%22http%3A%2F%2Fbit.ly%2Fovew9z%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22Creating%20an%20Access%20Database%20In%20Powershell%20without%20Access%20installed%22%20%7D);"></div>
<p>Recently I stumbled across a <a href="http://blogs.technet.com/b/heyscriptingguy/">Hey, Scripting Guy!</a> blog post titled &#8220;<a href="http://blogs.technet.com/b/heyscriptingguy/archive/2009/02/16/how-can-i-use-windows-powershell-to-create-an-office-access-database.aspx">How Can I Use Windows PowerShell to Create an Office Access Database?</a>&#8221; that demonstrated how to create a Microsoft Access database in powershell. The only problem with this script was it required Microsoft Access to be installed on the machine that it ran on. I knew this dependency on Access was unnecessary, because a few years ago I wrote an open source project for manipulating Microsoft Access and <a href="http://www.sqlite.org/">SQLite</a> databases called <a href="http://plane-disaster.sourceforge.net/">PlaneDisaster.NET</a>. That program did not require Microsoft Access to be installed and it allowed you to <a href="https://github.com/zippy1981/plane-disaster/blob/master/PlaneDisaster.Dba/JetSqlUtil.cs">create, compact and repair databases</a>. (I&#8217;ve discussed PlaneDisaster.NET <a href="http://www.justaprogrammer.net/2007/11/28/successful-versus-unsuccessful-open-source-projects/">previously</a> on this blog.)</p>
<p>So, as a matter of personal and professional pride I determined that I must write a PowerShell script that could create an Access Database without requiring Microsoft Access to be installed. After all, If you can do something in C#, you can do it in PowerShell. I did have one concern. I was making unmanaged Win32 API calls via <a href="http://pinvoke.net/">PInvoke</a>. However, I quickly learned <a href="http://www.leeholmes.com/blog/2009/01/19/powershell-pinvoke-walkthrough/">that&#8217;s not a problem at all</a>. My particular PInvoke calls involve enums, but you can <a href="http://blogs.msdn.com/b/powershell/archive/2008/06/03/v2-custom-enums.aspx">create enums in PowerShell</a>. However, I ended up replacing the enums with ints in the PInvoke declarations and no one complained since PowerShell is good at figuring that sort of thing out. The code I ended up with is:</p>
<pre lang="powershell">$signature = @'
[DllImport("ODBCCP32.DLL",CharSet=CharSet.Unicode, SetLastError=true)]
public static extern int SQLConfigDataSource
    (int hwndParent, int fRequest, string lpszDriver, string lpszAttributes);

[DllImport("odbccp32", CharSet=CharSet.Auto)]
public static extern int SQLInstallerError(int iError, ref int pfErrorCode, StringBuilder lpszErrorMsg, int cbErrorMsgMax, ref int pcbErrorMsg);
'@;

Add-Type -MemberDefinition $signature -Name Win32Utils -Namespace PInvoke -Using PInvoke,System.Text;</pre>
<p>This created two static functions I could call, <strong>[PInvoke.WIn32Utils]::SQLConfigDataSource()</strong> and <strong>[PInvoke.WIn32Utils]::SQLInstallerError()</strong>.</p>
<p>However, a new problem emerged. I could not get the script to run in a 64 bit PowerShell process. A quick google search informed me that the only way to get a 64 bit Access driver is through the <a href="http://www.microsoft.com/download/en/details.aspx?id=13255">Microsoft Access Database Engine 2010 Redistributable</a>. However, even after installing the 64 bit version of that executable, my script did not work unless I ran it through a 32 bit instance of PowerShell.</p>
<p>After a lot of searching and frustration I eventually had an epiphany. The provider name I was using to create the database was <strong>Microsoft Access Driver (*.mdb)</strong>. This provider name refered to ODBCJT32.DLL, which is only available as a 32 bit version. However, the driver that ships with the Access 2010 redistributable is called ACEODBC.DLL. This dll has a provider name of <strong>Microsoft Access Driver (*.mdb, *.accdb)</strong>.  The code for this is simple:</p>
<pre lang="powershell">[string] $driver = 'Microsoft Access Driver (*.mdb)';
if ([IntPtr]::Size -eq <img src='http://www.justaprogrammer.net/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' /> {
    $driver = 'Microsoft Access Driver (*.mdb, *.accdb)';
}</pre>
<p>Yes I&#8217;m using the size of a pointer to determine if I&#8217;m running in 32 or 64 bits.</p>
<p>The full script is below:</p>
<p><script type="text/javascript" src="http://PoshCode.org/embed/2928"></script></p>
<p>That version is hosted on poshcode.org to be more searchable. However, the authoritative one will remain as a <a href="https://gist.github.com/1166670">github gist</a>.</p>

]]></content:encoded>
			<wfw:commentRss>http://www.justaprogrammer.net/2011/08/25/creating-an-access-database-in-powershell-without-access-installed/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>The cost of fixing a computer, and Open Source Software</title>
		<link>http://www.justaprogrammer.net/2011/08/19/the-cost-of-fixing-a-computer-and-open-source-software/</link>
		<comments>http://www.justaprogrammer.net/2011/08/19/the-cost-of-fixing-a-computer-and-open-source-software/#comments</comments>
		<pubDate>Fri, 19 Aug 2011 11:04:30 +0000</pubDate>
		<dc:creator>Justin</dc:creator>
				<category><![CDATA[Just A Programmer]]></category>
		<category><![CDATA[computer repair]]></category>
		<category><![CDATA[editorial]]></category>
		<category><![CDATA[OSS]]></category>

		<guid isPermaLink="false">http://www.justaprogrammer.net/?p=637</guid>
		<description><![CDATA[Note: I started writing this a while ago, but just finished it. This is made obvious by the time stamps of the tweets I reference. Twitter is a great tool, but sometimes you need more than a 140 characters for a reply. This is one of those cases. It all started with a retweet by Karen [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fwww.justaprogrammer.net%252F2011%252F08%252F19%252Fthe-cost-of-fixing-a-computer-and-open-source-software%252F%22%2C%20%22shorturl%22%3A%20%22http%3A%2F%2Fbit.ly%2Fonpwmn%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22The%20cost%20of%20fixing%20a%20computer%2C%20and%20Open%20Source%20Software%22%20%7D);"></div>
<blockquote><p><strong>Note: </strong>I started writing this a while ago, but just finished it. This is made obvious by the time stamps of the tweets I reference.</p></blockquote>
<p>Twitter is a great tool, but sometimes you need more than a 140 characters for a reply. This is one of those cases.</p>
<p>It all started with <a href="https://twitter.com/#!/datachick/statuses/96368425919717376">a retweet</a> by Karen Lopez, a.k.a. <a href="http://www.twitter.com/datachick">@datachick</a>:</p>
<blockquote><p>“<a href="http://twitter.com/jlopez255" rel="nofollow" data-screen-name="jlopez255">@jlopez255</a>: Starting today -&#8221;Name your own price computer repair&#8221;, U name the price for my labor and I will fix your computer. Parts extra.</p></blockquote>
<p>Which lead to me putting forth the following propositions to Karen and Jennifer:</p>
<ol>
<li>It&#8217;s a problem that is is cheaper to buy a new computer than repair it for low end computers under 3 years old.</li>
<li>We need to make repairing computers cheaper, because many individuals cannot afford what professionals rightfully charge for their skill level.</li>
<li>OSS is better suited than closed course for bringing down the cost of computer repair.</li>
<li><del>You can petition the Lord with prayer.</del></li>
</ol>
<div>On point one I was preaching to the choir. On point number two I received no direct response. However, for number 3 Karen <a href="https://twitter.com/#!/datachick/statuses/96375023803174912">responded</a>:</div>
<blockquote>
<div><a href="http://twitter.com/zippy1981" rel="nofollow" data-screen-name="zippy1981">@zippy1981</a><a href="http://twitter.com/jlopez255" rel="nofollow" data-screen-name="jlopez255">@jlopez255</a> I have not had great ease of use with OSS. For every great 1, there are 10 that require lots of Dev / tech skills.</div>
</blockquote>
<div>I don&#8217;t refute this statement at face value, However, I do have the following commentary to offer backing up my third proposition.</div>
<div>First of all, lets limit the scope to the average personal machine owned by joe sixpack. Microsoft Office, or Open Office (or Libre Office) are power tools for these people. Other than an Office Suite, we are really talking about the web browser, and maybe the email client. For these users, a default Ubuntu install is more than enough. Most of their stuff is done on the web. Open/Libre Office are a little lacking in UX and features, but google docs makes up for the UX. Also, most of these users don&#8217;t want or need the missing features. In terms of web browsers and a window manager, the web browsers are exactly the same (yes I trained both my parents to use firefox), and the Ubuntu GUI is on par Windows 7 in terms of polish, with some interesting innovations such as how it handles full screen windows. Also, for netbooks, Ubuntu has a special install disc that tweaks the UI for the small screen.</div>
<div>Secondly, with Ubuntu, Linux is truly for end users. Rarely does something not work. When it fails to work, you might have to bust out the command line, but the procedures are no more complicated than what one would have to do on windows. Quite frankly, if you want a *nix OS that requires you to do a lot manually, try a BSD or Solaris.</div>
<div>Third, my point was OSS is better suited for reimaging hard drives cheaply than windows. Because OSS is free as in beer for all practical purposes, there are no licensing restrictions to enforce. Therefore, there are no restrictions on creative ways of deploying Linux automatically. <a href="http://en.wikipedia.org/wiki/Windows_Deployment_Services">Windows Deployment Services (WDS)</a> and its predecessor <a href="http://en.wikipedia.org/wiki/Remote_Installation_Services">Remote Installation Services (RIS)</a> are expensive, and designed for enterprise deployment. Microsoft could develop a version of these aimed at mom and pop geeksquad equivalents. If such a program allowed you to entered license keys for windows, office, etc and it install fully patched versions of the licensed software, plus whatever third party stuff they wanted to add (and their was a gallery where you could pick third party free and paid software to install), that might compete with what can be achieved when your software is free as in freedom and beer. However, I honestly don&#8217;t see Microsoft doing this until someone does this with Linux first.</div>
<div>So my point was that OSS has better potential for automating PC repair compared to Windows. You can simplify the process with OSS which will allow less skilled people to perform PC repaired. These less skilled people will command lower fees.</div>

]]></content:encoded>
			<wfw:commentRss>http://www.justaprogrammer.net/2011/08/19/the-cost-of-fixing-a-computer-and-open-source-software/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Yak Shaving Digest 2011-08-13</title>
		<link>http://www.justaprogrammer.net/2011/08/14/yak-shaving-digest-2011-08-13/</link>
		<comments>http://www.justaprogrammer.net/2011/08/14/yak-shaving-digest-2011-08-13/#comments</comments>
		<pubDate>Sun, 14 Aug 2011 13:23:03 +0000</pubDate>
		<dc:creator>Justin</dc:creator>
				<category><![CDATA[Just A Programmer]]></category>
		<category><![CDATA[.Net]]></category>
		<category><![CDATA[oauth]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[yak shaving]]></category>

		<guid isPermaLink="false">http://www.justaprogrammer.net/?p=641</guid>
		<description><![CDATA[This blog post is inspired by Brendan W McAdams (blog &#124; twitter) for introducing me to the term yak shaving, Aaron Bertrand (blog &#124; twitter) for his Connect Digests and Jennifer Lopez (not that one) (website &#124; twitter) for expressing  her desire to see the intersect of who she follows on twitter and who follows [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_blue" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fwww.justaprogrammer.net%252F2011%252F08%252F14%252Fyak-shaving-digest-2011-08-13%252F%22%2C%20%22shorturl%22%3A%20%22http%3A%2F%2Fbit.ly%2Fr1stIQ%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22Yak%20Shaving%20Digest%202011-08-13%22%20%7D);"></div>
<p>This blog post is inspired by Brendan W McAdams (<a href="http://ramblings.evilmonkeylabs.com/">blog</a> | <a href="http://twitter.com/rit">twitter</a>) for introducing me to the term <a href="http://en.wiktionary.org/wiki/yak_shaving">yak shaving</a>, Aaron Bertrand (<a href="http://sqlblog.com/blogs/aaron_bertrand/">blog</a> | <a href="https://twitter.com/aaronbertrand">twitter</a>) for his <a href="http://sqlblog.com/blogs/aaron_bertrand/archive/tags/Connect/default.aspx">Connect Digests</a> and Jennifer Lopez (not that one) (<a href="http://www.lopezgeeks.net/">website</a> | <a href="https://twitter.com/jlopez255">twitter</a>) for expressing  her desire to see <a href="https://twitter.com/#!/jlopez255/statuses/100224376200376320">the intersect of who she follows on twitter and who follows her</a>, which thereby made me want to do the same thing.</p>
<p>I was working on a C# console app the past week or so that would find the intersect of my following and followed by list on twitter. This Saturday was dedicated to getting it suitable for github, <a href="https://github.com/zippy1981/twitter.GetFriends/">which it now is</a>. However, I encountered several issues along the way. Because I had some blocking issues, I allowed myself to be distracted  by every minor issue  I encountered with the libraries and tools I was using for the task, for a brief period of time. The purpose of this was to report the issues, and if possible resolve them. This lead to bug reports, feature requests, and two patches. I listed them all here to add some context to all of them.</p>
<ul>
<li><strong>OAuth issues</strong>: This actually occurred earlier in the week. Twitter uses <a href="http://hueniverse.com/oauth/">OAuth v1</a>, which I discovered <a href="http://programmers.stackexchange.com/questions/99295/how-do-i-store-the-oauth-v1-consumer-key-and-secret-for-an-open-source-desktop-tw">isn&#8217;t really suited for desktop apps</a> because you have to share the secret that associates a request with your app with the world. That&#8217;s the equivalent of being required to share a pgp private key with the world. My workaround is to simple make users of my app generate their own app key (annoying, but something you&#8217;d probably be willing to do to get CLI access to twitter). If the app becomes popular I will request <a href="https://dev.twitter.com/docs/oauth/xauth">xAuth</a> access for my application.</li>
<li><strong>Sensitive info in config files and version control.</strong> This is related to the first issue. This app was not even stored in a local git repo despite me being a SCM nazi because I needed to figure out a strategy that would allow me to push an empty app.config to github. I store my consumer key/secret in the app.config, which I point out above I don&#8217;t want to share with anyone. I solved this problem by not checking the config file into version control and having a sanitized one with a different name in version control. Also, I used <a href="http://weblogs.asp.net/fmarguerie/archive/2007/04/26/using-configsource-to-split-configuration-files.aspx">configSource</a> so all my OAuth things would be in a <a href="https://github.com/zippy1981/twitter.GetFriends/blob/master/twitter.GetFriends/twitterizer.config.default">separate config file</a> from the main one.</li>
<li><strong>Being anal retentive about <a href="http://kbcsv.codeplex.com/">KBCsv</a> overloads.</strong> I am a huge fan of <a href="http://kentb.blogspot.com/">Kent Boogaart</a>&#8216;s CSV library. In my console app, I wanted to output the results as a CSV, so I could sort the data with excel.  However, along the way I got the crazy idea  to change some constructor parameters from <a href="http://kbcsv.codeplex.com/workitem/11185">string[] toIEnumerable&lt;string&gt;</a>. I discovered this could lead to ambiguous overloads . However, I did submit a fully working patch for IList&lt;string&gt; and WIP for the IEnumerable&lt;string&gt; with some commentary and asking if it made sense to complete the work. See patch 101185 and 101186 in the <a href="http://kbcsv.codeplex.com/SourceControl/list/patches">KBCsv patchlist</a> for the actual code. I&#8217;ll call this a partial victory.</li>
<li><strong>Filing a feature request with <a href="http://thehelpertrinity.codeplex.com/">HelperTrinity</a>.</strong> HelperTrinity is Ken Boogaart&#8217;s general helper library, used by KBCsv. While hacking on the KBCsv source I thought, &#8220;Hey! This could use some more helper and extension methods.&#8221; So I submitted a <a href="http://thehelpertrinity.codeplex.com/workitem/8607">feature request</a>.</li>
<li><strong>Finding  a bug in <a href="http://www.jetbrains.com/resharper/">ReSharper</a>.</strong> Digging through the KBCsv source code lead me to find an edge case that could lead to resharper reporting a false error. So I opened <a href="http://youtrack.jetbrains.net/issue/RSRP-274868">RSRP-274868</a>.</li>
<li><strong>Filed two codeplex feature requests.</strong> I went total meta and made two suggestions for codeplex itself. Both are the sort of simple things that I expect will be received by the codeples staff with either a &#8220;great idea&#8221; or &#8220;no thats so terrible for this reason&#8221;</li>
<ul>
<li><a title="Created work item: Add the codeplex favicon to the svnbridge servers" href="http://codeplex.codeplex.com/workitem/25935"><strong>Codeplex Workitem 25935</strong> Add the codeplex favicon to the svnbridge servers</a></li>
<li><a href="http://codeplex.codeplex.com/workitem/25936"><strong>Codeplex Workitem 25936</strong> Make the tfs and svn links in connection instructions clickable</a></li>
</ul>
<li><strong>MongoDB feature requests.</strong> I constantly find the <a href="http://bsonspec.org/">BSON</a> implementation in the <a href="http://www.mongodb.org/display/DOCS/CSharp+Language+Center">MongDB C# driver</a> useful outside of mongodb. It was useful here, but the time it saved me was eaten up filing two feature requests. I hope to implement patches for both of them.</li>
<ul>
<li><a href="https://jira.mongodb.org/browse/CSHARP-304"><strong>CSHARP-304</strong>: Add ToHashTable() extension method to MongoDB.Bson.dll</a></li>
<li><a href="https://jira.mongodb.org/browse/CSHARP-305"><strong>CSHARP-305</strong>: Separate MongoDB.Bson.dll into its own nuget package</a></li>
</ul>
<li><strong>Finally, one of my twitter calls broke.</strong> <a href="http://www.twitterizer.net/">Twitterizer</a> is the library I am using for twitter, and in the middle of debugging <a href="http://forums.twitterizer.net/viewtopic.php?f=9&amp;t=579">a call that always worked stopped working</a>. Looking elsewhere on the forums shows this is not a problem unique to me. This is the event that convinced me that my time would be better spent shaving the yak. In the end, this is still an open issue, but reverting to an older version of the library in a <a href="https://github.com/zippy1981/twitter.GetFriends/commits/twitterizer-reversion">different branch</a>, and excessive use of <a href="http://www.kernel.org/pub/software/scm/git/docs/git-cherry-pick.html">git cherry-pick</a> made it work.</li>
<li><strong>Epilogue:</strong> <del>The app works, but <a href="http://www.libreoffice.org/download/">LibreOffice</a> does not correctly import all rows in the spreadsheet. Since its all the import columns occur before the problems occur, and this can be cleaned in a text editor, I will investigate and file the bugs appropiatly with KBCsv and LibreOffice appropriately. Also, I need to get access to a machine with Excel installed. I expect Excel to be better at parsing CSV.</del>  It seems that I was specifying space as a delimiter in the CVS import dialog. Once I unchecked that the CSV imported properly.</li>
</ul>
<p>So in conclusion, my app works mostly, and between my bug reports and patches, I hope that the libraries and ReSharper will be improved. Also, by writing this blog post, I hope that having the big picture will be useful to myself as I polish of this twitter utility, and implement fixes for some of the bugs.</p>

]]></content:encoded>
			<wfw:commentRss>http://www.justaprogrammer.net/2011/08/14/yak-shaving-digest-2011-08-13/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

