<?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>Ryan's Tech Blog &#187; annoying</title>
	<atom:link href="http://ryepup.unwashedmeme.com/blog/category/annoying/feed/" rel="self" type="application/rss+xml" />
	<link>http://ryepup.unwashedmeme.com/blog</link>
	<description>mostly tech, mostly rants</description>
	<lastBuildDate>Wed, 04 Jan 2012 03:42:20 +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>Installing VS 2008 and SQL 2008 Express on Windows 7</title>
		<link>http://ryepup.unwashedmeme.com/blog/2010/03/30/installing-vs-2008-and-sql-2008-express-on-windows-7/</link>
		<comments>http://ryepup.unwashedmeme.com/blog/2010/03/30/installing-vs-2008-and-sql-2008-express-on-windows-7/#comments</comments>
		<pubDate>Tue, 30 Mar 2010 17:54:21 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[annoying]]></category>
		<category><![CDATA[mssql]]></category>
		<category><![CDATA[visual studio]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://ryepup.unwashedmeme.com/blog/?p=195</guid>
		<description><![CDATA[A new decade means time for a fresh windows install at work.  I ran into some trouble with windows 7, visual studio 2008, and SQL 2008 Express.  Here&#8217;s how I resolved them.  Contrary to most things I found on the web, I&#8217;m not using betas or release candidates. First off, installing SQL 2008 Express.  I [...]]]></description>
			<content:encoded><![CDATA[<p>A new decade means time for a fresh windows install at work.  I ran into some trouble with windows 7, visual studio 2008, and SQL 2008 Express.  Here&#8217;s how I resolved them.  Contrary to most things I found on the web, I&#8217;m not using betas or release candidates.</p>
<p>First off, installing SQL 2008 Express.  I only wanted the management tools, and this was a little hard to come by.  I downloaded various EXE files from MSDN, but none of them worked (they would error out, bring up an seemingly unrelated installer, or any other confusing behavior that may have led you here).  Here&#8217;s what worked for me:</p>
<ol>
<li>Be sure any previous installation attempts have been purged via Add / Remove Programs</li>
<li>Go to the &#8220;other install options&#8221; page for SQL express: <a href="http://www.microsoft.com/express/Database/default.aspx#Installation_Options">http://www.microsoft.com/express/Database/default.aspx#Installation_Options</a></li>
<li>Click the &#8220;Management Tools&#8221; install button (for me that&#8217;s: <a href="http://www.microsoft.com/web/gallery/install.aspx?appsxml=www.microsoft.com%2Fweb%2Fwebpi%2F2.0%2FWebProductList.xml%3Bwww.microsoft.com%2Fweb%2Fwebpi%2F2.0%2FWebProductList.xml&amp;appid=134%3B135">http://www.microsoft.com/web/gallery/install.aspx?appsxml=www.microsoft.com%2Fweb%2Fwebpi%2F2.0%2FWebProductList.xml%3Bwww.microsoft.com%2Fweb%2Fwebpi%2F2.0%2FWebProductList.xml&amp;appid=134%3B135</a>)</li>
<li>Install the &#8220;Microsoft Web Platform Installer&#8221; (MWPI) if it asks you to</li>
<li>Should be straightforward from here on</li>
</ol>
<p>The funny thing here is the MWPI seems to download an installer that looks a lot like the one at <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=08E52AC2-1D62-45F6-9A4A-4B76A8564A2B&amp;displaylang=en">Microsoft® SQL Server® 2008 Management Studio Express</a> that didn&#8217;t work for me.</p>
<p>Next up, Visual Studio 2008 (VS2008).  My company has an MSDN subscription, so we downloaded an ISO (named en_visual_studio_2008_professional_x86_x64wow_dvd_X14-26326.iso) and I used freeware <a href="http://www.magiciso.com/tutorials/miso-magicdisc-overview.htm?=mdisc_hlp106">MagicISO</a> to mount it, then ran &#8220;setup.exe&#8221;.  The install failed on the &#8220;Microsoft Visual Studio Web Authoring Component&#8221; (MVSWAC).  Here&#8217;s what worked for me:</p>
<ol>
<li>IF YOU WANT SQL2008, DO THAT FIRST</li>
<li>Be sure any previous installation attempts have been purged via Add /  Remove Programs</li>
<li>Download <a href="http://go.microsoft.com/fwlink/?LinkId=95934">WebDesignerCore.EXE</a> from microsoft</li>
<li>Run it</li>
<li>Install VS2008 from disc/iso as normal.</li>
</ol>
<p>Digging into the ISO using <a href="http://www.7-zip.org/">7zip</a>, the problem is /WCU/WebDesignerCore/WebDesignerCore.EXE is corrupt.  To get VS2008 to install cleanly, first we need to install MVSWAC, at which point the VS2008 installer will happily skip past the corrupt file.  I ran across several blog/forum posts with horror stories about VS2008 installing SQL2005, and needing to uninstall half the planet to get things working right.</p>
<p>As always, be sure to hit up windows update, and change your update settings so you get fixes for VS2008 and SQL2008.</p>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">
<h1>Microsoft® SQL Server® 2008 Management Studio Express</h1>
</div>
]]></content:encoded>
			<wfw:commentRss>http://ryepup.unwashedmeme.com/blog/2010/03/30/installing-vs-2008-and-sql-2008-express-on-windows-7/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Is programming all marshmallows and toothpicks, or is it just web apps?</title>
		<link>http://ryepup.unwashedmeme.com/blog/2010/02/18/is-programming-all-marshmallows-and-toothpicks-or-is-it-just-web-apps/</link>
		<comments>http://ryepup.unwashedmeme.com/blog/2010/02/18/is-programming-all-marshmallows-and-toothpicks-or-is-it-just-web-apps/#comments</comments>
		<pubDate>Fri, 19 Feb 2010 01:09:55 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[annoying]]></category>
		<category><![CDATA[rant]]></category>
		<category><![CDATA[whiny]]></category>

		<guid isPermaLink="false">http://ryepup.unwashedmeme.com/blog/?p=186</guid>
		<description><![CDATA[I&#8217;ve been doing some maintenance programming for a few days solid (rare for me to get to program that much), and I again find myself amazed that any software works at all.  I&#8217;ve only been programming seriously for about a decade (mostly web apps), but it feels like I&#8217;m building rickety crap on top of [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been doing some maintenance programming for a few days solid (rare for me to get to program that much), and I again find myself amazed that any software works at all.  I&#8217;ve only been programming seriously for about a decade (mostly web apps), but it feels like I&#8217;m building rickety crap on top of other people&#8217;s horrible hacks.</p>
<p>The bar for quality software seems so abysmally low.  When coding around some bizarre behavior I&#8217;m seeing out of the .NET framework, I know I&#8217;m introducing weird brittle bits.  It feels wrong, but I don&#8217;t see any other option.  And this is <strong>new code</strong>, written for the latest released version of a very popular system!  It seems like everyone else is doing the same thing in every programming environment I&#8217;ve seen.</p>
<p>My best guess is I&#8217;m working at maybe the 1000th layer of abstraction over the bare metal, and that sounds low.  That&#8217;s a lot of cruft, hacks, bugs, security holes, late-night fixes, bad compromises and coffee.</p>
<p>Maybe my sense of &#8220;clean code&#8221; is just OCD?  Sometimes I wonder if writing good code is just a waste of time.  Is shoddy copy/paste winning the evolutionary battle for the software base that will drive humanity for the next millennium?</p>
]]></content:encoded>
			<wfw:commentRss>http://ryepup.unwashedmeme.com/blog/2010/02/18/is-programming-all-marshmallows-and-toothpicks-or-is-it-just-web-apps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>shibboleth attribute &#8220;scope () not accepted&#8221; and &#8220;value () could not be validated by policy, rejecting it&#8221;</title>
		<link>http://ryepup.unwashedmeme.com/blog/2009/06/25/shibboleth-attribute-not-accepted-could-not-be-validated-by-policy/</link>
		<comments>http://ryepup.unwashedmeme.com/blog/2009/06/25/shibboleth-attribute-not-accepted-could-not-be-validated-by-policy/#comments</comments>
		<pubDate>Thu, 25 Jun 2009 17:20:44 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[annoying]]></category>
		<category><![CDATA[shibboleth]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://ryepup.unwashedmeme.com/blog/?p=116</guid>
		<description><![CDATA[I have a client who acts as a Shibboleth Service Provider (SP), and the corresponding Identity Provider (IdP) needed to update some of their information, so I had to spend a few hours debugging shibboleth again this morning. The punchline: in the metadata for an IdP, there are TWO places you need to specify the [...]]]></description>
			<content:encoded><![CDATA[<style type="text/css">
    <!--
      body {
        color: #000000;
        background-color: #ffffff;
      }
      .function-name {
        /* font-lock-function-name-face */
        color: #0000ff;
      }
      .sgml-namespace {
        /* sgml-namespace */
        color: #da70d6;
      }
      .string {
        /* font-lock-string-face */
        color: #bc8f8f;
      }
      .variable-name {
        /* font-lock-variable-name-face */
        color: #b8860b;
      }</p>
<p>      a {
        color: inherit;
        background-color: inherit;
        font: inherit;
        text-decoration: inherit;
      }
      a:hover {
        text-decoration: underline;
      }
    -->
    </style>
<p>I have a client who acts as a Shibboleth Service Provider (SP), and the corresponding Identity Provider (IdP) needed to update some of their information, so I had to spend a few hours debugging shibboleth again this morning.</p>
<p>The punchline: in the metadata for an IdP, there are TWO places you need to specify the scope of the IdP, once in the <code>&lt;IDPSSODescriptor&gt;</code> to cover authentication, and once later in the <code>&lt;AttributeAuthorityDescriptor&gt;</code> to cover any attributes.</p>
<p>Shibboleth is all about trust, and the lack thereof.  The SP and IdP share a few keys, and then each maintain their own configuration files specifying how much information to trust.  When a user logs in, they get bounced from SP-&gt;IdP to authenticate, then again from IdP -&gt; SP with an auth token.  From there, the SP can assume an authenticated user.  If the SP wants any more information about the user (say, a username), it can make SOAP calls to the IdP requesting more attributes.  The IdP checks it&#8217;s config files to see how many attributes to release to that particular SP, and sends back the attributes.  The SP doesn&#8217;t trust the IdP on it&#8217;s word, so the SP checks it&#8217;s config files to validate that it can accept these attributes from this IdP.  This is where I ran into a problem, getting an error like:</p>
<blockquote><p>attribute (username) scope (foo.bar.edu) not accepted</p></blockquote>
<p>This brings up another aspected of attributes, the <em>scope</em>.  An attribute&#8217;s scope seems somewhat akin to a namespace to me, it&#8217;s a way of grouping related attributes and prevent name conflicts between attributes.  In my case, my IdP was &#8220;bar.edu&#8221;, and my SP was configured to accept the username attribute from any site with any value (in my AAP.xml).  However, the IdP was returning the username scoped under a different domain, so the SP, being a paranoid creature, assumes the IdP is trying to falsify information and refused the attribute.  To convince the SP to accept the different scope, you have to change the metadata for the IdP, and specify that it is allowed to provide attributes in the new scope.  Unfortunately for me, there are 2 kinds of scopes you can change:</p>
<ol>
<li>Scope of the initial authentication</li>
<li>Scope of the attributes</li>
</ol>
<p>There are both children of <code>&lt;EntityDescriptor&gt;</code>.  This led to a frustrating morning of restarting IIS (because you need to restart everything under the sun for the configuration to get reloaded), and not seeing any change.  There are many ways to alter your attribute policy, and along to way to discovering the second place to specify scope I ran across another error message:</p>
<blockquote><p>attribute (username) value (my-user) could not be validated by policy, rejecting it</p></blockquote>
<p>This seemed to happen when my SP config tried to treat the username as an unscoped attribute.  You can&#8217;t just ignore the scope of an attribute if the IdP is sending one.</p>
<p>The end solution is to add another <code>&lt;shibmeta:Scope&gt;</code> specification to the attributes configuration section in the IdP&#8217;s metadata:</p>
<pre>
  &lt;<span class="function-name">AttributeAuthorityDescriptor</span> <span class="variable-name">protocolSupportEnumeration</span>=<span class="string">"urn:oasis:names:tc:SAML:1.1:protocol"</span>&gt;
    &lt;<span class="function-name">Extensions</span>&gt;
      &lt;<span class="sgml-namespace">shibmeta</span>:<span class="function-name">Scope</span> <span class="sgml-namespace">xmlns</span>:<span class="variable-name">shibmeta</span>=<span class="string">"urn:mace:shibboleth:metadata:1.0"</span>
                      <span class="variable-name">regexp</span>=<span class="string">"false"</span>&gt;bar.edu&lt;/<span class="sgml-namespace">shibmeta</span>:<span class="function-name">Scope</span>&gt;
      &lt;<span class="sgml-namespace">shibmeta</span>:<span class="function-name">Scope</span> <span class="sgml-namespace">xmlns</span>:<span class="variable-name">shibmeta</span>=<span class="string">"urn:mace:shibboleth:metadata:1.0"</span>
                      <span class="variable-name">regexp</span>=<span class="string">"false"</span>&gt;foo.bar.edu&lt;/<span class="sgml-namespace">shibmeta</span>:<span class="function-name">Scope</span>&gt;
    &lt;/<span class="function-name">Extensions</span>&gt;
    ...
</pre>
]]></content:encoded>
			<wfw:commentRss>http://ryepup.unwashedmeme.com/blog/2009/06/25/shibboleth-attribute-not-accepted-could-not-be-validated-by-policy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>brief list of things that make working in C# frustrating</title>
		<link>http://ryepup.unwashedmeme.com/blog/2008/02/13/brief-list-of-things-that-make-working-in-c-frustrating/</link>
		<comments>http://ryepup.unwashedmeme.com/blog/2008/02/13/brief-list-of-things-that-make-working-in-c-frustrating/#comments</comments>
		<pubDate>Wed, 13 Feb 2008 22:58:17 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[annoying]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://ryepup.unwashedmeme.com/blog/2008/02/13/brief-list-of-things-that-make-working-in-c-frustrating/</guid>
		<description><![CDATA[Problem: .NET framework classes don&#8217;t use interfaces enough Specific example: DataSource / DataBind()are separately defined on Repeater and GridView, (and Control, and many, many others), and my abstract base class doesn&#8217;t care which option an implementor chooses, it just wants to bind the data however the base control wants it. Possible Solutions: Define interface IDataBinding, [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Problem: </strong> .NET framework classes don&#8217;t use interfaces enough</p>
<p><strong>Specific example:</strong> <code>DataSource </code>/ <code>DataBind()</code>are separately defined on <code>Repeater </code> and <code>GridView</code>, (and <code>Control</code>, and many, many others), and my abstract base class doesn&#8217;t care which option an implementor chooses, it just wants to bind the data however the base control wants it.</p>
<p><strong>Possible Solutions:</strong></p>
<ul>
<li>Define interface <code>IDataBinding</code>, class <code>MyRepeater : Repeater, IDataBinding</code>, class <code>MyGridView : GridView, IDataBinding</code>, etc.</li>
<li><strike>Define interface <code>IDataBinding</code>, upgrade to C# 3, use extension methods to add <code>IDataBinding</code></strike> nope, extension methods can&#8217;t do this</li>
<li>Copy/paste identical code from my base class into concrete classes</li>
<li>Use reflection to set <code>DataSource </code>and call <code>DataBind()</code>, completely sidestepping the C# type system</li>
</ul>
<hr />
<strong>Problem: </strong>.NET framework classes not designed for extension: &#8220;<code>cannot override inherited member  'System.Collections.Generic.Dictionary&lt;X, Y&gt;.Add(X, Y)' because it is not marked virtual, abstract, or override</code>&#8220;</p>
<p><strong>Specific Example:</strong> Extending <code>System.Collections.Generic.Dictionary</code> to do some permit a list of values for one key, so adding the first item is stored as a single value, but adding a second value to the same key stores both values in a list.  Error message is: &#8220;<code>cannot override inherited member  'System.Collections.Generic.Dictionary&lt;X, Y&gt;.Add(X, Y)' because it is not marked virtual, abstract, or override</code>&#8220;</p>
<p><strong>Possible Solutions:</strong></p>
<ul>
<li>Define wrapper classes that encapsulates the framework class and implements all the base interfaces, with the vast majority of the code being straight delegation to the framework class:
<pre>
class MyDict : IDictionary, [other interfaces...] {
private Dictionary&lt;X,Y&gt; dict = new Dictionary&lt;X,Y&gt;;
public bool Contains(X key){ return dict.Contains(key);}
[... other simple wrappers...]
}</pre>
</li>
<li>Find a less appropriate framework class that is designed for extension, duplicate behavior of the proper framework class manually, eg: add run-time type checks for <code>Hashtable.Add(object, object) </code>in place of the letting the compiler handle the types as in <code>Dictionary&lt;X,Y&gt;.Add(X, Y)</code></li>
<li>Extend Dictionary&lt;X,Y&gt;, define a method <code>AddList(X,Y)</code>, and avoid using <code>IDictionary</code> in the rest of my code</li>
<li>Upgrade the C# 3, use extension to add function <code>AddList </code>to <code>IDictionary</code>, be sure to include those extensions on every consumer of <code>IDictionary</code></li>
</ul>
<hr />
<strong>Problem:</strong> .NET framwork classes not designed for extension: members declared private/ internal / protected internal</p>
<p><strong>Specific Example:</strong> Storing additional data in <code>ViewState </code>on 2 different controls that have different base classes.   One is a user control, another extends <code>RadioButtonList </code>to provide different UI for the same data</p>
<p><strong>Possible solutions:</strong></p>
<ul>
<li><strike>Upgrade to C# 3, use extension methods to add functions</strike> nope, extension methods can only see public members, <code>ViewState </code>is protected</li>
<li>Use reflection to set <code>ViewState</code></li>
<li>Copy/paste code into each control</li>
<li>Define  interface <code>IPublicViewstate</code>,  class <code>MyRadioButtonList : RadioButtonList, IPublicViewState</code>,  class<code> MyUserControl : UserControl, IPublicViewState</code>,  etc</li>
</ul>
<hr /> As Nathan said, I&#8217;m stuck between a rock and <code>IHardPlace</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://ryepup.unwashedmeme.com/blog/2008/02/13/brief-list-of-things-that-make-working-in-c-frustrating/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>SQL Server 2005 doesn&#8217;t like bitwise comparison of large numbers</title>
		<link>http://ryepup.unwashedmeme.com/blog/2008/01/29/sql-server-2005-doesnt-like-bitwise-comparison-of-large-numbers/</link>
		<comments>http://ryepup.unwashedmeme.com/blog/2008/01/29/sql-server-2005-doesnt-like-bitwise-comparison-of-large-numbers/#comments</comments>
		<pubDate>Tue, 29 Jan 2008 15:26:28 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[annoying]]></category>
		<category><![CDATA[mssql]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://ryepup.unwashedmeme.com/blog/2008/01/29/sql-server-2005-doesnt-like-bitwise-comparison-of-large-numbers/</guid>
		<description><![CDATA[An update trigger using COLUMNS_UPDATED() was failing, and I figured out the problem: Some simple SQL: SELECT CAST(0&#215;0200 as bigint), 0&#215;0200 &#124; 0 SELECT CAST(0&#215;02000 as bigint), 0&#215;02000 &#124; 0 SELECT CAST(0&#215;020000 as bigint), 0&#215;020000 &#124; 0 SELECT CAST(0&#215;0200000 as bigint), 0&#215;0200000 &#124; 0 SELECT CAST(0&#215;02000000 as bigint), 0&#215;02000000 &#124; 0 SELECT CAST(0&#215;020000000 as bigint), [...]]]></description>
			<content:encoded><![CDATA[<p>An update trigger using COLUMNS_UPDATED() was failing, and I figured out the problem:</p>
<p>Some simple SQL:</p>
<p>SELECT CAST(0&#215;0200 as bigint), 0&#215;0200 | 0<br />
SELECT CAST(0&#215;02000 as bigint), 0&#215;02000 | 0<br />
SELECT CAST(0&#215;020000 as bigint), 0&#215;020000 | 0<br />
SELECT CAST(0&#215;0200000 as bigint), 0&#215;0200000 | 0<br />
SELECT CAST(0&#215;02000000 as bigint), 0&#215;02000000 | 0<br />
SELECT CAST(0&#215;020000000 as bigint), 0&#215;020000000 | 0<br />
SELECT CAST(0&#215;0200000000 as bigint), 0&#215;0200000000 | 0<br />
I had &#8220;IF COLUMNS_UPDATED() | 0 &gt; 0&#8243; in my trigger, and on large values of COLUMNS_UPDATED(), bitwise ORing with zero equals zero.  Of course, &#8220;IF COLUMNS_UPDATED() | 0 &gt; 0&#8243; is a retarded way to say &#8220;IF COLUMNS_UPDATED() &gt; 0&#8243;, but whatever codepath that large number triggers wigs out there to.  Try these out:</p>
<p>SELECT 1 WHERE 0&#215;0200000000 &gt; 0<br />
SELECT 1 WHERE CAST(0&#215;0200000000 as bigint) &gt; 0</p>
<p>So, to fix my trigger, I have &#8220;IF CAST(COLUMNS_UPDATED() as bigint) &gt; 0&#8243;, which still seems a little retarded, but at least my trigger works.</p>
]]></content:encoded>
			<wfw:commentRss>http://ryepup.unwashedmeme.com/blog/2008/01/29/sql-server-2005-doesnt-like-bitwise-comparison-of-large-numbers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Quicken 2007 fails</title>
		<link>http://ryepup.unwashedmeme.com/blog/2008/01/15/quicken-2007-fails/</link>
		<comments>http://ryepup.unwashedmeme.com/blog/2008/01/15/quicken-2007-fails/#comments</comments>
		<pubDate>Wed, 16 Jan 2008 01:08:38 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[annoying]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://ryepup.unwashedmeme.com/blog/2008/01/15/quicken-2007-fails/</guid>
		<description><![CDATA[I use quicken to manage my finances, and find it overall does an excellent job, but every now and then it does something outrageous: Seriously?   You still can&#8217;t handle that?  I guess that means its time to take another stab at gnucash.]]></description>
			<content:encoded><![CDATA[<p>I use <a href="http://quicken.intuit.com/">quicken</a> to manage my finances, and find it overall does an excellent job, but every now and then it does something outrageous:</p>
<p><img src="http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2008/01/quicken-fails.png" alt="quicken-fails.png" /></p>
<p>Seriously?   You <em>still</em> can&#8217;t handle that?  I guess that means its time to take another stab at <a href="http://www.gnucash.org/">gnucash</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://ryepup.unwashedmeme.com/blog/2008/01/15/quicken-2007-fails/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>&#8220;manual or distributed transaction mode&#8221;, ruby, rails, mssql, ado</title>
		<link>http://ryepup.unwashedmeme.com/blog/2007/11/26/manual-or-distributed-transaction-mode-ruby-rails-mssql-ado/</link>
		<comments>http://ryepup.unwashedmeme.com/blog/2007/11/26/manual-or-distributed-transaction-mode-ruby-rails-mssql-ado/#comments</comments>
		<pubDate>Mon, 26 Nov 2007 21:31:26 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[annoying]]></category>
		<category><![CDATA[mssql]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://ryepup.unwashedmeme.com/blog/2007/11/26/manual-or-distributed-transaction-mode-ruby-rails-mssql-ado/</guid>
		<description><![CDATA[Spent too much damn time debugging the database layer in rails again today. This was the error: OLE error code:80004005 in Microsoft OLE DB Provider for SQL Server Cannot create new connection because in manual or distributed transaction mode. This was getting thrown after an insert, and the problem was very non-obvious.  I found one [...]]]></description>
			<content:encoded><![CDATA[<p> Spent too much damn time debugging the database layer in rails again today.  This was the error:</p>
<blockquote><p>OLE error code:80004005 in Microsoft OLE DB Provider for SQL Server<br />
Cannot create new connection because in manual or distributed transaction mode.</p></blockquote>
<p>This was getting thrown after an insert,  and the problem was very non-obvious.  I found one potential solution on <a href="http://occationallyuseful.blogspot.com/">Occasionally Useful Software</a>&#8216;s post about <a href="http://occationallyuseful.blogspot.com/2007/08/ruby-and-sql-server.html">Ruby and SQL Server</a>, but that seemed a little heavy-handed.</p>
<p>Somewhere in the bowels of ActiveRecord, dbi.rb, ADO.rb, and the SQL<ins></ins>NCLI driver, something expected one result-set per SQL command.  My insert was firing a database trigger, and so the ruby stack saw two result-sets, one saying &#8220;1 row affected&#8221; for the original insert, one saying &#8220;0 rows affected&#8221; for the trigger.  I&#8217;m still a little confused, as I thought those &#8220;rows affected&#8221; messages were separate from proper result-sets (the results from a SELECT, for example), but apparently those little buggers count enough.</p>
<p>Adding a &#8220;SET NOCOUNT ON&#8221; to the top of the trigger fixed it.</p>
]]></content:encoded>
			<wfw:commentRss>http://ryepup.unwashedmeme.com/blog/2007/11/26/manual-or-distributed-transaction-mode-ruby-rails-mssql-ado/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Debugging Shibboleth and &#8220;error:14094412:SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate&#8221; errors</title>
		<link>http://ryepup.unwashedmeme.com/blog/2007/07/13/debugging-shibboleth-and-error14094412ssl-routinesssl3_read_bytessslv3-alert-bad-certificate-errors/</link>
		<comments>http://ryepup.unwashedmeme.com/blog/2007/07/13/debugging-shibboleth-and-error14094412ssl-routinesssl3_read_bytessslv3-alert-bad-certificate-errors/#comments</comments>
		<pubDate>Fri, 13 Jul 2007 15:56:15 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[annoying]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[shibboleth]]></category>

		<guid isPermaLink="false">http://ryepup.unwashedmeme.com/blog/2007/07/13/debugging-shibboleth-and-error14094412ssl-routinesssl3_read_bytessslv3-alert-bad-certificate-errors/</guid>
		<description><![CDATA[Mucking about with Shibboleth again, and ran into some errors on the SP, specifically: 2007-07-10 19:49:42 DEBUG SAML.libcurl [79] sessionGet: SSL read: error:14094412:SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate, errno 0 This is the &#8220;catch-all&#8221; error message for Shibboleth OpenSSL Errors. After much research and testing, it was a problem with the IdP, their server was rejecting [...]]]></description>
			<content:encoded><![CDATA[<p>
Mucking about with <a href="http://shibboleth.internet2.edu/">Shibboleth</a> again, and ran into some errors on the SP, specifically:
</p>
<blockquote><p>
2007-07-10 19:49:42 DEBUG SAML.libcurl [79] sessionGet: SSL read: error:14094412:SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate, errno 0
</p></blockquote>
<p>
This is the &#8220;catch-all&#8221; error message for <a href="https://spaces.internet2.edu/display/SHIB/OpenSSLErrors">Shibboleth OpenSSL Errors</a>.  After much research and testing, it was a problem with the IdP, their server was rejecting my client certificate.
</p>
<h3>How it should work (I think)</h3>
<ol>
<li>User requests protected content on the SP</li>
<li>SP redirects to the IdP for authentication</li>
<li>IdP authenticates user, sends an SSL (with client certificae) SOAP request to the SP with some info, and then redirects the user back</li>
<li>SP validates SOAP request by comparing client certifacte with a white-list in the shibboleth metadata</li>
<li>SP sends an SSL (with client certificate) SOAP request to IdP to get more information about the user (in my case, a username so I can identify them in my database)</li>
<li>IdP validates SSL cert of SP with a white-list in their shibboleth metadata, responds with whatever information was requested</li>
<li>SP uses that information to serve or deny access to the user from step 1</li>
</ol>
<p>
SSL cert problems can happen at steps 4 and 6.  You can test these somewhat by using <a href="http://www.openssl.org/">openssl</a> on the command line.  Openssl has about a <a href="http://www.office-humour.co.uk/content/images/2007/07/6194.jpg">brazillion</a> options, but the one useful here is <a href="http://www.openssl.org/docs/apps/s_client.html#">s_client(1)</a>.</p>
<h3>Be sure the SP recognizes the IdP&#8217;s certs</h3>
<p>
  First up, check that the SP has the IdP&#8217;s certs in order:</p>
<blockquote><p>
openssl s_client -connect HOST:443 -showcerts
</p></blockquote>
<p>That will give you back the certificate chain:</p>
<blockquote><p>
Certificate chain<br />
 0 s: <em>SUBJECT FOR THE IDP</em><br />
   i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)05/CN=VeriSign Class 3 Secure Server CA<br />
&#8212;&#8211;BEGIN CERTIFICATE&#8212;&#8211;<br />
<em>ASCII JUMBLE</em><br />
&#8212;&#8211;END CERTIFICATE&#8212;&#8211;<br />
 1 s:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)05/CN=VeriSign Class 3 Secure Server CA<br />
   i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority<br />
&#8212;&#8211;BEGIN CERTIFICATE&#8212;&#8211;<br />
<em>ASCII JUMBLE</em><br />
&#8212;&#8211;END CERTIFICATE&#8212;&#8211;<br />
&#8212;<br />
Server certificate<br />
subject=<em>SUBJECT FOR THE IDP</em><br />
issuer=/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)05/CN=VeriSign Class 3 Secure Server CA<br />
&#8212;<br />
<em>some other stuff&#8230;</em>
</p></blockquote>
<p>The issuing certificate (in the example, cert 1) should be in your shibboleth metadata.  All you need is the top-most issuer, and shibboleth will look down the certificat chain until it finds a certificate it trusts, and all will be well.
</p>
<p>If that doesn&#8217;t solve it, then we see if the IdP has the SP cert straight.</p>
<h3>Be sure the IdP recognizes the SP&#8217;s certs</h3>
<p>
This is harder to debug from the SP&#8217;s side, but you can try make an SSL connection using the SP cert and key:</p>
<blockquote><p>
openssl s_client -connect HOST:443 -showcerts -cert SP.crt -key SP.key
</p></blockquote>
<p>If that connects, then you know the server isn&#8217;t rejecting you outright, but it&#8217;s possible that Apache config is rejecting you elsewhere.  The best way to check is to just ask your IdP if your config is still in their shibboleth white-list.
</p>
<p>If that doesn&#8217;t solve it, check the apache config.</p>
<h3>Be sure everyone&#8217;s apache config is OK</h3>
<p>
The possible failure here is that the certificate is being rejected before making it to shibboleth.  You don&#8217;t want to tell your whole server to accept any client certificate, you want to just pass those through to shibboleth and let shibboleth decide.  You&#8217;ll want to have <code>SSLVerifyClient optional_no_ca</code> in your Apache location blocks for shibboleth URLs.
</p>
<h3>Conclusion</h3>
<p>
Certificates are a good idea, but a pain in the ass.  The <a href="https://mail.internet2.edu/wws/arc/shibboleth-users">shibboleth-users</a> mailing list is a good source of information, and you can get prompt replies from there.  And next time I have this problem, I&#8217;ll know where to look for debugging tips.</p>
]]></content:encoded>
			<wfw:commentRss>http://ryepup.unwashedmeme.com/blog/2007/07/13/debugging-shibboleth-and-error14094412ssl-routinesssl3_read_bytessslv3-alert-bad-certificate-errors/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>EventHandlerList, key equality, and auto-boxing in C#</title>
		<link>http://ryepup.unwashedmeme.com/blog/2007/05/25/eventhandlerlist-key-equality-and-auto-boxing-in-c/</link>
		<comments>http://ryepup.unwashedmeme.com/blog/2007/05/25/eventhandlerlist-key-equality-and-auto-boxing-in-c/#comments</comments>
		<pubDate>Fri, 25 May 2007 17:29:27 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[annoying]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[code snippet]]></category>

		<guid isPermaLink="false">http://ryepup.unwashedmeme.com/blog/2007/05/25/eventhandlerlist-key-equality-and-auto-boxing-in-c/</guid>
		<description><![CDATA[I was recently implementing some custom events, and found a couple of good (if old) articles describing how to do this efficiently using EventHandlerList: Manage many events easily with EventHandlerList Objects with dense events, but sparse usage can benefit from custom event storage. Those articles go into why it's nicer to deal with one EventHandlerList [...]]]></description>
			<content:encoded><![CDATA[<p>I was recently implementing some custom events, and found a couple of good (if old) articles describing how to do this efficiently using <a href="http://msdn2.microsoft.com/en-us/library/system.componentmodel.eventhandlerlist(vs.80).aspx">EventHandlerList</a>:
<ul>
<li><a href="http://weblogs.asp.net/rosherove/archive/2004/12/31/344773.aspx">Manage many events easily with EventHandlerList</a></li>
<li><a href="http://weblogs.asp.net/justin_rogers/archive/2004/09/22/232834.aspx">Objects with dense events, but sparse usage can benefit from custom event storage.</a></li>
</ul>
<p>Those articles go into why it's nicer to deal with one EventHandlerList instead of many seperate EventHandlers, so read those for more information.  For the lazy, here's some code showing how you're supposed to use these things:</p>
<div class="igBar"><span id="lcsharp-5"><a href="#" onclick="javascript:showPlainTxt('csharp-5'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">C#:</span>
<div id="csharp-5">
<div class="csharp" style="font-family: monospace;">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> MyClass <span style="color: #000000;">&#123;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #0600FF;">private</span> EventHandlerList Events = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> EventHandlerList<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">event</span> EventHandler MyEvent <span style="color: #000000;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; add <span style="color: #000000;">&#123;</span> Events.<span style="color: #0000FF;">AddHandler</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;MyEvent&quot;</span>, value<span style="color: #000000;">&#41;</span>; <span style="color: #000000;">&#125;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; remove <span style="color: #000000;">&#123;</span> Events.<span style="color: #0000FF;">RemoveHandler</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;MyEvent&quot;</span>, value<span style="color: #000000;">&#41;</span>; <span style="color: #000000;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #000000;">&#125;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">event</span> EventHandler MyOtherEvent <span style="color: #000000;">&#123;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; add <span style="color: #000000;">&#123;</span> Events.<span style="color: #0000FF;">AddHandler</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;MyOtherEvent&quot;</span>, value<span style="color: #000000;">&#41;</span>; <span style="color: #000000;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; remove <span style="color: #000000;">&#123;</span> Events.<span style="color: #0000FF;">RemoveHandler</span><span style="color: #000000;">&#40;</span><span style="color: #808080;">&quot;MyOtherEvent&quot;</span>, value<span style="color: #000000;">&#41;</span>; <span style="color: #000000;">&#125;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #000000;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">void</span> OnMyEvent<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">object</span> sender, EventArgs e<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; EventHandler handler = <span style="color: #000000;">&#40;</span>EventHandler<span style="color: #000000;">&#41;</span> Events<span style="color: #000000;">&#91;</span><span style="color: #808080;">&quot;MyEvent&quot;</span><span style="color: #000000;">&#93;</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>handler != <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; handler<span style="color: #000000;">&#40;</span>sender, e<span style="color: #000000;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #000000;">&#125;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">void</span> OnMyOtherEvent<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">object</span> sender, EventArgs e<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; EventHandler handler = <span style="color: #000000;">&#40;</span>EventHandler<span style="color: #000000;">&#41;</span> Events<span style="color: #000000;">&#91;</span><span style="color: #808080;">&quot;MyOtherEvent&quot;</span><span style="color: #000000;">&#93;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>handler != <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; handler<span style="color: #000000;">&#40;</span>sender, e<span style="color: #000000;">&#41;</span>;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #000000;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #000000;">&#125;</span></div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Pretty straightforward stuff.   When you add an event handler to the list, you associate it with a key, and then when its time to trigger the events, you look for any handlers under the same key.  The other day I was putting together something similar, and ran into some unexpected behavior with the keys.  I had started by refactoring the magic strings into an enum:</p>
<div class="igBar"><span id="lcsharp-6"><a href="#" onclick="javascript:showPlainTxt('csharp-6'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">C#:</span>
<div id="csharp-6">
<div class="csharp" style="font-family: monospace;">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #0600FF;">protected</span> <span style="color: #FF0000;">enum</span> MyEvents <span style="color: #000000;">&#123;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; MyEvent,</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; MyOtherEvent</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #000000;">&#125;</span></div>
</li>
</ol>
</div>
</div>
</div>
<p>
and replaced all the strings with members of that enum.  I figured this would work just fine, but the change caused my unit test to fail.  Upon debugging, the EventHandlerList was always returning null in my <code>On*Event</code> calls.  After some more testing, the pattern became apparent: value types don't work as keys.  This was somewhat unexpected, as I've used enums like this in Hashtables all over the place before.  After doing a little <a href="http://www.aisto.com/roeder/dotnet/">Reflector</a>ing, the actual search for the key comes down to traversing a linked list with a simple equality test, something like this:</p>
<div class="igBar"><span id="lcsharp-7"><a href="#" onclick="javascript:showPlainTxt('csharp-7'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">C#:</span>
<div id="csharp-7">
<div class="csharp" style="font-family: monospace;">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #0600FF;">while</span> <span style="color: #000000;">&#40;</span>head != <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #000000;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>head.<span style="color: #0000FF;">key</span> == key<span style="color: #000000;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#123;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0600FF;">return</span> head;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000;">&#125;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; head = head.<span style="color: #0000FF;">next</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #000000;">&#125;</span></div>
</li>
</ol>
</div>
</div>
</div>
<p>
The culprit ends up being <a href="http://msdn2.microsoft.com/en-us/library/yz2be5wk(VS.80).aspx">C#'s auto-boxing</a>.  The <code>key</code> is stored as an object, so my value types are being boxed on the way in, and therefore <code>==</code> is comparing object identity, not the object values.  If EventHandlerList used <code>head.key.Equals(key)</code>, everything would have worked how I expected.  The solution to rid myself of magic strings now becomes using static objects as my keys, so the object identities will match:</p>
<div class="igBar"><span id="lcsharp-8"><a href="#" onclick="javascript:showPlainTxt('csharp-8'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">C#:</span>
<div id="csharp-8">
<div class="csharp" style="font-family: monospace;">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #0600FF;">private</span> <span style="color: #0600FF;">static</span> <span style="color: #0600FF;">readonly</span> <span style="color: #FF0000;">object</span> MyEventKey = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> <span style="color: #FF0000;">object</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #0600FF;">private</span> <span style="color: #0600FF;">static</span> <span style="color: #0600FF;">readonly</span> <span style="color: #FF0000;">object</span> MyOtherEventKey = <a href="http://www.google.com/search?q=new+msdn.microsoft.com"><span style="color: #008000;">new</span></a> <span style="color: #FF0000;">object</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>;</div>
</li>
</ol>
</div>
</div>
</div>
<p>
That pattern reminds me a lot of enums in Java before it got a <a href="http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html">enum</a> keyword, which came on the heels of C#'s nice solution to the enumerated type problem.  It'd be nice if I could use enums for their intended purpose, but cases like this make me a bit wary.  Where else in the .NET framework am I going to find object identity equality where I expect to find object value equality?  Is there some rational explanation for this, or is this just a bug?</p>
]]></content:encoded>
			<wfw:commentRss>http://ryepup.unwashedmeme.com/blog/2007/05/25/eventhandlerlist-key-equality-and-auto-boxing-in-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Codeplex wastes six months reinventing wheels</title>
		<link>http://ryepup.unwashedmeme.com/blog/2007/03/27/codeplex-wastes-six-months-reinventing-wheels/</link>
		<comments>http://ryepup.unwashedmeme.com/blog/2007/03/27/codeplex-wastes-six-months-reinventing-wheels/#comments</comments>
		<pubDate>Tue, 27 Mar 2007 16:45:26 +0000</pubDate>
		<dc:creator>ryan</dc:creator>
				<category><![CDATA[annoying]]></category>
		<category><![CDATA[open source]]></category>

		<guid isPermaLink="false">http://ryepup.unwashedmeme.com/blog/2007/03/27/codeplex-wastes-six-months-reinventing-wheels/</guid>
		<description><![CDATA[I saw an announcement today that CodePlex, Microsoft's version of Sourceforge, has released a source control client. From the release: A common theme we've heard from our users is the desire to be able to work offline (in the "edit-merge-commit" style) when working on their CodePlex projects. Six months ago, we started working to write [...]]]></description>
			<content:encoded><![CDATA[<p>I saw an announcement today that <a href="http://www.codeplex.com/">CodePlex</a>, Microsoft's version of <a href="http://sourceforge.net">Sourceforge</a>, has released a <a href="http://blogs.msdn.com/codeplex/archive/2007/03/26/announcing-the-codeplex-source-control-client.aspx">source control client</a>.  From the release:</p>
<blockquote><p>
A common theme we've heard from our users is the desire to be able to work offline (in the "edit-merge-commit" style) when working on their CodePlex projects. Six months ago, we started working to write such a client that would integrate with our existing TFS server infrastructure, and today we've released <a href="http://www.codeplex.com/CodePlex/Release/ProjectReleases.aspx?ReleaseId=2660">our first beta of the client.</a></p>
<p>The CodePlex Client is a command line client for Windows, and requires .NET 2.0.
</p></blockquote>
<p>
This <strong>infuriates</strong> me.  This cool thing they spent six months (six!) writing is called <a href="http://subversion.tigris.org/">Subversion</a>, and it had a 1.0.0 release <a href="http://subversion.tigris.org/servlets/NewsItemView?newsItemID=612">three years ago.</a>  Subversion had its first beta <a href="http://subversion.tigris.org/servlets/NewsItemView?newsItemID=543">in late 2003</a>, so the Codeplex folks are waaay behind the state of the art on this one.
</p>
<p>
As a whole, I think the state of software is abysmal.  The only way to make it better is to stop writing new code.  New code is always full of bugs, and its an expensive path to get from blank screen to stable program.  We need to treat programming more like math, we need to build on our results.  Development tools is a special market, as our needs are all very similar, and when we need a tool, we have the skills to make it.
</p>
<p>
The Codeplex staff stated they needed to write their own client in order to integrate with the TFS server infrastructure.  According to an msdn article (<a href="http://msdn.microsoft.com/msdnmag/issues/06/00/TeamSystem/default.aspx">Get All Your Devs In A Row With Visual Studio 2005 Team System</a>), TFS seems to be a complicated tool to help manage your developers.  Reading the description, TFS seems to be an issue tracker, unit tester, continuous integration, source control system, and visual studio plugin.  So, basically a combination of <a href="http://trac.edgewall.org/">Trac</a>, <a href="http://www.nunit.org/">NUnit</a>, <a href="http://cruisecontrol.sourceforge.net/">CruiseControl.NET</a>, <a href="http://subversion.tigris.org/">Subversion</a>, and a visual studio plugin.  Why not just write the visual studio plugin, and hook into the tools people are already using?  All those tools have rich plugin-architectures that would probably support any sensible addition you'd want to make.
</p>
<p>
This problem is ingrained at Microsoft, which feels the need to brand everything, but it is in no way limited to them.  A search on <a href="http://sourceforge.net">Sourceforge</a> for "issue tracker" gives 585 results.  Sifting through those to pick a winner is difficult.  </p>
<p>It's more fun to write new code than read old code, but this fun wears off.  After a certain initial momentum creating your new tool, you will inevitably come to a realization "this is going to take me for-fucking-ever".  Unless your itch is particularly strong, you'll probably quit, and the world will be cursed with a 586th buggy issue tracker.  By writing a plugin, you can ride the new-code high usually from start to finish, since its a much smaller task.  </p>
<p>Reading code seems more difficult, but I think that's largely perception.  Its just another puzzle to solve.  Once you get over the idea that reading code is more difficult, it's really not that bad.  For most mature projects, it's probably easier for you to read through someone else's mound of debugged code than it is to write and debug your own mud-ball.
</p>
<p>I think we need find and evolve extensible tools, and stop trying to write them over again.  We can get the custom behavior we all need by writing and debugging plugins, which are going to be orders of magnitude faster and cheaper than writing the whole system from scratch.  I see this happening already, with communities forming around different tools to share plugins.  </p>
<p>Next time you need a development tool, don't open a new code file.  Do us all a favor, open up a browser, and just re-use previous results.</p>
]]></content:encoded>
			<wfw:commentRss>http://ryepup.unwashedmeme.com/blog/2007/03/27/codeplex-wastes-six-months-reinventing-wheels/feed/</wfw:commentRss>
		<slash:comments>54</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 1.047 seconds -->

