<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" version="2.0">

<channel>
	<title>Winterdom</title>
	
	<link>http://winterdom.com</link>
	<description>by dæmons be driven</description>
	<lastBuildDate>Wed, 08 May 2013 02:35:37 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/Commonality" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="commonality" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>ClrMD: Fetching DAC Libraries From Symbol Servers</title>
		<link>http://winterdom.com/2013/05/clrmd-fetching-dac-libraries-from-symbol-servers</link>
		<comments>http://winterdom.com/2013/05/clrmd-fetching-dac-libraries-from-symbol-servers#comments</comments>
		<pubDate>Wed, 08 May 2013 02:35:37 +0000</pubDate>
		<dc:creator>Tomas Restrepo</dc:creator>
				<category><![CDATA[.NET]]></category>

		<guid isPermaLink="false">http://winterdom.com/?p=1352</guid>
		<description><![CDATA[Last week, the first public beta of the Microsoft.Diagnostics.Runtime library was released. This is a very cool library that can be used to write automated dump analysis of processes hosting the CLR. One of the first things you will need in order to use ClrMD is get a hold of the DAC library for the [...]]]></description>
			<content:encoded><![CDATA[<p>Last week, the <a href="http://blogs.msdn.com/b/dotnet/archive/2013/05/01/net-crash-dump-and-live-process-inspection.aspx">first public beta</a> of the Microsoft.Diagnostics.Runtime library was released. This is a very cool library that can be used to write automated dump analysis of processes hosting the CLR.</p>
<p>One of the first things you will need in order to use ClrMD is get a hold of the DAC library for the specific version of the CLR that your dump/live process is using. If this is a local dump/process, then you&#8217;ll have the DAC handy, as it will be part of your .NET Framework installation (example: <code>c:\windows\Microsoft.NET\Framework64\v2.0.50727\mscordacwks.dll</code>).</p>
<p>If you&#8217;re inspecting a dump from another machine, then you could also copy the mscordacwks.dll from the right folder in the remote machine. A more interesting option, however, is to dynamically fetch the right DAC library from the public Microsoft Symbol Server. ClrMD does not have built-in code to do this, and it can be a bit tricky, but it&#8217;s possible to implement it relatively easy in many scenarios.</p>
<p>In order to do this, you first need find two native libraries and copy them over to the same directory your application executable is located:</p>
<ul>
<li>dbghelp.dll</li>
<li>symsrv.dll</li>
</ul>
<p>The right place to pick these up is as part of the Debugging Tools For Windows package. Remember that you need to pick these for the right bitness (x64 or x86) depending on your process architecture, which needs to match the architecture of the dump/process you&#8217;re going to be inspecting. For this case, I picked the debugger tools package that comes with the <a href="http://msdn.microsoft.com/en-US/windows/hardware/hh852363">Windows 8 SDK</a>. When you install the tools from the SDK installer, these get installed to <code>c:\Program Files (x86)\Windows Kits\8.0\Debuggers</code>.</p>
<p>For this sample, you need to put the x64 and x86 versions of the libraries in the corresponding folder under .\dbglibs in the project folder. A custom build action will then copy the right version over to the output directory:</a></p>
<pre class="codebg"><code>copy &quot;$(ProjectDir)dbglibs\$(PlatformName)\*.dll&quot; &quot;$(TargetDir)&quot;
</code></pre>
<p>The relevant code can be found in the <code>DacLocator</code> class. This class will load the dbghelp.dll library and initialize it. Using it is relatively simple:</p>
<pre class="codebg"><code>dacloc = DacLocator.FromPublicSymbolServer<span class="level16c">(</span>localCachePathTextBox.Text<span class="level16c">)</span>;
DataTarget dt = DataTarget.LoadCrashDump<span class="level16c">(</span>dumpFileTextBox.Text<span class="level16c">)</span>;
String dac = dacloc.FindDac<span class="level16c">(</span>dt.ClrVersions<span class="level15c">[</span><span class="Number">0</span><span class="level15c">]</span><span class="level16c">)</span>;
</code></pre>
<p>Here we&#8217;re just initializing the library to use the public Symbol Server and using the specified path as the local cache, and then attempting to locate the DAC library that is required. Finding the DAC itself is done using the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms680726(v=vs.85).aspx"><code>SymFindFileInPath()</code></a> function:</p>
<pre class="codebg"><code>StringBuilder symbolFile = <span class="Statement">new</span> StringBuilder<span class="level16c">(</span><span class="Number">2048</span><span class="level16c">)</span>;
<span class="Conditional">if</span> <span class="level16c">(</span> SymFindFileInPath<span class="level15c">(</span>ourProcess.Handle, searchPath, dacname,
    timestamp, fileSize, <span class="Number">0</span>, <span class="Number">0x02</span>, symbolFile, IntPtr.Zero, IntPtr.Zero<span class="level15c">)</span> <span class="level16c">)</span> <span class="level16c">{</span>
  <span class="Repeat">return</span> symbolFile.ToString<span class="level15c">()</span>;
<span class="level16c">}</span> <span class="Conditional">else</span> <span class="level16c">{</span>
  <span class="Exception">throw</span> <span class="Statement">new</span> Win32Exception<span class="level15c">(</span>String.Format<span class="level14c">(</span><span class="String">&quot;SymFindFileInPath() failed: {0}&quot;</span>, Marshal.GetLastWin32Error<span class="level13c">()</span><span class="level14c">)</span><span class="level15c">)</span>;
<span class="level16c">}</span>
</code></pre>
<p>The rest of the sample is pretty straightforward: It just iterates through all objects in the heap, looking for HttpContext items and then<br />
printing out some basic details of each one:</p>
<pre class="codebg"><code><span class="StorageClass">private</span> IEnumerable&lt;HttpCtxtInfo&gt; FindHttpContexts<span class="level16c">(</span>ClrRuntime clr<span class="level16c">)</span> <span class="level16c">{</span>
  ClrHeap heap = clr.GetHeap<span class="level15c">()</span>;
  <span class="Repeat">foreach</span> <span class="level15c">(</span> <span class="Type">ulong</span> addr <span class="Statement">in</span> heap.EnumerateObjects<span class="level14c">()</span> <span class="level15c">)</span> <span class="level15c">{</span>
    ClrType type = heap.GetObjectType<span class="level14c">(</span>addr<span class="level14c">)</span>;
    <span class="Conditional">if</span> <span class="level14c">(</span> type == <span class="Constant">null</span> <span class="level14c">)</span> <span class="Repeat">continue</span>;
    <span class="Conditional">if</span> <span class="level14c">(</span> type.Name != <span class="String">&quot;System.Web.HttpContext&quot;</span> <span class="level14c">)</span> <span class="Repeat">continue</span>;

    <span class="Repeat">yield</span> <span class="Repeat">return</span> GetHttpContextInfo<span class="level14c">(</span>heap, addr, type<span class="level14c">)</span>;
  <span class="level15c">}</span>
<span class="level16c">}</span>

<span class="StorageClass">private</span> HttpCtxtInfo GetHttpContextInfo<span class="level16c">(</span>ClrHeap heap, <span class="Type">ulong</span> addr, ClrType type<span class="level16c">)</span> <span class="level16c">{</span>
  HttpCtxtInfo info = <span class="Statement">new</span> HttpCtxtInfo <span class="level15c">{</span>
    Address = addr
  <span class="level15c">}</span>;
  <span class="Type">ulong</span> reqAddr = <span class="level15c">(</span><span class="Type">ulong</span><span class="level15c">)</span>type.GetFieldByName<span class="level15c">(</span><span class="String">&quot;_request&quot;</span><span class="level15c">)</span>.GetFieldValue<span class="level15c">(</span>addr<span class="level15c">)</span>;
  ClrType reqType = heap.GetObjectType<span class="level15c">(</span>reqAddr<span class="level15c">)</span>;
  info.Method = <span class="level15c">(</span><span class="Type">string</span><span class="level15c">)</span>reqType.GetFieldByName<span class="level15c">(</span><span class="String">&quot;_httpMethod&quot;</span><span class="level15c">)</span>.GetFieldValue<span class="level15c">(</span>reqAddr<span class="level15c">)</span>;
  info.Url = <span class="level15c">(</span><span class="Type">string</span><span class="level15c">)</span>reqType.GetFieldByName<span class="level15c">(</span><span class="String">&quot;_rawUrl&quot;</span><span class="level15c">)</span>.GetFieldValue<span class="level15c">(</span>reqAddr<span class="level15c">)</span>;
  <span class="Repeat">return</span> info;
<span class="level16c">}</span>
</code></pre>
<p>Running the sample app will look something like this:</p>
<div id="attachment_1354" class="wp-caption alignnone" style="width: 680px"><a href="http://winterdom.com/wp-content/uploads/2013/05/DacSample.png"><img src="http://winterdom.com/wp-content/uploads/2013/05/DacSample.png" alt="" title="DacSample" width="670" height="439" class="size-full wp-image-1354" /></a><p class="wp-caption-text">DacSample Screenshot</p></div>
<p>The sample code can be downloaded <a href="http://winterdom.com/files/DacSample.zip">here</a>. Enjoy!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Commonality?a=vpQoG2tCiNU:wu94nae87JE:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/Commonality?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Commonality?a=vpQoG2tCiNU:wu94nae87JE:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Commonality?i=vpQoG2tCiNU:wu94nae87JE:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Commonality/~4/vpQoG2tCiNU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://winterdom.com/2013/05/clrmd-fetching-dac-libraries-from-symbol-servers/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Updating Visual Studio Extensions</title>
		<link>http://winterdom.com/2012/07/updating-visual-studio-extensions</link>
		<comments>http://winterdom.com/2012/07/updating-visual-studio-extensions#comments</comments>
		<pubDate>Sun, 01 Jul 2012 16:50:38 +0000</pubDate>
		<dc:creator>Tomas Restrepo</dc:creator>
				<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false">http://winterdom.com/2012/07/updating-visual-studio-extensions</guid>
		<description><![CDATA[I spent some time this week researching what would be needed to update some of my Visual Studio 2010 extensions to support Visual Studio 2012. I’ve now managed to do so, and would like to share what I found in case anyone else finds it useful. Warning: This post was written and tested with the [...]]]></description>
			<content:encoded><![CDATA[<p>I spent some time this week researching what would be needed to update some of my Visual Studio 2010 extensions to support Visual Studio 2012. I’ve now managed to do so, and would like to share what I found in case anyone else finds it useful.</p>
<p><b>Warning:</b> This post was written and tested with the Visual Studio 2012 release candidate and I have no clue how well it will work on the final release. I&#8217;ll update it or post again once it comes out if needed.</p>
<p>The first thing to try was, of course, to take the existing code, migrate it into a VS2012 project, and update all references to Visual Studio assemblies. That worked, as far as building goes, but the extensions would still not work. It is not that they would cause any errors; they just didn’t do anything.</p>
<p>In this particular case, I focused on two of my extensions: <a href="http://winterdom.com/2009/10/updating-vs2010-extensions-for-beta-2">KeywordClassifier</a> and <a href="http://winterdom.com/2010/05/betterxml">BetterXml</a>. Both of them rely on the same mechanism, which was layering an <code>ITagger&lt;ClassificationTag&gt;</code> on top of the tags produced by the original provider. This was done through the use of an <code>ITagAggregator&lt;ClassificationTag&gt;</code>.</p>
<p>After a bit of debugging, I discovered the reason the original code was no longer working was because the <code>ITagAggregator&lt;ClassificationTag&gt;</code> instance returned by Visual Studio would simply return an empty list when <code>GetTags()</code> was called.</p>
<p>With some experimentation, I realized that while asking for an <code>ITagAggregator&lt;ClassificationTag&gt;</code> no longer worked, asking for an <code>ITagAggregator&lt;<i>IClassificationTag</i>&gt;</code> (that is, use the interface instead of the specific type) would indeed work. Plus, the same code would work just as well in VS2010!</p>
<pre class="codebg"><code><span class="Repeat">return</span> <span class="Statement">new</span> KeywordTagger<span class="level16c">(</span>
  ClassificationRegistry,
  Aggregator.CreateTagAggregator&lt;IClassificationTag&gt;<span class="level15c">(</span>buffer<span class="level15c">)</span>
<span class="level16c">)</span> <span class="Statement">as</span> ITagger&lt;T&gt;;
</code></pre>
<p>I was still not terribly thrilled about having to keep separate branches of the extensions with different project files and manifests to support both Visual Studio versions, so I started digging a bit more to see what other options there were. After a bunch of tests, I came up with something that works and allows me to keep a single VSIX file that works across both versions:</p>
<ul>
<li>Modify the extension manifest to make it installable under VS2012. I did this modifying the <code>&lt;SupportedProducts&gt;</code> tag in the .vsixmanifest file to add an entry for VS2012, like this:
<pre class="codebg"><code><span class="Function">&lt;</span><span class="Function">VisualStudio</span><span class="Function"> </span><span class="Type">Version</span>=<span class="String">&quot;11.0&quot;</span><span class="Function">&gt;</span>
  <span class="Function">&lt;</span><span class="Function">Edition</span><span class="Function">&gt;</span>Ultimate<span class="Identifier">&lt;/Edition&gt;</span>
  <span class="Function">&lt;</span><span class="Function">Edition</span><span class="Function">&gt;</span>Premium<span class="Identifier">&lt;/Edition&gt;</span>
  <span class="Function">&lt;</span><span class="Function">Edition</span><span class="Function">&gt;</span>Pro<span class="Identifier">&lt;/Edition&gt;</span>
  <span class="Function">&lt;</span><span class="Function">Edition</span><span class="Function">&gt;</span>IntegratedShell<span class="Identifier">&lt;/Edition&gt;</span>
  <span class="Function">&lt;</span><span class="Function">Edition</span><span class="Function">&gt;</span>VST_All<span class="Identifier">&lt;/Edition&gt;</span>
<span class="Identifier">&lt;/VisualStudio&gt;</span>
</code></pre>
<p>Now, I do not know if these are the correct edition strings, though, but they work with the VS2012 release candidate ultimate edition that is in MSDN. If anyone knows what the right strings should be, let me know and I&#8217;ll fix it. </li>
<li>I changed the MaxVersion attribute of the SupportedFrameworkRuntimeEdition tag to specify .NET 4.5. I don&#8217;t know if that is needed (or useful), but probably wouldn&#8217;t hurt <img src='http://winterdom.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> 
<pre class="codebg"><code><span class="Function">&lt;</span><span class="Function">SupportedFrameworkRuntimeEdition</span><span class="Function"> </span><span class="Type">MinVersion</span>=<span class="String">&quot;4.0&quot;</span><span class="Function"> </span><span class="Type">MaxVersion</span>=<span class="String">&quot;4.5&quot;</span><span class="Function"> /&gt;</span>
</code></pre>
</li>
<li>Build the extension and package using VS2010, without changing the existing (and VS2010-specific) assembly references. </li>
</ul>
<p>After trying this, the two extensions would load and run just fine in both VS2010 and VS2012, even if just one of them had been installed. I guess that VS2012 might be doing some assembly redirection when the extension is loaded, to ensure references are loaded correctly despite the fact that they have changed versions for 2012.</p>
<p>I&#8217;ve updated the code of <a href="https://github.com/tomasr/KeywordClassifier">KeywordClassifier</a> and <a href="https://github.com/tomasr/BetterXml">BetterXml</a> on GitHub with the necessary changes. A big &#8216;Thank you!&#8217; goes out to Oren Novotny for the help.</p>
<p>On the plus side, I discovered that my <a href="http://winterdom.com/2010/02/fix-for-xaml-highlighting-in-vs2010">XAML Classifier Fix</a> extension is no longer needed in Visual Studio 2012, now that the team introduced an explicit <code>XAML Text</code> classification.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Commonality?a=Pq8WH8dAgcc:gE9ptl5LUAU:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/Commonality?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Commonality?a=Pq8WH8dAgcc:gE9ptl5LUAU:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Commonality?i=Pq8WH8dAgcc:gE9ptl5LUAU:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Commonality/~4/Pq8WH8dAgcc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://winterdom.com/2012/07/updating-visual-studio-extensions/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Using PowerShell with Clustered MSMQ</title>
		<link>http://winterdom.com/2011/10/using-powershell-with-clustered-msmq</link>
		<comments>http://winterdom.com/2011/10/using-powershell-with-clustered-msmq#comments</comments>
		<pubDate>Tue, 25 Oct 2011 13:43:43 +0000</pubDate>
		<dc:creator>Tomas Restrepo</dc:creator>
				<category><![CDATA[MSMQ]]></category>

		<guid isPermaLink="false">http://winterdom.com/2011/10/using-powershell-with-clustered-msmq</guid>
		<description><![CDATA[My good friend Lars Wilhelmsen asked me a couple of days ago if I knew of a way to automate creating Queues on a clustered instance of MSMQ. Normally, a cluster of machines using Microsoft Cluster Service (MSCS) with MSMQ in Windows Server 2008 and up will have several MSMQ instances installed. For example, a [...]]]></description>
			<content:encoded><![CDATA[<p>My good friend <a href="http://www.larswilhelmsen.com/">Lars Wilhelmsen</a> asked me a couple of days ago if I knew of a way to automate creating Queues on a clustered instance of MSMQ. Normally, a cluster of machines using Microsoft Cluster Service (MSCS) with MSMQ in Windows Server 2008 and up will have several MSMQ instances installed. For example, a 2-node cluster will typically have 3 MSMQ instances: 2 local ones (one for each node) and the clustered instance, which will be configured/running on a single node at a time.</p>
<p>So what usually happens is that if you try using <code>System.Messaging</code> on PowerShell on an MSMQ cluster, you’ll end up creating the queues in the local instance, not the clustered instance. And <code>MessageQueue.Create()</code> doesn’t allow you to specify a machine name either.</p>
<p>The trick to getting this to work lies in <a href="http://support.microsoft.com/kb/198893">KB198893</a> (Effects of checking ”Use Network Name for Computer Name” in MSCS). Basically all you have to do is set the <code>_CLUSTER_NETWORK_NAME_</code> environment variable to the name of the Virtual Server that hosts the clustered MSMQ resource:</p>
<pre class="codebg"><code><span class="Identifier">$env:_CLUSTER_NETWORK_NAME_</span> = <span class="String">'myclusterMSMQ'</span>
<span class="Type">[System.Messaging.MessageQueue]</span>::Create(<span class="String">'.\Private$\MyQueue'</span>)
</code></pre>
<p>One thing to keep in mind, though: You have to set this environment variable <em>before</em> you attempt to use any <code>System.Messaging</code> feature; otherwise it will simply be ignored because the MSMQ runtime will already be bound to the local MSMQ instance.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Commonality?a=-dW0tzTKqMU:JyzSNABobXg:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/Commonality?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Commonality?a=-dW0tzTKqMU:JyzSNABobXg:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Commonality?i=-dW0tzTKqMU:JyzSNABobXg:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Commonality/~4/-dW0tzTKqMU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://winterdom.com/2011/10/using-powershell-with-clustered-msmq/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>MSMQ and External Certificates</title>
		<link>http://winterdom.com/2011/09/msmq-and-external-certificates</link>
		<comments>http://winterdom.com/2011/09/msmq-and-external-certificates#comments</comments>
		<pubDate>Fri, 30 Sep 2011 01:26:45 +0000</pubDate>
		<dc:creator>Tomas Restrepo</dc:creator>
				<category><![CDATA[MSMQ]]></category>

		<guid isPermaLink="false">http://winterdom.com/2011/09/msmq-and-external-certificates</guid>
		<description><![CDATA[I’ve spent some time lately playing around with MSMQ, Authentication and the use of External Certificates. This is an interesting scenario, but one that I found to be documented in relatively unclear terms, with somewhat conflicting information all over the place. Plus, the whole process isn’t very transparent at first. Normally, when you’re using MSMQ [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve spent some time lately playing around with MSMQ, Authentication and the use of External Certificates. This is an interesting scenario, but one that I found to be documented in relatively unclear terms, with somewhat conflicting information all over the place. Plus, the whole process isn’t very transparent at first.</p>
<p>Normally, when you’re using MSMQ Authentication, you’ll have MSMQ configured with Active Directory Integration. When this setup, MSMQ will normally create an internal, self-signed certificate for each user/machine pair and register it in Active Directory. The sender would then request that the message be sent authenticated, which will cause the local MSMQ runtime to sign the message body + a set of properties using this certificate, and then include the public key of the certificate and the signature (encrypted with the certificate’s private key) alongside the message.</p>
<p>The MSMQ service where the authenticated queue is defined would then verify the signature using the certificate public key to ensure it wasn’t tampered with. If that check passed, it could then lookup a matching certificate in AD, allowing it to identity the user sending the message for authentication (there are a few more checks in there, but this is the basic process).</p>
<p>This basic setup runs fairly well and is easy to test. Normally all you have to do here is:</p>
<ul>
<li>Mark the target queue with the Authenticated property:      <br /><a href="http://winterdom.com/wp-content/uploads/2011/09/msmq_auth.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="msmq_auth" border="0" alt="msmq_auth" src="http://winterdom.com/wp-content/uploads/2011/09/msmq_auth_thumb.png" width="366" height="120" /></a> </li>
<li>Have the sender make sure to request authentication. For System.Messaging, this would be the <a href="http://msdn.microsoft.com/en-us/library/system.messaging.messagequeue.authenticate.aspx">MessageQueue.Authenticate</a> property, while using the C/C++ API it would mean setting the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms701308(v=vs.85).aspx">PROPID_M_AUTH_LEVEL</a> property to an appropriate value (normally MQMSG_AUTH_LEVEL_ALWAYS). </li>
</ul>
<h2>External Certificates</h2>
<p>So what if you didn’t want to use the MSMQ internal certificate, for some reason? Well, MSMQ also allows you to use your own certificates, which could be, for example, generated using your Certificate Server CA installation trusted by your domain, or some other well known Certification Authority. To do this you need to:</p>
<ol>
<li>Register your certificate + private key on the sender machine for the user that is going to be sending the messages. The docs all talk about registering the certificate on the “Microsoft Internet Explorer Certificate Store” which confused me at first, but turns out it just meant that it would normally be the CurrentUser\MY store. </li>
<li>Register the certificate (public key only) on the corresponding AD object so that the receiving MSMQ server can find it. You can do this using the MSMQ admin console from the MSMQ server properties window, or using the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms705096(v=vs.85).aspx">MQRegisterCertificate()</a> API. </li>
</ol>
<p>I decided to try this using a simple self-signed certificate generated using <a href="http://msdn.microsoft.com/en-us/library/bfsktky3(v=vs.80).aspx">MakeCert</a> (a tool I hate having to use because I can never remember the right arguments to use!). I created my certificate into CurrentUser\MY, then registed the public part of the cert using with the MSMQ management console.</p>
<p>The next part was changing my sender application code to use the external certificate, which is done by setting MessageQueue.SenderCertificate (or the PROPID_M_SENDER_CERT property). It wasn’t immediately obvious at first what format the certificate was to be provided, but turns out it’s just the DER-encoded representation of the X.509 certificate. In .NET, this means you can just use <a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate.getrawcertdata.aspx">X509Certificate.GetRawCertData()</a>/<a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2.rawdata.aspx">X509Certificate2.RawData</a> or <a href="http://msdn.microsoft.com/en-us/library/dxz81eb9.aspx">X509Certificate.Export()</a> with <a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509contenttype.aspx">X509ContentType.Cert</a> value, which is equivalent. Here’s the basic code:</p>
<pre class="codebg"><code>X509Certificate cert = ...;

Message msg = <span class="Statement">new</span> Message();
msg.Body = data;
msg.UseDeadLetterQueue = <span class="Constant">true</span>;
msg.UseAuthentication = <span class="Constant">true</span>;
msg.SenderCertificate = cert.GetRawCertData();
queue.Send(msg, MessageQueueTransactionType.Single);
</code></pre>
<p>I ran this on my Windows 7 machine and all I got was this error: </p>
<pre class="codebg"><code>System.Messaging.MessageQueueException (0x80004005): Cryptographic function has failed.
   at System.Messaging.MessageQueue.SendInternal(Object obj, MessageQueueTransaction internalTransaction, MessageQueueTransactionType transactionType)
   at System.Messaging.MessageQueue.Send(Object obj, MessageQueueTransactionType transactionType)
   at MsmqTest1.Program.Main(String[] args) in C:\tomasr\tests\MSMQ\MsmqTest1\Program.cs:line 73
</code></pre>
<p>What follows is a nice chase down the rabbit hole in order to figure it out.</p>
<h2>The Problem</h2>
<p>After bashing my head against this error for a few hours, I have to admit I was stumped and had no clue what was going on. My first impression was that I had been specifying the certificate incorrectly (false) or that I was deploying my certificate to the wrong stores. That wasn&#8217;t it, either. Then I thought perhaps there was something in my self-signed certificate that was incorrect, so I started comparing its properties with those of the origina MSMQ internal certificate used in the first test. As far as I could see, the only meaningful difference was that the MSMQ one had 2048-bit keys while mine had 1024-bit ones, but that was hardly relevant at this point.</p>
<p>After some spelunking and lots of searching I ran into the <a href="http://blogs.msdn.com/b/johnbreakwell/archive/2008/07/09/latest-version-1-5-of-the-logging-script-for-msmq-3-0.aspx">MQTrace script</a> [1]. With that in hand, I enabled MSMQ tracing and notice a 0&#215;80090008 error code, which means NTE_BAD_ALGID (&quot;Invalid algorithm specified&quot;). So obviously somehow MSMQ was using a &quot;wrong&quot; algorithm, but which one, and why?</p>
<p>In the middle of all this I decided to try something: I switched my sender application to delivering the message over HTTP instead of the native MSMQ TCP-based protocol; all it required was changing the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms700996(v=vs.85).aspx">Format Name</a> used to reference the queue. This failed with the same error, but the MSMQ log gave me another bit of information: The NTE_BAD_ALGID error was being returned by a <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa379908(v=vs.85).aspx">CryptCreateHash()</a> function call!</p>
<p>Armed with this dangerous knowledge, I whipped out trusty WinDBG, set up a breakpoint in CryptCreateHash() and ran into this:</p>
<pre class="codebg"><code>003ee174 50b6453f 005e14d0 <font color="red">0000800e</font> 00000000 CRYPTSP!CryptCreateHash</code></pre>
<p>0x800e is CALG_SHA512. So MSMQ was trying to use the SHA-512 algorithm for the hash; good information! Logically, the next thing I tried was to force MSMQ to use the more common SHA-1 algorithm instead by setting the appropriate property in the message (<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms706984(v=vs.85).aspx">PROPID_M_HASH_ALG</a>):</p>
<pre class="codebg"><code>msg.HashAlgorithm = HashAlgorithm.Sha;</code></pre>
<p>And it worked! Well, for HTTP anyhow, as it broke again as soon as I switched the sender app back to the native transport. It turns out that the <code>PROPID_M_HASH_ALG</code> property is ignored when using the native transport.</p>
<h2>Changes in MSMQ 4.0 and 5.0</h2>
<p>Around this time I ran into a couple of interesting documents:</p>
<ul>
<li><a href="http://technet.microsoft.com/en-us/library/dd759129.aspx">What&#8217;s new in Message Queuing 5.0</a> </li>
<li><a href="http://blogs.msdn.com/b/johnbreakwell/archive/2009/05/22/changes-for-msmq-in-windows-7-and-windows-server-2008-r2.aspx">MSMQ 5.0 &#8211; Changes introduced with Windows 7 and Windows Server 2008 R2</a> </li>
</ul>
<p>The key part that came up from both of these is that in MSMQ 4.0 and 5.0 there were security changes around the Hash algorithm used for signing messages. In MSMQ 4.0, support for using SHA-2 was added and MAC/MD2/MD4/MD5 were disabled by default, while keeping SHA-1 as the default one. In MSMQ 5.0, however, SHA-1 was disabled by default again and SHA-2 (specifically SHA-512) was made the default [2]. So this explains readily why my test case was using SHA-512 as the hashing algorithm.</p>
<p>At this point I went back to using internal MSMQ certificates and checked what Hash algorithm was being used in that case and, sure enough, it was using SHA-512 as well. Obviously then something in the certificate I was providing was triggering the problem, but what?</p>
<p>And then it hit me that the problem had nothing to do with the certificate itself, but with the private/public key pair associated with the certificate. When you create/request a certificate, one aspect is what Cryptographic (CAPI) Provider to use to generate (and store it?) and I had been using the default, which is the &quot;Microsoft Strong Cryptographic Provider&quot;; according to <a href="http://msdn.microsoft.com/en-us/library/bb931357(v=VS.85).aspx">this page</a> it apparently isn&#8217;t quite strong enough to support SHA-2 [3].</p>
<p>So I created a new certificate, this time explicitly using a cryptographic provider that supports SHA-2, by providing the following arguments to my <code>MakeCert.exe</code> call</p>
<pre class="codebg"><code>-sp &quot;Microsoft Enhanced RSA and AES Cryptographic Provider&quot; -sy 12</code></pre>
<p>And sure enough, sending authenticated messages over the native protocol succeeded now. Sending over HTTP also worked with the updated certificate without having to set the <code>HashAlgorithm</code> property.</p>
<h2>Exporting and Using Certificates</h2>
<p>Something to watch out for that might not be entirely obvious: If you export a certificate + private key from a system store into a PFX (PKCS#12) file, your original choice of cryptographic service provider is stored alongside the key in the file:</p>
<p><a href="http://winterdom.com/wp-content/uploads/2011/09/pfx.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="pfx" border="0" alt="pfx" src="http://winterdom.com/wp-content/uploads/2011/09/pfx_thumb.png" width="717" height="394" /></a></p>
<p>Once you import the PFX file into a second machine, it will use the same crypto provider as the original one. This might be important if you&#8217;re generating certificates in one machine for using in another. The lesson so far seems to be: </p>
<p><quote>When using external certificates for use with MSMQ 5.0, ensure you choose a cryptographic provider that supports SHA-2 when generating the public/private key pair of the certificate, like the &quot;Microsoft Enhanced RSA and AES Cryptographic Provider&quot;.</quote> </p>
<p>At this point I&#8217;m not entirely sure how much control you have over this part if you&#8217;re generating the certificates in, say, Unix machines where this concept doesn&#8217;t apply (or how exactly it might work with external certification authorities).</p>
<h2>External Certificates in Workgroup Mode</h2>
<p>Another aspect I was interested in was the use of External Certificates when MSMQ is in Workgroup mode. In this mode, authenticated queues aren&#8217;t all that useful (at least as far as I understand things right now), because without AD the receiving MSMQ server has no way to match the certificate used to sign the message with a Windows identity to use for the access check on the queue. In this scenario messages appear to be rejected when they reach the queue with a &quot;The signature is invalid&quot; error.</p>
<p>However, if the queue does <b>not</b> have the <code>Authenticated</code> option checked, then messages signed with external certificates will reach the queue successfully. The receiving application can then check that the message was indeed signed because the <a href="http://msdn.microsoft.com/en-us/library/system.messaging.message.digitalsignature.aspx">Message.DigitalSignature</a> (<a href="http://msdn.microsoft.com/en-us/library/ms699802(v=vs.85).aspx">PROPID_M_SIGNATURE</a>)property will contain the hash encrypted with the certificate private key as expected. The application could then simply retrieve the public key and look it up in whatever application-specific store it had to check it against known certificates.</p>
<p>My understanding here is that despite that it cannot lookup the certificate in DS, the MSMQ receiving server will still verify that the signature is indeed valid according to the certificate attached to the message. That&#8217;s only half the work so that&#8217;s why the application should then verify that the certificate is known and trusted.</p>
<p><b>[1]</b> John Breakwell&#8217;s MSMQ blog on MSDN is a godsend when troubleshooting and understanding MSMQ. Glad he continued posting about this stuff on his <a href="http://geekswithblogs.net/Plumbersmate/Default.aspx">alternate blog</a> after he left MS. </p>
<p><b>[2]</b> The System.Messaging stuff does not provide a way to specify SHA-2 algorithms in the message properties in .NET 4.0. No idea if this will be improved in the future. </p>
<p><b>[3]</b> I always thought the CAPI providers seemed to be named by someone strongly bent on confusing his/her enemies&#8230;</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Commonality?a=7-crYQ0zdYQ:riYHvEeDT1c:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/Commonality?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Commonality?a=7-crYQ0zdYQ:riYHvEeDT1c:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Commonality?i=7-crYQ0zdYQ:riYHvEeDT1c:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Commonality/~4/7-crYQ0zdYQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://winterdom.com/2011/09/msmq-and-external-certificates/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Having Fun with WinDBG</title>
		<link>http://winterdom.com/2011/06/having-fun-with-windbg</link>
		<comments>http://winterdom.com/2011/06/having-fun-with-windbg#comments</comments>
		<pubDate>Sun, 05 Jun 2011 18:16:44 +0000</pubDate>
		<dc:creator>Tomas Restrepo</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[windbg]]></category>

		<guid isPermaLink="false">http://winterdom.com/2011/06/having-fun-with-windbg</guid>
		<description><![CDATA[I’ve been spending lots of quality time with WinDBG and the rest of the Windows Debugging Tools, and ran into something I thought was fun to do. For the sake of keeping it simple, let’s say I have a sample console application that looks like this: using System; using System.Collections.Generic; using System.Linq; using System.Text; using [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve been spending lots of quality time with WinDBG and the rest of the Windows Debugging Tools, and ran into something I thought was fun to do.</p>
<p>For the sake of keeping it simple, let’s say I have a sample console application that looks like this:</p>
<pre class="codebg"><code><span class="Statement">using</span> System;
<span class="Statement">using</span> System.Collections.Generic;
<span class="Statement">using</span> System.Linq;
<span class="Statement">using</span> System.Text;
<span class="Statement">using</span> System.Runtime.CompilerServices;

<span class="StorageClass">class</span> Program {
  <span class="StorageClass">static</span> <span class="Type">void</span> Main(<span class="Type">string</span>[] args) {
    Program p = <span class="Statement">new</span> Program();
    <span class="Repeat">for</span> ( <span class="Type">int</span> i = <span class="Number">0</span>; i &lt; <span class="Number">10</span>; i++ ) {
      p.RunTest(<span class="String">"Test Run No. "</span> + i, i);
    }
  }
  [MethodImpl(MethodImplOptions.NoInlining)]
  <span class="StorageClass">public</span> <span class="Type">void</span> RunTest(String msg, <span class="Type">int</span> executionNumber) {
    Console.WriteLine(<span class="String">"Executing test"</span>);
  }
}</code></pre>
<p>Now, imagine I&#8217;m debugging such an application and I&#8217;d like to figure out what is passed as parameters to the <code>RunTest()</code> method, seeing as how the application doesn&#8217;t actually print those values directly. This seems contrived, but a classic case just like this one is a method that throws an <code>ArgumentException</code> because of a bad parameter input but the exception message doesn&#8217;t specify what the parameter value itself was.</p>
<p>For the purposes of this post, I’ll be compiling using release x86 as the target and running on 32-bit Windows. Now, let’s start a debug session on this sample application. Right after running it in the debugger, it will break right at the unmanaged entry point:</p>
<pre class="codebg"><code>Microsoft (R) Windows Debugger Version 6.11.0001.404 X86
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: .\DbgTest.exe
Symbol search path is: *** Invalid ***
****************************************************************************
* Symbol loading may be unreliable without a symbol search path.           *
* Use .symfix to have the debugger choose a symbol path.                   *
* After setting your symbol path, use .reload to refresh symbol locations. *
****************************************************************************
Executable search path is:
ModLoad: 012f0000 012f8000   DbgTest.exe
ModLoad: 777f0000 77917000   ntdll.dll
ModLoad: 73cf0000 73d3a000   C:\Windows\system32\mscoree.dll
ModLoad: 77970000 77a4c000   C:\Windows\system32\KERNEL32.dll
(f9c.d94): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=00000000 ecx=001cf478 edx=77855e74 esi=fffffffe edi=7783c19e
eip=77838b2e esp=001cf490 ebp=001cf4c0 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for ntdll.dll -
ntdll!DbgBreakPoint:
77838b2e cc              int     3
</code></pre>
<p>Now let&#8217;s fix the symbol path and also make sure SOS is loaded at the right time:</p>
<pre class="codebg"><code>0:000&gt; .sympath srv*C:\symbols*http://msdl.microsoft.com/download/symbols
Symbol search path is: srv*C:\symbols*http://msdl.microsoft.com/download/symbols
Expanded Symbol search path is: srv*c:\symbols*http://msdl.microsoft.com/download/symbols
0:000&gt; .reload
Reloading current modules
......
0:000&gt; sxe -c ".loadby sos clr" ld:mscorlib
0:000&gt; g
(1020.12c8): Unknown exception - code 04242420 (first chance)
ModLoad: 70b80000 71943000   C:\Windows\assembly\NativeImages_v4.0.30319_32\mscorlib\246f1a5abb686b9dcdf22d3505b08cea\mscorlib.ni.dll
eax=00000001 ebx=00000000 ecx=0014e601 edx=00000000 esi=7ffdf000 edi=20000000
eip=77855e74 esp=0014e5dc ebp=0014e630 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!KiFastSystemCallRet:
77855e74 c3              ret
</code></pre>
<p>At this point, managed code is not executing yet, but we&#8217;ve got SOS loaded. Now, what I&#8217;d like to do is set an initial breakpoint in the <code>RunTest()</code> method. Because it&#8217;s a managed method, we&#8217;d need to wait until it is jitted to be able to grab the generated code entry point. Instead of doing all that work, I&#8217;ll just use the !BPMD command included in SOS to set a pending breakpoint [1] on it, the resume execution:</p>
<pre class="codebg"><code>0:000&gt; !BPMD DbgTest.exe Program.RunTest
Adding pending breakpoints...
0:000&gt; g
(110c.121c): CLR notification exception - code e0444143 (first chance)
(110c.121c): CLR notification exception - code e0444143 (first chance)
(110c.121c): CLR notification exception - code e0444143 (first chance)
JITTED DbgTest!Program.RunTest(System.String, Int32)
Setting breakpoint: bp 001600D0 [Program.RunTest(System.String, Int32)]
Breakpoint 0 hit
eax=000d37fc ebx=0216b180 ecx=0216b180 edx=0216b814 esi=0216b18c edi=00000000
eip=001600d0 esp=002fece0 ebp=002fecf4 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
001600d0 55              push    ebp
</code></pre>
<p>Now he debugger has stopped execution on the first call to <code>RunTest</code>, so we can actually examine the values of the method arguments:</p>
<pre class="codebg"><code>0:000&gt; !CLRStack -p
OS Thread Id: 0x121c (0)
Child SP IP       Call Site
002fece0 001600d0 Program.RunTest(System.String, Int32)
    PARAMETERS:
        this (<clr reg>) = 0x0216b180
        msg (<clr reg>) = 0x0216b814
        executionNumber (0x002fece4) = 0x00000000
</code></pre>
<p>So the first parameter is the <code>this</code> pointer, as this is a method call. The <code>msg</code> parameter is a string, so let&#8217;s examine that as well:</p>
<pre class="codebg"><code>0:000&gt; !dumpobj -nofields 0x0216b814
Name:        System.String
MethodTable: 70e9f9ac
EEClass:     70bd8bb0
Size:        42(0x2a) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String:      Test Run No. 0
</code></pre>
<p>Now let&#8217;s look at this at a slightly lower level:</p>
<pre class="codebg"><code>0:000&gt; kbn3
 # ChildEBP RetAddr  Args to Child
WARNING: Frame IP not in any known module. Following frames may be wrong.
00 002fecdc 001600ab 00000000 00000000 004aa100 0x1600d0
01 002fecf4 727221db 002fed14 7272e021 002fed80 0x1600ab
02 002fed04 72744a2a 002fedd0 00000000 002feda0 clr!CallDescrWorker+0x33
0:000&gt; !IP2MD 0x1600d0
MethodDesc:   000d37fc
Method Name:  Program.RunTest(System.String, Int32)
Class:        000d1410
MethodTable:  000d3810
mdToken:      06000002
Module:       000d2e9c
IsJitted:     yes
CodeAddr:     001600d0
Transparency: Critical
0:000&gt; !IP2MD 0x1600ab
MethodDesc:   000d37f0
Method Name:  Program.Main(System.String[])
Class:        000d1410
MethodTable:  000d3810
mdToken:      06000001
Module:       000d2e9c
IsJitted:     yes
CodeAddr:     00160070
Transparency: Critical
</code></pre>
<p>Here we see the top 3 stack frames including the first 3 parameters to the call, and from the !IP2MD calls you can see the first 2 are the calls to <code>RunTest()</code> and <code>Main()</code>, just as we would expect.</p>
<p>The parameters displayed by the <code>kb</code> command, however, seem a bit weird for the <code>RunTest</code> call: <code>00000000 00000000 004aa100</code>. These are, literally, the values on the stack:</p>
<pre class="codebg"><code>0:000&gt; dd esp L8
002fece0  001600ab 00000000 00000000 004aa100
002fecf0  002fed20 002fed04 727221db 002fed14
</code></pre>
<p>Notice that at the top of the stack we have the return address to the place in <code>Main()</code> where the method call happened, followed by the &#8220;3 parameters&#8221; displayed by <code>kb</code>. However, this isn&#8217;t actually correct.</p>
<p>The CLR uses a calling convention that resembles the FASTCALL convention a bit. That means that in this case, the left-most parameter would be passed in the ECX register, the next one in EDX and the rest on the stack. In our case, this means that the value of the <code>this</code> pointer will go in ECX:</p>
<pre class="codebg"><code>0:000&gt; r ecx
ecx=0216b180
0:000&gt; !dumpobj ecx
Name:        Program
MethodTable: 000d3810
EEClass:     000d1410
Size:        12(0xc) bytes
File:        C:\temp\DbgTest\bin\release\DbgTest.exe
Fields:
None
</code></pre>
<p>It also means that the <code>msg</msg> argument will go in EDX:</code> </p>
<pre class="codebg"><code>0:000&gt; r edx
edx=0216b814
0:000&gt; !dumpobj -nofields edx
Name:        System.String
MethodTable: 70e9f9ac
EEClass:     70bd8bb0
Size:        42(0x2a) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String:      Test Run No. 0
</code></pre>
<p>So the value <code>executionNumber</code> argument will go in the stack, and we&#8217;ll find it at [esp+4]:</p>
<pre class="codebg"><code>0:000&gt; dd [esp+4] L1
002fece4  00000000
</code></pre>
<p>We could even disassemble the small piece of code in <code>Main</code> that calls <code>RunTest</code>, by backing up a bit before the current return address, and you&#8217;ll see how the value of <code>i</code> is pushed into the stack from the <code>edi</code> register and how the <code>ecx</code> and <code>edx</code> are likewise prepared for the call:</p>
<pre class="codebg"><code>0:000&gt; u 001600ab-12 L8
0016009b e87076b870      call    mscorlib_ni+0x2b7710 (70e37710)
001600a0 57              push    edi
001600a1 8bd0            mov     edx,eax
001600a3 8bcb            mov     ecx,ebx
001600a5 ff1504380d00    call    dword ptr ds:[0D3804h]
001600ab 47              inc     edi
001600ac 83ff0a          cmp     edi,0Ah
</code></pre>
<p>Knowing all this, if we wanted to print out the values of the <code>msg</code> and <code>executionNumber</code> parameters on all remaining calls to <code>RunTest</code>, we could replace the breakpoint setup by the <code>!BPMD</code> command with a regular breakpoint that executes a command and then continues execution. This would look something like this:</p>
<pre class="codebg"><code>0:000&gt; * remove existing breakpoint
0:000&gt; bc 0
0:000&gt; * check start address of RunTest
0:000&gt; !name2ee DbgTest.exe Program.RunTest
Module:      000d2e9c
Assembly:    DbgTest.exe
Token:       06000002
MethodDesc:  000d37fc
Name:        Program.RunTest(System.String, Int32)
JITTED Code Address: 001600d0
0:000&gt; * set breakpoint
0:000&gt; bp 001600d0 "!dumpobj -nofields edx; dd [esp+4] L1; g"
0:000&gt; g
Name:        System.String
MethodTable: 70e9f9ac
EEClass:     70bd8bb0
Size:        42(0x2a) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String:      Test Run No. 1
002fece4  00000001
Executing test
Name:        System.String
MethodTable: 70e9f9ac
EEClass:     70bd8bb0
Size:        42(0x2a) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String:      Test Run No. 2
002fece4  00000002
Executing test
Name:        System.String
MethodTable: 70e9f9ac
EEClass:     70bd8bb0
Size:        42(0x2a) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String:      Test Run No. 3
002fece4  00000003
...
</code></pre>
<p>As you can see, we&#8217;re indeed getting the values of both our arguments without problems in the debugger log (which we could easily write to a file using the <code>.logopen</code> command). This is a simple scenario, but can still prove useful sometimes. Of course, you could argue that going through all these contortions might be over the top, given that the <code>!ClrStack -p</code> command can give you parameters to each function in the call stack. The answer is that <code>!ClrStack</code> doesn&#8217;t make it easy to dump just the first frame, not does it combine with other commands so that you can easily use <code>!DumpObj</code> on the parameter values.</p>
<p><b>[1]</b> If !BPMD doesn&#8217;t seem to work, it&#8217;s likely because the CLR debugger notifications are disabled. See <a href="http://naveensrinivasan.com/2010/12/05/bpmdnotworking/">this post</a> on how to fix it (for .NET 4.0, just remember to replace <code>mscorwks</code> for <code>clr</code>).</p>
<pre></pre>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Commonality?a=hlJ-da6n9Zo:nAH_f9qKSto:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/Commonality?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Commonality?a=hlJ-da6n9Zo:nAH_f9qKSto:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Commonality?i=hlJ-da6n9Zo:nAH_f9qKSto:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Commonality/~4/hlJ-da6n9Zo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://winterdom.com/2011/06/having-fun-with-windbg/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item><title>Links for 2011-03-29 [del.icio.us]</title><link>http://del.icio.us/tomas.restrepo#2011-03-29</link><pubDate>Wed, 30 Mar 2011 00:00:00 PDT</pubDate><guid isPermaLink="true">http://del.icio.us/tomas.restrepo#2011-03-29</guid><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="http://marketplace.eclipse.org/content/eclipse-color-theme"&gt;Eclipse Color Theme | Eclipse Plugins, Bundles and Products ...&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/Commonality/~4/KsRA8V29VKM" height="1" width="1"/&gt;</description></item><item><title>Links for 2011-03-28 [del.icio.us]</title><link>http://del.icio.us/tomas.restrepo#2011-03-28</link><pubDate>Tue, 29 Mar 2011 00:00:00 PDT</pubDate><guid isPermaLink="true">http://del.icio.us/tomas.restrepo#2011-03-28</guid><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.smashingmagazine.com/2011/03/28/get-started-developing-for-android-with-eclipse-reloaded/"&gt;Get Started Developing For Android With Eclipse, Reloaded ...&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/Commonality/~4/VoYY8IOmwtY" height="1" width="1"/&gt;</description></item><item><title>Links for 2011-03-27 [del.icio.us]</title><link>http://del.icio.us/tomas.restrepo#2011-03-27</link><pubDate>Mon, 28 Mar 2011 00:00:00 PDT</pubDate><guid isPermaLink="true">http://del.icio.us/tomas.restrepo#2011-03-27</guid><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.dropbox.com/gallery/11469318/1/Android%20Stuff?h=d6c9f9"&gt;Android Wallpapers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/Commonality/~4/oR352D5ob7w" height="1" width="1"/&gt;</description></item><item>
		<title>Github Repo for Molokai</title>
		<link>http://winterdom.com/2011/02/github-repo-for-molokai</link>
		<comments>http://winterdom.com/2011/02/github-repo-for-molokai#comments</comments>
		<pubDate>Sun, 13 Feb 2011 15:20:32 +0000</pubDate>
		<dc:creator>Tomas Restrepo</dc:creator>
				<category><![CDATA[Vim]]></category>

		<guid isPermaLink="false">http://winterdom.com/2011/02/github-repo-for-molokai</guid>
		<description><![CDATA[After a couple of requests, I’ve created a separate git repository on github for my Molokai color scheme for Vim. Enjoy!]]></description>
			<content:encoded><![CDATA[<p>After a couple of requests, I’ve created a separate <a href="https://github.com/tomasr/molokai">git repository</a> on github for my <a href="http://winterdom.com/2008/08/molokaiforvim">Molokai</a> color scheme for Vim. Enjoy!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Commonality?a=lqSqJA976_8:meJ0-K2h_C0:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/Commonality?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Commonality?a=lqSqJA976_8:meJ0-K2h_C0:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Commonality?i=lqSqJA976_8:meJ0-K2h_C0:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Commonality/~4/lqSqJA976_8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://winterdom.com/2011/02/github-repo-for-molokai/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>BizTalk Send Handlers/SSO Bug?</title>
		<link>http://winterdom.com/2010/12/biztalk-send-handlerssso-bug</link>
		<comments>http://winterdom.com/2010/12/biztalk-send-handlerssso-bug#comments</comments>
		<pubDate>Fri, 17 Dec 2010 14:57:42 +0000</pubDate>
		<dc:creator>Tomas Restrepo</dc:creator>
				<category><![CDATA[BizTalk]]></category>

		<guid isPermaLink="false">http://winterdom.com/2010/12/biztalk-send-handlerssso-bug</guid>
		<description><![CDATA[My good friend Carlos ran into a situation while working with one of his clients that seems to be triggering what looks like a bug in BizTalk Server 2010. The specific case came up when changing the Windows User Group associated with a BizTalk Host when that host is already associated as a Send Handler [...]]]></description>
			<content:encoded><![CDATA[<p>My good friend Carlos ran into a situation while working with one of his clients that seems to be triggering what looks like a bug in BizTalk Server 2010. The specific case came up when changing the Windows User Group associated with a BizTalk Host when that host is already associated as a Send Handler for an adapter.</p>
<p>Apparently, when doing the change, BizTalk will correctly update the information stored in the Enterprise Single Sign-On (ENTSSO) database (SSODB) for Receive Handlers, but not with Send Handlers, which leaves the system generating errors when the host later tries to access the SSODB to access the stored adapter settings.</p>
<p>Here’s&#160; the repro instructions:</p>
<ol>
<li>Create a new BizTalk Host for the test. Let’s name it BTTestHost. Assign to it the default BizTalk Application Users group, and then create a new Host instance. </li>
<li>Add the BTTestHost as a send handler for an adapter; we’ll use the FILE adapter in this example. </li>
<li>At this point, if you&#8217; check the <code>ssodb.dbo.SSOX_ApplicationInfo</code> table, you should see an entry associated with FILE_TL_BTTestHost, so that’s our newly created send handler. You’ll notice that the <code>ai_admin_group_name</code> column has the value ”BizTalk Application Users”, as expected. </li>
<li>Now create a send port associated to the new Send Handler and test to verify everything is working correctly. </li>
<li>Stop and delete the existing host instance. </li>
<li>Now let’s create a new Windows Users Group, let’s name it “BizTalk Test Group”. We’ll also create a new windows user we’ll use to create a new host instance in a bit; and we’ll make that user a member of BizTalk Test Group. Make sure the user is <em>not</em> a member of “BizTalk Application Users”. </li>
<li>Open the properties for BTTestHost and change the associated Windows User Group, to the new “BizTalk Test Group”. </li>
<li>Go ahead and create a new Host Instance, add a new Send Port associated with our Send Handler and run a test. You’ll notice you’ll get an error with something like <em>“Access denied. The client user must be a member of one of the following accounts to perform this function.” </em>(followed by a list of windows user groups). </li>
<li>At this point, if you go back and check the <code>SSOX_ApplicationInfo</code> table again, you’ll notice that the row FILE_TL_BTTestHost still has the same value on the <code>ai_admin_group_name</code> column referencing the original group associated with the host, not the new group we assigned to it. This causes the access denied error for the host instance, because the host user is not considered to have access to the SSODB to read the adapter settings. </li>
</ol>
<p>The ugly part is that working around this problem requires you to delete the original Send Handler and recreating it, which requires you to move all send ports already associated with it one by one.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Commonality?a=KDUBGnWELoo:g49XHS9pSN8:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/Commonality?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Commonality?a=KDUBGnWELoo:g49XHS9pSN8:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Commonality?i=KDUBGnWELoo:g49XHS9pSN8:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Commonality/~4/KDUBGnWELoo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://winterdom.com/2010/12/biztalk-send-handlerssso-bug/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>BizTalk 2010 Config Tool Hanging</title>
		<link>http://winterdom.com/2010/11/biztalk-2010-config-tool-hanging</link>
		<comments>http://winterdom.com/2010/11/biztalk-2010-config-tool-hanging#comments</comments>
		<pubDate>Mon, 08 Nov 2010 12:35:57 +0000</pubDate>
		<dc:creator>Tomas Restrepo</dc:creator>
				<category><![CDATA[BizTalk]]></category>

		<guid isPermaLink="false">http://winterdom.com/2010/11/biztalk-2010-config-tool-hanging</guid>
		<description><![CDATA[Last week I was installing BizTalk Server 2010 on my development Virtual Machine, which previously had 2009 installed. Installation went fine, but when I started the BizTalk Configuration tool, it started hanging for minutes at a time. Strangely enough, the tool let me configure Enterprise Single Sign-On (ENTSSO) without any problems, but would hang every [...]]]></description>
			<content:encoded><![CDATA[<p>Last week I was installing BizTalk Server 2010 on my development Virtual Machine, which previously had 2009 installed. Installation went fine, but when I started the BizTalk Configuration tool, it started hanging for minutes at a time.</p>
<p>Strangely enough, the tool let me configure Enterprise Single Sign-On (ENTSSO) without any problems, but would hang every time I tried to configure a new BizTalk Group. After some tests, it became obvious it was hanging when trying to connect to SQL Server to check if the group databases could be created until the connection timeout would expire.</p>
<p>It would indeed eventually respond again, but trying to do anything would only cause it to hang again. It was really weird that it would hang here because of the database connection, when the SQL Server used was local and ENTSSO had configured straight away without any problems.</p>
<p>Fortunately, I managed to figure it out: The problem was that the SQL Server instance had TCP/IP connectivity disabled (only shared memory was enabled). Enabling TCP/IP and restarting the SQL Server service fixed the problem.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Commonality?a=K6FtAvXiOJY:a5l68u_hmoU:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/Commonality?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Commonality?a=K6FtAvXiOJY:a5l68u_hmoU:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Commonality?i=K6FtAvXiOJY:a5l68u_hmoU:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Commonality/~4/K6FtAvXiOJY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://winterdom.com/2010/11/biztalk-2010-config-tool-hanging/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item><title>Links for 2010-10-17 [del.icio.us]</title><link>http://del.icio.us/tomas.restrepo#2010-10-17</link><pubDate>Mon, 18 Oct 2010 00:00:00 PDT</pubDate><guid isPermaLink="true">http://del.icio.us/tomas.restrepo#2010-10-17</guid><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.d90.us/toolbox/2009/05/26/adding-ssl-support-to-squid-package-on-ubuntu/"&gt;Building Squid+SSL in ubuntu&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/Commonality/~4/bGc9AZFO7Bk" height="1" width="1"/&gt;</description></item><item><title>Links for 2010-10-02 [del.icio.us]</title><link>http://del.icio.us/tomas.restrepo#2010-10-02</link><pubDate>Sun, 03 Oct 2010 00:00:00 PDT</pubDate><guid isPermaLink="true">http://del.icio.us/tomas.restrepo#2010-10-02</guid><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.khanacademy.org/"&gt;Khan Academy&lt;/a&gt;&lt;br/&gt;
The Khan Academy is a not-for-profit 501(c)(3) with the mission of providing a world-class education to anyone, anywhere.&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/Commonality/~4/v_zcnrNcYqM" height="1" width="1"/&gt;</description></item><item><title>Links for 2010-07-28 [del.icio.us]</title><link>http://del.icio.us/tomas.restrepo#2010-07-28</link><pubDate>Thu, 29 Jul 2010 00:00:00 PDT</pubDate><guid isPermaLink="true">http://del.icio.us/tomas.restrepo#2010-07-28</guid><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="http://simpledesktops.com/"&gt;Simple Desktops&lt;/a&gt;&lt;br/&gt;
Simple, minimalistic wallpapers&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/Commonality/~4/aOPGZ8VG2pY" height="1" width="1"/&gt;</description></item><item><title>Links for 2010-07-21 [del.icio.us]</title><link>http://del.icio.us/tomas.restrepo#2010-07-21</link><pubDate>Thu, 22 Jul 2010 00:00:00 PDT</pubDate><guid isPermaLink="true">http://del.icio.us/tomas.restrepo#2010-07-21</guid><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.websequencediagrams.com/"&gt;WebSequenceDiagrams.com - Make Sequence Diagrams with one click&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/Commonality/~4/93gDT5j-a-c" height="1" width="1"/&gt;</description></item><item>
		<title>WCF Messages Not Getting Closed</title>
		<link>http://winterdom.com/2010/06/wcf-messages-not-getting-closed</link>
		<comments>http://winterdom.com/2010/06/wcf-messages-not-getting-closed#comments</comments>
		<pubDate>Wed, 30 Jun 2010 13:56:00 +0000</pubDate>
		<dc:creator>Tomas Restrepo</dc:creator>
				<category><![CDATA[WCF]]></category>

		<guid isPermaLink="false">http://winterdom.com/2010/06/wcf-messages-not-getting-closed</guid>
		<description><![CDATA[I spent some time yesterday evening tracking down an issue with a custom WCF transport channel. This particular channel would support the IInputChannel channel shape, but with a twist: it would return a custom implementation of System.ServiceModel.Channels.Message instead of one of the built-in WCF implementations. There’s nothing wrong with that and it was working just [...]]]></description>
			<content:encoded><![CDATA[<p>I spent some time yesterday evening tracking down an issue with a custom WCF transport channel. This particular channel would support the <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.channels.iinputchannel.aspx">IInputChannel</a> channel shape, but with a twist: it would return a custom implementation of <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.channels.message.aspx">System.ServiceModel.Channels.Message</a> instead of one of the built-in WCF implementations.</p>
<p>There’s nothing wrong with that and it was working just fine in most cases, until I ran into a few scenarios where the <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.channels.message.onclose.aspx">OnClose()</a> method of my custom Message class wasn’t being called at all.</p>
<p>After some digging, I discovered that the specific messages this was happening to were not being processed normally by the ServiceHost infrastructure. In particular, they were not being dispatched because no method in the service contract matched the action in the messages, so instead the <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.servicehostbase.unknownmessagereceived.aspx">UnknownMessageReceived</a> event in the ServiceHost instance was being raised.</p>
<p>Our UnknownMessageReceived implementation wasn’t closing messages explicitly, but that was easily corrected, so no problems, right? Wrong. Turns out, that it appears that in WCF 3.0/5 (haven’t checked 4.0 yet), if you do <em>not</em> have an event handler for UnknownMessageReceived, then the messages won’t get closed either.</p>
<p>This seems like a bad bug to me, because since Message implements IDisposable, there’s obviously the expectation that it will hold resources that should be released as soon as possible, so not calling <code>Dispose()</code> or <code>Closed()</code> will leak resources and potentially cause trouble.</p>
<p>Attaching an event handler to UnknownMessageReceived just isn’t an option always, and even if it were, there’s no reason why WCF itself shouldn’t be guaranteeing that messages are closed as soon as they aren’t needed.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Commonality?a=PGPDODWTXxY:0VXhItY0CCQ:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/Commonality?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Commonality?a=PGPDODWTXxY:0VXhItY0CCQ:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Commonality?i=PGPDODWTXxY:0VXhItY0CCQ:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Commonality/~4/PGPDODWTXxY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://winterdom.com/2010/06/wcf-messages-not-getting-closed/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>BetterXml</title>
		<link>http://winterdom.com/2010/05/betterxml</link>
		<comments>http://winterdom.com/2010/05/betterxml#comments</comments>
		<pubDate>Thu, 20 May 2010 03:20:41 +0000</pubDate>
		<dc:creator>Tomas Restrepo</dc:creator>
				<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false">http://winterdom.com/2010/05/betterxml</guid>
		<description><![CDATA[BetterXml is a Visual Studio 2010 extension I’ve been working on recently in an attempt to improve the experience of the built-in XML editor in VS. Right now it’s only on its early stages, so it doesn’t add much, but I hope to improve it as I find new things I’d like to add. What [...]]]></description>
			<content:encoded><![CDATA[<p>BetterXml is a Visual Studio 2010 extension I’ve been working on recently in an attempt to improve the experience of the built-in XML editor in VS. Right now it’s only on its early stages, so it doesn’t add much, but I hope to improve it as I find new things I’d like to add.</p>
<p>What does it do? BetterXml has two main features right now: Syntax highlighting extension and namespace tooltips.</p>
<h3></h3>
<h2>Syntax Highlighting</h2>
<p>BetterXml provides two new classification format definitions: XML Prefix and XML Closing Tag.</p>
<ul>
<li>XML Prefix will change the color/format used to highlight prefixes in XML names (the ‘x’ in x:name). </li>
<li>XML Closing Tag will change the color/format used to highlight closing element tags. This is one feature that some color schemes use in Vim that I always missed in VS, and it’s pretty cool that the extensibility model in VS2010 allows me to provide this; it makes reading long documents a lot easier. </li>
</ul>
<p>Here’s a screenshot showing both of these:</p>
<p><img alt="syntax highlighting" src="http://github.com/tomasr/BetterXml/raw/master/preview.png" /></p>
<p>This is supported on regular XML documents (including XSD) as well as XAML and HTML documents.</p>
<h2>Namespace Tooltips</h2>
<p>If you hover the mouse pointer over a prefix in an XML document, BetterXml will try to figure out the URI of the namespace that prefix maps to, and present a tooltip with that information:</p>
<p><img alt="tooltips" src="http://github.com/tomasr/BetterXml/raw/master/img/tooltips.png" /></p>
<p>I haven’t done much tweaking of this feature yet so it will probably be a bit slow on large documents, since it requires partially parsing the document. This feature is only supported on XML and XAML documents.</p>
<h2>Other Plans</h2>
<p>I’ve been looking into other improvements I’d like to add to BetterXml. One I really wanted to provide was extending Intellisense completion based on previously used element/attribute names, which would be pretty useful for XML documents without schema.</p>
<p>VS2010 does provide ways to <a href="http://msdn.microsoft.com/en-us/library/ee372314.aspx">extend completion</a>, and while it requires a lot of boilerplate code, it works. Unfortunately, after much trial and error I’ve been unable to make it work correctly, and certainly could never get it to behave the same way the built-in completion works.</p>
<p>While VS does seem to support multiple concurrent completion providers on the same buffer and will display the completion sets for all of them, I could not figure out the magic incantations to make it work reliably and in ways that behavior was predictable. Probably my own fault, but without clear documentation on how they are supposed to work together (if it’s even supported at all), it’s not trivial to do.</p>
<h2>Source</h2>
<p>Source code for <a href="http://github.com/tomasr/BetterXml">BetterXml</a> is available as usual on github.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Commonality?a=NjUW1BCKoKA:AoBuYyLOoZk:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/Commonality?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Commonality?a=NjUW1BCKoKA:AoBuYyLOoZk:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/Commonality?i=NjUW1BCKoKA:AoBuYyLOoZk:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Commonality/~4/NjUW1BCKoKA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://winterdom.com/2010/05/betterxml/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss><!-- Dynamic page generated in 0.349 seconds. --><!-- Cached page generated by WP-Super-Cache on 2013-05-13 20:54:36 -->
