<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" version="2.0">
  <channel>
    <title>Steve's Techspot</title>
    <link>http://www.stevestechspot.com/</link>
    <description>The weblog of Steve Johnson</description>
    <language>en-us</language>
    <copyright>Steve Johnson</copyright>
    <lastBuildDate>Mon, 18 Feb 2008 15:40:50 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 1.9.6264.0</generator>
    <managingEditor>sjjohnson@pobox.com</managingEditor>
    <webMaster>sjjohnson@pobox.com</webMaster>
    <item>
      <trackback:ping>http://www.stevestechspot.com/Trackback.aspx?guid=402f8247-76a4-4d2b-823b-d03a99b4942b</trackback:ping>
      <pingback:server>http://www.stevestechspot.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.stevestechspot.com/PermaLink,guid,402f8247-76a4-4d2b-823b-d03a99b4942b.aspx</pingback:target>
      <dc:creator>Steve Johnson</dc:creator>
      <wfw:comment>http://www.stevestechspot.com/CommentView,guid,402f8247-76a4-4d2b-823b-d03a99b4942b.aspx</wfw:comment>
      <wfw:commentRss>http://www.stevestechspot.com/SyndicationService.asmx/GetEntryCommentsRss?guid=402f8247-76a4-4d2b-823b-d03a99b4942b</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Today, a user reported the following error, which occurred when attempting to load
the extension.
</p>
        <p>
          <em>The call to LoadLibrary(sosex) failed, Win32 error 0n14001 "This application
has failed to start because the application configuration is incorrect. Reinstalling
the application may fix this problem." Please check your debugger configuration
and/or network access.</em>
        </p>
        <p>
The short answer to this is that I failed to include the VC9 redist.  You can
solve this problem by downloading the latest SOSEX zip file or by downloading the <a href="http://www.microsoft.com/Downloads/details.aspx?familyid=9B2DA534-3E03-4391-8A4D-074B9F2BC1BF&amp;displaylang=en">VC9
redist package</a> from Microsoft. The link to the x64 package is also at the bottom
of that page.
</p>
        <p>
Here's how I got there, given error number 14001, in case somebody else sees a similar
error message in their application.  The description for error 14001 is "The
application has failed to start because its side-by-side configuration is incorrect.
Please see the application event log for more detail."  My search for an
explanation of this error led me to <a href="http://blogs.msdn.com/junfeng/archive/2006/04/14/576314.aspx">this
page</a> on <a href="http://blogs.msdn.com/junfeng/default.aspx">Junfeng Zhang's excellent
blog</a>.  It was there that I learned that a missing CRT could cause this error.
</p>
        <img width="0" height="0" src="http://www.stevestechspot.com/aggbug.ashx?id=402f8247-76a4-4d2b-823b-d03a99b4942b" />
      </body>
      <title>SOSEX Initialization Problem</title>
      <guid isPermaLink="false">http://www.stevestechspot.com/PermaLink,guid,402f8247-76a4-4d2b-823b-d03a99b4942b.aspx</guid>
      <link>http://www.stevestechspot.com/SOSEXInitializationProblem.aspx</link>
      <pubDate>Mon, 18 Feb 2008 15:40:50 GMT</pubDate>
      <description>&lt;p&gt;
Today, a user reported the following error, which occurred when attempting to load
the extension.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;The call to LoadLibrary(sosex) failed, Win32 error 0n14001 &amp;quot;This application
has failed to start because the application configuration is incorrect. Reinstalling
the application may fix this problem.&amp;quot; Please check your debugger configuration
and/or network access.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
The short answer to this is that I failed to include the VC9 redist.&amp;#160; You can
solve this problem by downloading the latest SOSEX zip file or by downloading the &lt;a href="http://www.microsoft.com/Downloads/details.aspx?familyid=9B2DA534-3E03-4391-8A4D-074B9F2BC1BF&amp;amp;displaylang=en"&gt;VC9
redist package&lt;/a&gt; from Microsoft. The link to the x64 package is also at the bottom
of that page.
&lt;/p&gt;
&lt;p&gt;
Here's how I got there, given error number 14001, in case somebody else sees a similar
error message in their application.&amp;#160; The description for error 14001 is &amp;quot;The
application has failed to start because its side-by-side configuration is incorrect.
Please see the application event log for more detail.&amp;quot;&amp;#160; My search for an
explanation of this error led me to &lt;a href="http://blogs.msdn.com/junfeng/archive/2006/04/14/576314.aspx"&gt;this
page&lt;/a&gt; on &lt;a href="http://blogs.msdn.com/junfeng/default.aspx"&gt;Junfeng Zhang's excellent
blog&lt;/a&gt;.&amp;#160; It was there that I learned that a missing CRT could cause this error.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.stevestechspot.com/aggbug.ashx?id=402f8247-76a4-4d2b-823b-d03a99b4942b" /&gt;</description>
      <comments>http://www.stevestechspot.com/CommentView,guid,402f8247-76a4-4d2b-823b-d03a99b4942b.aspx</comments>
    </item>
    <item>
      <trackback:ping>http://www.stevestechspot.com/Trackback.aspx?guid=c51f1a46-0016-4f24-9ca7-61125105c6e1</trackback:ping>
      <pingback:server>http://www.stevestechspot.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.stevestechspot.com/PermaLink,guid,c51f1a46-0016-4f24-9ca7-61125105c6e1.aspx</pingback:target>
      <dc:creator>Steve Johnson</dc:creator>
      <wfw:comment>http://www.stevestechspot.com/CommentView,guid,c51f1a46-0016-4f24-9ca7-61125105c6e1.aspx</wfw:comment>
      <wfw:commentRss>http://www.stevestechspot.com/SyndicationService.asmx/GetEntryCommentsRss?guid=c51f1a46-0016-4f24-9ca7-61125105c6e1</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I've finally gotten around to updating SOSEX.  I incorporated most of the feedback
I received and I added a couple of other new goodies.  Here's what's new:
</p>
        <p>
          <strong>!vars:</strong>
          <br />
Added support for inspecting variables in frames other than the current frame. 
By passing a frame index (eg. !vars 3), you can inspect the variables in any single
frame in the call stack.  By passing the -w switch (!vars -w), the command will
walk the stack all the way up, dumping args/locals for each managed frame.  This
was the number one requested improvement for sosex. 
</p>
        <p>
          <strong>!date:</strong>
          <br />
New command.  Pass the address of a System.DateTime Value Type and the date will
be displayed in a human readable format (yyyy/mm/dd HH:mm:ss.zzz) 
<br />
This was another popular feature request. 
</p>
        <p>
          <strong>!dlk:</strong>
          <br />
Added detection capability for cases where a deadlock is caused by a dead thread holding
a lock. 
</p>
        <p>
          <strong>!bpmo/!bpsc:</strong>
          <br />
In v1.0, there was a bug that caused only the first instance of a generic method to
receive the breakpoint.  This is now fixed so that all generic instances get
the breakpoint as expected. 
</p>
        <p>
          <strong>!isf:</strong>
          <br />
Added -c switch to allow viewing of the static variable in the current context only. 
Without the switch, the state of the static field is displayed for all AppDomains/Threads. 
</p>
        <p>
          <strong>Value Type display:</strong>
          <br />
I also improved the display of value types.  When !isf or !vars show a value
type, SOSEX indicates a value type using a "VALUETYPE" indicator along with
a "MT" (method table address) and "ADDR" (value type start address)
indicator to facilitate dumping the data with the SOS!dumpvc command.  This provides
a big advantage over SOS and v1.0 of SOSEX, because they simply display the first
4 bytes of the value type data, with no VT indication or MT info.
</p>
        <p>
As always, feel free to contact me or leave comments to this post with any bug reports
or feature requests.
</p>
        <p>
Enjoy!
</p>
        <p>
 
</p>
        <p>
Download: <a href="/downloads/sosex_32.zip">x86</a> | <a href="/downloads/sosex_64.zip">x64</a></p>
        <img width="0" height="0" src="http://www.stevestechspot.com/aggbug.ashx?id=c51f1a46-0016-4f24-9ca7-61125105c6e1" />
      </body>
      <title>SOSEX Updated - v1.1 Available</title>
      <guid isPermaLink="false">http://www.stevestechspot.com/PermaLink,guid,c51f1a46-0016-4f24-9ca7-61125105c6e1.aspx</guid>
      <link>http://www.stevestechspot.com/SOSEXUpdatedV11Available.aspx</link>
      <pubDate>Fri, 15 Feb 2008 04:09:36 GMT</pubDate>
      <description>&lt;p&gt;
I've finally gotten around to updating SOSEX.&amp;#160; I incorporated most of the feedback
I received and I added a couple of other new goodies.&amp;#160; Here's what's new:
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;!vars:&lt;/strong&gt; 
&lt;br /&gt;
Added support for inspecting variables in frames other than the current frame.&amp;#160;
By passing a frame index (eg. !vars 3), you can inspect the variables in any single
frame in the call stack.&amp;#160; By passing the -w switch (!vars -w), the command will
walk the stack all the way up, dumping args/locals for each managed frame.&amp;#160; This
was the number one requested improvement for sosex. 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;!date:&lt;/strong&gt; 
&lt;br /&gt;
New command.&amp;#160; Pass the address of a System.DateTime Value Type and the date will
be displayed in a human readable format (yyyy/mm/dd HH:mm:ss.zzz) 
&lt;br /&gt;
This was another popular feature request. 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;!dlk:&lt;/strong&gt; 
&lt;br /&gt;
Added detection capability for cases where a deadlock is caused by a dead thread holding
a lock. 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;!bpmo/!bpsc:&lt;/strong&gt; 
&lt;br /&gt;
In v1.0, there was a bug that caused only the first instance of a generic method to
receive the breakpoint.&amp;#160; This is now fixed so that all generic instances get
the breakpoint as expected. 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;!isf:&lt;/strong&gt; 
&lt;br /&gt;
Added -c switch to allow viewing of the static variable in the current context only.&amp;#160;
Without the switch, the state of the static field is displayed for all AppDomains/Threads. 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Value Type display:&lt;/strong&gt; 
&lt;br /&gt;
I also improved the display of value types.&amp;#160; When !isf or !vars show a value
type, SOSEX indicates a value type using a &amp;quot;VALUETYPE&amp;quot; indicator along with
a &amp;quot;MT&amp;quot; (method table address) and &amp;quot;ADDR&amp;quot; (value type start address)
indicator to facilitate dumping the data with the SOS!dumpvc command.&amp;#160; This provides
a big advantage over SOS and v1.0 of SOSEX, because they simply display the first
4 bytes of the value type data, with no VT indication or MT info.
&lt;/p&gt;
&lt;p&gt;
As always, feel free to contact me or leave comments to this post with any bug reports
or feature requests.
&lt;/p&gt;
&lt;p&gt;
Enjoy!
&lt;/p&gt;
&lt;p&gt;
&amp;#160;
&lt;/p&gt;
&lt;p&gt;
Download: &lt;a href="/downloads/sosex_32.zip"&gt;x86&lt;/a&gt; | &lt;a href="/downloads/sosex_64.zip"&gt;x64&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.stevestechspot.com/aggbug.ashx?id=c51f1a46-0016-4f24-9ca7-61125105c6e1" /&gt;</description>
      <comments>http://www.stevestechspot.com/CommentView,guid,c51f1a46-0016-4f24-9ca7-61125105c6e1.aspx</comments>
    </item>
    <item>
      <trackback:ping>http://www.stevestechspot.com/Trackback.aspx?guid=db2a3694-9021-4b1b-8555-a0a72843bac3</trackback:ping>
      <pingback:server>http://www.stevestechspot.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.stevestechspot.com/PermaLink,guid,db2a3694-9021-4b1b-8555-a0a72843bac3.aspx</pingback:target>
      <dc:creator>Steve Johnson</dc:creator>
      <wfw:comment>http://www.stevestechspot.com/CommentView,guid,db2a3694-9021-4b1b-8555-a0a72843bac3.aspx</wfw:comment>
      <wfw:commentRss>http://www.stevestechspot.com/SyndicationService.asmx/GetEntryCommentsRss?guid=db2a3694-9021-4b1b-8555-a0a72843bac3</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
One of the top search phrases I get is "Unable to obtain IXCLRDataProcess". 
The reason you're getting this is likely because you are using the !bpsc or !bpmo
extensions before the CLR has been initialized.  If you try to run these extensions
at the initial process breakpoint, they won't work because the runtime has not been
loaded.  I'm hoping to have this corrected for the next release of SOSEX so that
!bpsc and !bpmo are saved and then executed when the runtime has initialized.
</p>
        <img width="0" height="0" src="http://www.stevestechspot.com/aggbug.ashx?id=db2a3694-9021-4b1b-8555-a0a72843bac3" />
      </body>
      <title>SOSEX and the Dreaded &amp;quot;Unable to Obtain IXCLRDataProcess&amp;quot;</title>
      <guid isPermaLink="false">http://www.stevestechspot.com/PermaLink,guid,db2a3694-9021-4b1b-8555-a0a72843bac3.aspx</guid>
      <link>http://www.stevestechspot.com/SOSEXAndTheDreadedQuotUnableToObtainIXCLRDataProcessquot.aspx</link>
      <pubDate>Thu, 16 Aug 2007 12:56:00 GMT</pubDate>
      <description>&lt;p&gt;
One of the top search phrases I get is "Unable to obtain IXCLRDataProcess".&amp;nbsp;
The reason you're getting this is likely because you are using the !bpsc or !bpmo
extensions before the CLR has been initialized.&amp;nbsp; If you try to run these extensions
at the initial process breakpoint, they won't work because the runtime has not been
loaded.&amp;nbsp; I'm hoping to have this corrected for the next release of SOSEX so that
!bpsc and !bpmo are saved and then executed when the runtime has initialized.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.stevestechspot.com/aggbug.ashx?id=db2a3694-9021-4b1b-8555-a0a72843bac3" /&gt;</description>
      <comments>http://www.stevestechspot.com/CommentView,guid,db2a3694-9021-4b1b-8555-a0a72843bac3.aspx</comments>
    </item>
    <item>
      <trackback:ping>http://www.stevestechspot.com/Trackback.aspx?guid=9fdcf4a4-6e09-4807-bc31-ac1adf836f6c</trackback:ping>
      <pingback:server>http://www.stevestechspot.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.stevestechspot.com/PermaLink,guid,9fdcf4a4-6e09-4807-bc31-ac1adf836f6c.aspx</pingback:target>
      <dc:creator>Steve Johnson</dc:creator>
      <wfw:comment>http://www.stevestechspot.com/CommentView,guid,9fdcf4a4-6e09-4807-bc31-ac1adf836f6c.aspx</wfw:comment>
      <wfw:commentRss>http://www.stevestechspot.com/SyndicationService.asmx/GetEntryCommentsRss?guid=9fdcf4a4-6e09-4807-bc31-ac1adf836f6c</wfw:commentRss>
      <slash:comments>20</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Over the course of the last few months, I've really put lots of effort into understanding
and utilizing <a href="http://www.microsoft.com/whdc/devtools/debugging/default.mspx">WinDbg</a>. As
a primarily C# developer, this meant also becoming intimately familiar with the <a href="http://msdn2.microsoft.com/en-us/library/bb190764(vs.80).aspx">SOS</a> extension. Though
a bit tedious, this exercise has already paid rich dividends in my debugging experience.
As powerful and handy as SOS is, however, it has some annoying limitations and quirks. My
personal peeves with SOS, combined with my desire to learn to write a WinDbg extension,
led me to develop SOSEX, a debugging extension for managed code that begins to
alleviate some of my frustrations with SOS. SOSEX (available in <a href="/downloads/sosex_32.zip">x86</a> and <a href="/downloads/sosex_64.zip">x64</a> versions)
provides 8 easy-to-use commands: !dumpgen (dumps the contents of a GC generation),
!gcgen (indicates the GC generation of a given object), !refs (lists all references to
and from the specified object), !bpsc (breakpoint, source code), !bpmo (breakpoint,
method offset), !vars (dump all args and local variables), !isf (inspect static field)
and !dlk (deadlock detection).
</p>
        <p>
The rest of this post will provide a bit more detail about each command and how they
can save you time. Use the !help command for a list of commands and !help &lt;command
name&gt; for the syntax and usage of each command.
</p>
        <p>
 
</p>
        <h5>!dumpgen and !gcgen
</h5>
        <p>
With SOS, you can dump the contents of the heap like so:
</p>
        <p>
          <font face="Courier New" size="1">0:000&gt; !dumpheap -short<br />
00000642787c7370 
<br />
00000642787c7388 
<br />
00000642787c73b0 
<br />
00000642787c7410 
<br />
00000642787c7440 
<br />
00000642787c7498 
<br />
00000642787c74f0...</font>
        </p>
        <p>
The problem with this is that there is no easy way to tell from the output which generation
each object belongs to. You can follow up the call to !dumpheap with !eeheap
-gc, which will provide the necessary information to determine generations. However,
determining the contents of, say, generation 2 using this method is <em>very</em> tedious. Here's
the output of !eeheap -gc for a dual-processor system in server GC mode: 
</p>
        <p>
          <font face="Courier New" size="1">0:000&gt; !eeheap -gc<br />
Number of GC Heaps: 2<br />
------------------------------<br />
Heap 0 (0000000002264180)<br />
generation 0 starts at 0x000000007fff0098<br />
generation 1 starts at 0x000000007fff0080<br />
generation 2 starts at 0x000000007fff0068<br />
ephemeral segment allocation context: none<br />
         segment           
begin         allocated            
size<br />
0000000002271b80 00000642787c7370  0000064278809088 0x0000000000041d18(269592)<br />
000000007fff0000 000000007fff0068  0000000080002fe8 0x0000000000012f80(77696)<br />
Large object heap starts at 0x00000000ffff0068<br />
         segment           
begin         allocated            
size<br />
00000000ffff0000 00000000ffff0068  00000000ffff80c8 0x0000000000008060(32864)<br />
Heap Size           0x5ccf8(380152)<br />
------------------------------<br />
Heap 1 (0000000002264e00)<br />
generation 0 starts at 0x00000000bfff0098<br />
generation 1 starts at 0x00000000bfff0080<br />
generation 2 starts at 0x00000000bfff0068<br />
ephemeral segment allocation context: none<br />
         segment           
begin         allocated            
size<br />
00000000bfff0000 00000000bfff0068  00000000bfff00b0 0x0000000000000048(72)<br />
Large object heap starts at 0x000000010fff0068<br />
         segment           
begin         allocated            
size<br />
000000010fff0000 000000010fff0068  000000010fff0080 0x0000000000000018(24)<br />
Heap Size             
0x60(96)<br />
------------------------------<br />
GC Heap Size           0x5cd58(380248)</font>
        </p>
        <p>
  
</p>
        <p>
As you can see, you have a lot of work to do in order to pick through the output
of !dumpheap and compare object addresses to the segment addresses provided by !eeheap
-gc. Enter SOSEX's !dumpgen command. Using !dumpgen, you can easily determine
the contents of a given generation simply by providing the number of the generation
you wish to examine: 
</p>
        <p>
          <font face="Courier New" size="1">0:000&gt; !dumpgen 2<br />
00000642787c7370         24   
System.Object<br />
00000642787c7388         38   
System.String    STRVAL=length<br />
00000642787c73b0         94   
System.String    STRVAL=ArgumentOutOfRange_MustBeNonNegNum<br />
00000642787c7410         46   
System.String    STRVAL=startIndex<br />
00000642787c7440         84   
System.String    STRVAL=ArgumentOutOfRange_StartIndex<br />
00000642787c7498         86   
System.String    STRVAL=ArgumentOutOfRange_IndexLength<br />
00000642787c74f0         42   
System.String    STRVAL=capacity...</font>
        </p>
        <p>
Conversely, if you know an object's address and you wish to know what generation it
belongs to, you can simply provide the address of the object to the !gcgen command.
</p>
        <p>
 
</p>
        <h5>!refs
</h5>
        <p>
Though not a replacement, the !refs command supplements SOS's !gcroot command by allowing
you to view  the immediate references from and to a given object.
</p>
        <p>
          <font face="Courier New" size="1">0:000&gt; !refs 0000000080000db8<br />
Objects referenced by 0000000080000db8 (System.Threading.Mutex):<br />
0000000080000ef0         32   
Microsoft.Win32.SafeHandles.SafeWaitHandle </font>
        </p>
        <p>
          <font face="Courier New" size="1">Objects referencing 0000000080000db8 (System.Threading.Mutex):<br />
0000000080000e08         72   
System.Threading.Mutex+&lt;&gt;c__DisplayClass3<br />
0000000080000e50         64   
System.Runtime.CompilerServices.RuntimeHelpers+CleanupCode</font>
        </p>
        <p>
The sample output above shows only heap references, but !refs will also list all references
from handles, stacks, registers and the freachable queues.
</p>
        <p>
 
</p>
        <h5>!dlk
</h5>
        <p>
The !dlk command allows you to easily spot deadlocks in your application if you
suspect deadlock to be the cause of an application hang. If !dlk detects deadlock,
the output will list the sync blocks that are held as well as the sync blocks for
which each thread is waiting, as well as the type, method, IL offset, and, if symbols
are available, the source code and line number at which each thread is waiting:
</p>
        <p>
          <font face="Courier New" size="1">0:010&gt; !dlk<br />
Deadlock detected:<br />
CLR thread 4 holds sync block 00000000024c6970 OBJ:000000007fff0f80[System.String]
STRVAL=SYNC1<br />
             waits sync
block 00000000024c6928 OBJ:000000007fff0fa8[System.String] STRVAL=SYNC2<br />
CLR thread 5 holds sync block 00000000024c6928 OBJ:000000007fff0fa8[System.String]
STRVAL=SYNC2<br />
             waits sync
block 00000000024c6970 OBJ:000000007fff0f80[System.String] STRVAL=SYNC1<br />
CLR Thread 4 is waiting at ConsoleTestApp.ConsoleTestApp.MonitorDeadlockThreadProc()+0xa4(IL)
[C:\dev\ConsoleTestApp\ConsoleTestApp.cs, line 195]<br />
CLR Thread 5 is waiting at ConsoleTestApp.ConsoleTestApp.MonitorDeadlockThreadProc()+0xa4(IL)
[C:\dev\ConsoleTestApp\ConsoleTestApp.cs, line 195] </font>
        </p>
        <p>
          <font face="Courier New" size="1">1 deadlock detected.</font>
        </p>
        <p>
As you can see, !dlk makes it dead simple to troubleshoot this common kind of deadlock
in managed code. One important caveat holds true for !dlk: it only works for
deadlocks on "sync blocks". Put more simply, it will only spot locks created
by Monitor.Enter (which is used by the C# <font face="Courier New">lock</font> keyword). !dlk
will not catch deadlock on other types of synchronization objects, such as mutexes
and semaphores. 
</p>
        <p>
  
</p>
        <h5>!bpsc and !bpmo
</h5>
        <p>
Although managed debugging with WinDbg has become more supported in later builds,
it is still difficult to get managed source code breakpoints to work correctly. With
the !bpsc command, it is now simple to set source code breakpoints. !bpsc allows
you to set a breakpoint in a source code file at a specified line number and, optionally,
column number. I've often wanted to stop the execution of my application either
deep inside a method in the BCL or in one of my own methods in a build for which I
have no symbols. Though SOS provides the handy !bpmd command, !bpmd only allows
you to set a breakpoint on the first instruction of a method. This is often not
effective for more difficult debugging scenarios. The !bpmo command now provides
a means for you to set a breakpoint at specific IL offset within a given type and method.  
</p>
        <p>
  
</p>
        <h5>!vars and !isf
</h5>
        <p>
Once you are stopped at a breakpoint, you need an easy means to inspect the contents
of method arguments, local variables and instance and static fields. !vars dumps
the values of arguments and local variables. If symbols are available, !vars
will display the names of the local variables. Names of arguments are (with rare
exception) provided even without symbols. In order to inspect member variables,
first call !vars and then provide the value of "this" to the sos!do command. Using
SOS, it is a bit of a cumbersome process to view the contents of static fields. The
!isf command makes it simple by allowing you to simply specify the type and field
name to inspect. 
</p>
        <p>
I hope you enjoy using SOSEX as much as I have enjoyed writing it. Please provide
bug reports and feature requests either in the comments for this post or via the "email"
link on my <a href="http://www.stevestechspot.com/">home page</a>. I owe many thanks
to <a href="http://www.wintellect.com/cs/blogs/jrobbins/default.aspx">John Robbins</a>,
who provided some key feature ideas for SOSEX as well as some valuable testing time. 
John has also written a <a href="http://www.wintellect.com/cs/blogs/jrobbins/archive/2007/06/19/great-sosex-a-phenomenal-net-debugging-extension-to-see-the-hard-stuff-steve-johnson-is-my-hero.aspx">nice
blog post</a> describing how he uses SOSEX in his own debugging.  Thanks, John! 
</p>
        <p>
Download: <a href="/downloads/sosex_32.zip">x86</a> | <a href="/downloads/sosex_64.zip">x64</a></p>
        <img width="0" height="0" src="http://www.stevestechspot.com/aggbug.ashx?id=9fdcf4a4-6e09-4807-bc31-ac1adf836f6c" />
      </body>
      <title>SOSEX - A New Debugging Extension for Managed Code</title>
      <guid isPermaLink="false">http://www.stevestechspot.com/PermaLink,guid,9fdcf4a4-6e09-4807-bc31-ac1adf836f6c.aspx</guid>
      <link>http://www.stevestechspot.com/SOSEXANewDebuggingExtensionForManagedCode.aspx</link>
      <pubDate>Tue, 19 Jun 2007 03:08:25 GMT</pubDate>
      <description>&lt;p&gt;
Over the course of the last few months, I've really put lots of effort into understanding
and utilizing &lt;a href="http://www.microsoft.com/whdc/devtools/debugging/default.mspx"&gt;WinDbg&lt;/a&gt;.&amp;nbsp;As
a primarily C# developer, this meant also&amp;nbsp;becoming intimately familiar with the &lt;a href="http://msdn2.microsoft.com/en-us/library/bb190764(vs.80).aspx"&gt;SOS&lt;/a&gt; extension.&amp;nbsp;Though
a bit tedious, this exercise has already paid rich dividends in my debugging experience.
As powerful and handy as SOS is, however, it has some annoying limitations and quirks.&amp;nbsp;My
personal peeves with SOS, combined with my desire to learn to write a WinDbg extension,
led me to develop SOSEX, a&amp;nbsp;debugging extension for managed code that begins to
alleviate some of my frustrations with SOS. SOSEX&amp;nbsp;(available in &lt;a href="/downloads/sosex_32.zip"&gt;x86&lt;/a&gt;&amp;nbsp;and &lt;a href="/downloads/sosex_64.zip"&gt;x64&lt;/a&gt;&amp;nbsp;versions)
provides 8 easy-to-use commands: !dumpgen (dumps the contents of a GC generation),
!gcgen (indicates the GC&amp;nbsp;generation of a given object), !refs (lists all references&amp;nbsp;to
and&amp;nbsp;from the specified object), !bpsc (breakpoint, source code), !bpmo (breakpoint,
method offset), !vars (dump all args and local variables), !isf (inspect static field)
and !dlk (deadlock detection).
&lt;/p&gt;
&lt;p&gt;
The rest of this post will provide a bit more detail about each command and how they
can save you time. Use the !help command for a list of commands and !help &amp;lt;command
name&amp;gt; for the syntax and usage of each command.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;h5&gt;!dumpgen and !gcgen
&lt;/h5&gt;
&lt;p&gt;
With SOS, you can dump the contents of the heap like so:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New" size="1"&gt;0:000&amp;gt; !dumpheap -short&lt;br&gt;
00000642787c7370 
&lt;br&gt;
00000642787c7388 
&lt;br&gt;
00000642787c73b0 
&lt;br&gt;
00000642787c7410 
&lt;br&gt;
00000642787c7440 
&lt;br&gt;
00000642787c7498 
&lt;br&gt;
00000642787c74f0...&lt;/font&gt; 
&lt;p&gt;
The problem with this is that there is no easy way to tell from the output which generation
each object belongs to.&amp;nbsp;You can follow up the call to !dumpheap with !eeheap
-gc, which will provide the necessary information to determine generations.&amp;nbsp;However,
determining the contents of, say, generation 2 using this method is &lt;em&gt;very&lt;/em&gt; tedious.&amp;nbsp;Here's
the output of !eeheap -gc&amp;nbsp;for a dual-processor system in server GC mode: 
&lt;p&gt;
&lt;font face="Courier New" size="1"&gt;0:000&amp;gt; !eeheap -gc&lt;br&gt;
Number of GC Heaps: 2&lt;br&gt;
------------------------------&lt;br&gt;
Heap 0 (0000000002264180)&lt;br&gt;
generation 0 starts at 0x000000007fff0098&lt;br&gt;
generation 1 starts at 0x000000007fff0080&lt;br&gt;
generation 2 starts at 0x000000007fff0068&lt;br&gt;
ephemeral segment allocation context: none&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; segment&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
begin&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; allocated&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
size&lt;br&gt;
0000000002271b80 00000642787c7370&amp;nbsp; 0000064278809088 0x0000000000041d18(269592)&lt;br&gt;
000000007fff0000 000000007fff0068&amp;nbsp; 0000000080002fe8 0x0000000000012f80(77696)&lt;br&gt;
Large object heap starts at 0x00000000ffff0068&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; segment&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
begin&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; allocated&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
size&lt;br&gt;
00000000ffff0000 00000000ffff0068&amp;nbsp; 00000000ffff80c8 0x0000000000008060(32864)&lt;br&gt;
Heap Size&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x5ccf8(380152)&lt;br&gt;
------------------------------&lt;br&gt;
Heap 1 (0000000002264e00)&lt;br&gt;
generation 0 starts at 0x00000000bfff0098&lt;br&gt;
generation 1 starts at 0x00000000bfff0080&lt;br&gt;
generation 2 starts at 0x00000000bfff0068&lt;br&gt;
ephemeral segment allocation context: none&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; segment&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
begin&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; allocated&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
size&lt;br&gt;
00000000bfff0000 00000000bfff0068&amp;nbsp; 00000000bfff00b0 0x0000000000000048(72)&lt;br&gt;
Large object heap starts at 0x000000010fff0068&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; segment&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
begin&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; allocated&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
size&lt;br&gt;
000000010fff0000 000000010fff0068&amp;nbsp; 000000010fff0080 0x0000000000000018(24)&lt;br&gt;
Heap Size&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
0x60(96)&lt;br&gt;
------------------------------&lt;br&gt;
GC Heap Size&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x5cd58(380248)&lt;/font&gt; 
&lt;p&gt;
&amp;nbsp; 
&lt;p&gt;
As you can see, you have a lot of work to do in order to pick through the&amp;nbsp;output
of !dumpheap and compare object addresses to the segment addresses provided by !eeheap
-gc.&amp;nbsp;Enter SOSEX's !dumpgen command.&amp;nbsp;Using !dumpgen, you can easily determine
the contents of a given generation simply by providing the number of the generation
you wish to examine: 
&lt;p&gt;
&lt;font face="Courier New" size="1"&gt;0:000&amp;gt; !dumpgen 2&lt;br&gt;
00000642787c7370&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 24&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.Object&lt;br&gt;
00000642787c7388&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 38&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.String&amp;nbsp;&amp;nbsp;&amp;nbsp; STRVAL=length&lt;br&gt;
00000642787c73b0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 94&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.String&amp;nbsp;&amp;nbsp;&amp;nbsp; STRVAL=ArgumentOutOfRange_MustBeNonNegNum&lt;br&gt;
00000642787c7410&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 46&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.String&amp;nbsp;&amp;nbsp;&amp;nbsp; STRVAL=startIndex&lt;br&gt;
00000642787c7440&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 84&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.String&amp;nbsp;&amp;nbsp;&amp;nbsp; STRVAL=ArgumentOutOfRange_StartIndex&lt;br&gt;
00000642787c7498&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 86&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.String&amp;nbsp;&amp;nbsp;&amp;nbsp; STRVAL=ArgumentOutOfRange_IndexLength&lt;br&gt;
00000642787c74f0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 42&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.String&amp;nbsp;&amp;nbsp;&amp;nbsp; STRVAL=capacity...&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Conversely, if you know an object's address and you wish to know what generation it
belongs to, you can simply provide the address of the object to the&amp;nbsp;!gcgen command.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;h5&gt;!refs
&lt;/h5&gt;
&lt;p&gt;
Though not a replacement, the !refs command supplements SOS's !gcroot command by allowing
you to view&amp;nbsp; the immediate references from and to a given object.
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New" size="1"&gt;0:000&amp;gt; !refs 0000000080000db8&lt;br&gt;
Objects referenced by 0000000080000db8 (System.Threading.Mutex):&lt;br&gt;
0000000080000ef0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 32&amp;nbsp;&amp;nbsp;&amp;nbsp;
Microsoft.Win32.SafeHandles.SafeWaitHandle &lt;/font&gt; 
&lt;p&gt;
&lt;font face="Courier New" size="1"&gt;Objects referencing 0000000080000db8 (System.Threading.Mutex):&lt;br&gt;
0000000080000e08&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 72&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.Threading.Mutex+&amp;lt;&amp;gt;c__DisplayClass3&lt;br&gt;
0000000080000e50&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 64&amp;nbsp;&amp;nbsp;&amp;nbsp;
System.Runtime.CompilerServices.RuntimeHelpers+CleanupCode&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
The sample output above shows only heap references, but !refs will also list all references
from handles, stacks, registers and the freachable queues.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;h5&gt;!dlk
&lt;/h5&gt;
&lt;p&gt;
The !dlk command&amp;nbsp;allows you to easily spot deadlocks in your application if you
suspect deadlock to be the cause of an application hang.&amp;nbsp;If !dlk detects deadlock,
the output will list the sync blocks that are held as well as the sync blocks for
which each thread is waiting, as well as the type, method, IL offset, and, if symbols
are available, the source code and line number at which each thread is waiting:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New" size="1"&gt;0:010&amp;gt; !dlk&lt;br&gt;
Deadlock detected:&lt;br&gt;
CLR thread 4 holds sync block 00000000024c6970 OBJ:000000007fff0f80[System.String]
STRVAL=SYNC1&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; waits sync
block 00000000024c6928 OBJ:000000007fff0fa8[System.String] STRVAL=SYNC2&lt;br&gt;
CLR thread 5 holds sync block 00000000024c6928 OBJ:000000007fff0fa8[System.String]
STRVAL=SYNC2&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; waits sync
block 00000000024c6970 OBJ:000000007fff0f80[System.String] STRVAL=SYNC1&lt;br&gt;
CLR Thread 4 is waiting at ConsoleTestApp.ConsoleTestApp.MonitorDeadlockThreadProc()+0xa4(IL)
[C:\dev\ConsoleTestApp\ConsoleTestApp.cs, line 195]&lt;br&gt;
CLR Thread 5 is waiting at ConsoleTestApp.ConsoleTestApp.MonitorDeadlockThreadProc()+0xa4(IL)
[C:\dev\ConsoleTestApp\ConsoleTestApp.cs, line 195] &lt;/font&gt; 
&lt;p&gt;
&lt;font face="Courier New" size="1"&gt;1 deadlock detected.&lt;/font&gt; 
&lt;p&gt;
As you can see, !dlk makes it dead simple to troubleshoot this common kind of deadlock
in managed code.&amp;nbsp;One important caveat holds true for !dlk: it only works for
deadlocks on "sync blocks".&amp;nbsp;Put more simply, it will only spot locks created
by Monitor.Enter (which is used by the C# &lt;font face="Courier New"&gt;lock&lt;/font&gt; keyword).&amp;nbsp;!dlk
will not catch deadlock on other types of synchronization objects, such as mutexes
and semaphores. 
&lt;p&gt;
&amp;nbsp; 
&lt;h5&gt;!bpsc and !bpmo
&lt;/h5&gt;
&lt;p&gt;
Although managed debugging with WinDbg has become more supported in later builds,
it is still difficult to get managed source code breakpoints to work correctly.&amp;nbsp;With
the !bpsc command, it is now simple to set source code&amp;nbsp;breakpoints.&amp;nbsp;!bpsc&amp;nbsp;allows
you to set a breakpoint in a source code file at a specified line number and, optionally,
column number.&amp;nbsp;I've often wanted to stop the execution of my application either
deep inside a method in the BCL or in one of my own methods in a build for which I
have no symbols.&amp;nbsp;Though SOS provides the handy !bpmd command, !bpmd only allows
you to set a breakpoint on the first instruction of a method.&amp;nbsp;This is often not
effective for more difficult debugging scenarios.&amp;nbsp;The !bpmo command now provides
a means for you to set a breakpoint at specific IL offset within a given type and&amp;nbsp;method.&amp;nbsp; 
&lt;p&gt;
&amp;nbsp; 
&lt;h5&gt;!vars and !isf
&lt;/h5&gt;
&lt;p&gt;
Once you are stopped at a breakpoint, you need an easy means to inspect the contents
of method arguments, local variables and instance and static fields.&amp;nbsp;!vars dumps
the&amp;nbsp;values of arguments and local variables.&amp;nbsp;If symbols are available, !vars
will display the names of the local variables.&amp;nbsp;Names of arguments are (with rare
exception) provided even without symbols.&amp;nbsp;In order to inspect member variables,
first call !vars and then provide the value of "this" to the sos!do command.&amp;nbsp;Using
SOS, it is a bit of a cumbersome process to&amp;nbsp;view the contents of static fields.&amp;nbsp;The
!isf command makes it simple by allowing you to simply specify the type and field
name to inspect. 
&lt;p&gt;
I hope you enjoy using SOSEX as much as I have enjoyed writing it.&amp;nbsp;Please provide
bug reports and feature requests either in the comments for this post or via the "email"
link on my &lt;a href="http://www.stevestechspot.com/"&gt;home page&lt;/a&gt;. I owe many thanks
to &lt;a href="http://www.wintellect.com/cs/blogs/jrobbins/default.aspx"&gt;John Robbins&lt;/a&gt;,
who provided some key feature ideas for SOSEX as well as some valuable testing time.&amp;nbsp;
John has also written a &lt;a href="http://www.wintellect.com/cs/blogs/jrobbins/archive/2007/06/19/great-sosex-a-phenomenal-net-debugging-extension-to-see-the-hard-stuff-steve-johnson-is-my-hero.aspx"&gt;nice
blog post&lt;/a&gt; describing how he uses SOSEX in his own debugging.&amp;nbsp; Thanks, John! 
&lt;p&gt;
Download: &lt;a href="/downloads/sosex_32.zip"&gt;x86&lt;/a&gt;&amp;nbsp;| &lt;a href="/downloads/sosex_64.zip"&gt;x64&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.stevestechspot.com/aggbug.ashx?id=9fdcf4a4-6e09-4807-bc31-ac1adf836f6c" /&gt;</description>
      <comments>http://www.stevestechspot.com/CommentView,guid,9fdcf4a4-6e09-4807-bc31-ac1adf836f6c.aspx</comments>
    </item>
    <item>
      <trackback:ping>http://www.stevestechspot.com/Trackback.aspx?guid=abf86797-5d26-472d-a736-0691fbc2de57</trackback:ping>
      <pingback:server>http://www.stevestechspot.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.stevestechspot.com/PermaLink,guid,abf86797-5d26-472d-a736-0691fbc2de57.aspx</pingback:target>
      <dc:creator>Steve Johnson</dc:creator>
      <wfw:comment>http://www.stevestechspot.com/CommentView,guid,abf86797-5d26-472d-a736-0691fbc2de57.aspx</wfw:comment>
      <wfw:commentRss>http://www.stevestechspot.com/SyndicationService.asmx/GetEntryCommentsRss?guid=abf86797-5d26-472d-a736-0691fbc2de57</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I just switched over to dasBlog and Windows Live Writer.  This is just a test
drive.
</p>
        <img width="0" height="0" src="http://www.stevestechspot.com/aggbug.ashx?id=abf86797-5d26-472d-a736-0691fbc2de57" />
      </body>
      <title>Test Drive</title>
      <guid isPermaLink="false">http://www.stevestechspot.com/PermaLink,guid,abf86797-5d26-472d-a736-0691fbc2de57.aspx</guid>
      <link>http://www.stevestechspot.com/TestDrive.aspx</link>
      <pubDate>Sun, 17 Jun 2007 00:38:20 GMT</pubDate>
      <description>&lt;p&gt;
I just switched over to dasBlog and Windows Live Writer.&amp;nbsp; This is just a test
drive.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.stevestechspot.com/aggbug.ashx?id=abf86797-5d26-472d-a736-0691fbc2de57" /&gt;</description>
      <comments>http://www.stevestechspot.com/CommentView,guid,abf86797-5d26-472d-a736-0691fbc2de57.aspx</comments>
    </item>
    <item>
      <trackback:ping>http://www.stevestechspot.com/Trackback.aspx?guid=102168a1-4d15-4a8f-bcc0-eee289e48c80</trackback:ping>
      <pingback:server>http://www.stevestechspot.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.stevestechspot.com/PermaLink,guid,102168a1-4d15-4a8f-bcc0-eee289e48c80.aspx</pingback:target>
      <dc:creator>Steve Johnson</dc:creator>
      <wfw:comment>http://www.stevestechspot.com/CommentView,guid,102168a1-4d15-4a8f-bcc0-eee289e48c80.aspx</wfw:comment>
      <wfw:commentRss>http://www.stevestechspot.com/SyndicationService.asmx/GetEntryCommentsRss?guid=102168a1-4d15-4a8f-bcc0-eee289e48c80</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
HttpConfig has been updated to work correctly with UAC on Vista.
</p>
        <p />
        <p>
Roger Lipscombe also pointed out some NullReferenceExceptions, which are also now
fixed. Thanks, Roger!
</p>
        <p />
        <p>
Download: <a href="/downloads/httpconfig.zip">exe</a><a href="/downloads/httpconfig_source.zip">source</a></p>
        <img width="0" height="0" src="http://www.stevestechspot.com/aggbug.ashx?id=102168a1-4d15-4a8f-bcc0-eee289e48c80" />
      </body>
      <title>HttpConfig Now Works Properly With UAC</title>
      <guid isPermaLink="false">http://www.stevestechspot.com/PermaLink,guid,102168a1-4d15-4a8f-bcc0-eee289e48c80.aspx</guid>
      <link>http://www.stevestechspot.com/HttpConfigNowWorksProperlyWithUAC.aspx</link>
      <pubDate>Wed, 13 Jun 2007 06:00:00 GMT</pubDate>
      <description>
		&lt;p&gt;
HttpConfig has been updated to work correctly with UAC on Vista.
&lt;/p&gt;
&lt;p /&gt;
&lt;p&gt;
Roger Lipscombe also pointed out some NullReferenceExceptions, which are also now
fixed. Thanks, Roger!
&lt;/p&gt;
&lt;p /&gt;
&lt;p&gt;
Download: &lt;a href="/downloads/httpconfig.zip"&gt;exe&lt;/a&gt; &lt;a href="/downloads/httpconfig_source.zip"&gt;source&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.stevestechspot.com/aggbug.ashx?id=102168a1-4d15-4a8f-bcc0-eee289e48c80" /&gt;</description>
      <comments>http://www.stevestechspot.com/CommentView,guid,102168a1-4d15-4a8f-bcc0-eee289e48c80.aspx</comments>
      <category>AllContent</category>
    </item>
    <item>
      <trackback:ping>http://www.stevestechspot.com/Trackback.aspx?guid=d84ac549-a40f-475c-b46f-dfda25fe82d9</trackback:ping>
      <pingback:server>http://www.stevestechspot.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.stevestechspot.com/PermaLink,guid,d84ac549-a40f-475c-b46f-dfda25fe82d9.aspx</pingback:target>
      <dc:creator>Steve Johnson</dc:creator>
      <wfw:comment>http://www.stevestechspot.com/CommentView,guid,d84ac549-a40f-475c-b46f-dfda25fe82d9.aspx</wfw:comment>
      <wfw:commentRss>http://www.stevestechspot.com/SyndicationService.asmx/GetEntryCommentsRss?guid=d84ac549-a40f-475c-b46f-dfda25fe82d9</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I've updated HttpConfig to fix a couple of 64-bit bugs.
</p>
        <p />
        <p>
Download: <a href="/downloads/httpconfig.zip">exe</a><a href="/downloads/httpconfig_source.zip">source</a></p>
        <img width="0" height="0" src="http://www.stevestechspot.com/aggbug.ashx?id=d84ac549-a40f-475c-b46f-dfda25fe82d9" />
      </body>
      <title>HttpConfig Bug Fixes for 64-bit</title>
      <guid isPermaLink="false">http://www.stevestechspot.com/PermaLink,guid,d84ac549-a40f-475c-b46f-dfda25fe82d9.aspx</guid>
      <link>http://www.stevestechspot.com/HttpConfigBugFixesFor64bit.aspx</link>
      <pubDate>Wed, 30 May 2007 06:00:00 GMT</pubDate>
      <description>
		&lt;p&gt;
I've updated HttpConfig to fix a couple of 64-bit bugs.
&lt;/p&gt;
&lt;p /&gt;
&lt;p&gt;
Download: &lt;a href="/downloads/httpconfig.zip"&gt;exe&lt;/a&gt; &lt;a href="/downloads/httpconfig_source.zip"&gt;source&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.stevestechspot.com/aggbug.ashx?id=d84ac549-a40f-475c-b46f-dfda25fe82d9" /&gt;</description>
      <comments>http://www.stevestechspot.com/CommentView,guid,d84ac549-a40f-475c-b46f-dfda25fe82d9.aspx</comments>
      <category>AllContent</category>
    </item>
    <item>
      <trackback:ping>http://www.stevestechspot.com/Trackback.aspx?guid=50d9c991-19d7-4dd8-9ede-7c179fbef7cd</trackback:ping>
      <pingback:server>http://www.stevestechspot.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.stevestechspot.com/PermaLink,guid,50d9c991-19d7-4dd8-9ede-7c179fbef7cd.aspx</pingback:target>
      <dc:creator>Steve Johnson</dc:creator>
      <wfw:comment>http://www.stevestechspot.com/CommentView,guid,50d9c991-19d7-4dd8-9ede-7c179fbef7cd.aspx</wfw:comment>
      <wfw:commentRss>http://www.stevestechspot.com/SyndicationService.asmx/GetEntryCommentsRss?guid=50d9c991-19d7-4dd8-9ede-7c179fbef7cd</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
At long last, I've been able to update the HttpConfig GUI tool. I've fixed many bugs,
streamlined the UI, added graphical security editing and gotten the thing to run on
Vista.
</p>
        <p>
Thanks to <a href="http://www.pluralsight.com/blogs/keith/">Keith</a> and <a href="http://www.leastprivilege.com">Dominick</a> for
the inspiration to enhance the security stuff. Now that I'm using .NET 2.0 for this
app, I was able to get the EditSecurity API working purely in C#.
</p>
Enjoy! 
<p>
Download: <a href="/downloads/httpconfig.zip">exe</a> <a href="/downloads/httpconfig_source.zip">source</a></p><img width="0" height="0" src="http://www.stevestechspot.com/aggbug.ashx?id=50d9c991-19d7-4dd8-9ede-7c179fbef7cd" /></body>
      <title>HttpConfig Update</title>
      <guid isPermaLink="false">http://www.stevestechspot.com/PermaLink,guid,50d9c991-19d7-4dd8-9ede-7c179fbef7cd.aspx</guid>
      <link>http://www.stevestechspot.com/HttpConfigUpdate.aspx</link>
      <pubDate>Tue, 05 Dec 2006 06:00:00 GMT</pubDate>
      <description>
		&lt;p&gt;
At long last, I've been able to update the HttpConfig GUI tool. I've fixed many bugs,
streamlined the UI, added graphical security editing and gotten the thing to run on
Vista.
&lt;/p&gt;
&lt;p&gt;
Thanks to &lt;a href="http://www.pluralsight.com/blogs/keith/"&gt;Keith&lt;/a&gt; and &lt;a href="http://www.leastprivilege.com"&gt;Dominick&lt;/a&gt; for
the inspiration to enhance the security stuff. Now that I'm using .NET 2.0 for this
app, I was able to get the EditSecurity API working purely in C#.
&lt;/p&gt;
Enjoy! 
&lt;p&gt;
Download:&amp;nbsp;&lt;a href="/downloads/httpconfig.zip"&gt;exe&lt;/a&gt;&amp;nbsp;&lt;a href="/downloads/httpconfig_source.zip"&gt;source&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.stevestechspot.com/aggbug.ashx?id=50d9c991-19d7-4dd8-9ede-7c179fbef7cd" /&gt;</description>
      <comments>http://www.stevestechspot.com/CommentView,guid,50d9c991-19d7-4dd8-9ede-7c179fbef7cd.aspx</comments>
      <category>AllContent</category>
    </item>
    <item>
      <trackback:ping>http://www.stevestechspot.com/Trackback.aspx?guid=9e9c347f-da37-4997-969b-015bc560a4a7</trackback:ping>
      <pingback:server>http://www.stevestechspot.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.stevestechspot.com/PermaLink,guid,9e9c347f-da37-4997-969b-015bc560a4a7.aspx</pingback:target>
      <dc:creator>Steve Johnson</dc:creator>
      <wfw:comment>http://www.stevestechspot.com/CommentView,guid,9e9c347f-da37-4997-969b-015bc560a4a7.aspx</wfw:comment>
      <wfw:commentRss>http://www.stevestechspot.com/SyndicationService.asmx/GetEntryCommentsRss?guid=9e9c347f-da37-4997-969b-015bc560a4a7</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
As indicated in my last post, I'm posting a wrap-up to the <a href="http://www.stevestechspot.com/default.aspx?articleId=3f39efbd09e24beb9d5ae37ad2fb3862">SSL
cert saga</a>. Unfortunately, I've waited too long between posts and forgotten some
of what I had intended to write here. However, since I included more details in the
last post than I had intended, you're not missing much.
</p>
        <p>
One of the more interesting tasks involved in researching SSL cert problems was how
to locate the key containers. The manner in which key containers are persisted is
not documented anywhere that I know of, and I'm sure that's intentional as key container
persistence is an internal implementation detail. I knew from some work several years
ago that the MS RSA providers persist the key containers in the file system. I also
remembered the approximate location, but I couldn't remember all the details. I fired
up filemon and my memory was refreshed. The keys are stored in the common or user
profile, depending on whether the container is a machine or user keyset. However,
the containers are named in some bizarre guidish/hashy-looking format, so it's not
obvious at a glance which files belong to which key containers. I was able to locate
older key containers by opening them in TextPad because the name of the container
is embedded in ASCII text within the file itself. New containers were easy to locate
simply by sorting the files. However, I wanted to know how the filenames are derived.
I have a sick mind that way. I always want to know how things work behind the scenes.
After a few hours with FileMon, RegMon and the disassembler, I finally think I understand
how these filenames are derived. I'm going to document this process here for the curious
and so I can find this information the next time I need it. This information is applicable
to Win2K, WinXP and Win2K3. I don't yet have a Vista box to test this on, so I don't
know if it remains the same in that version of the OS.
</p>
        <p>
First of all, the key containers are persisted in the following locations:<br />
User keys: %PROFILE%\Application Data\Microsoft\Crypto\RSA\[SID string]<br />
Machine keys: %ALLUSERS%\Application Data\Microsoft\Crypto\RSA\MachineKeys
</p>
        <p>
The filenames look like so: d99e964c16600b1681cdfbad2d5d5eac_2f896382-3658-492e-9219-ce847feb6b8a
</p>
        <p>
The filename consists of a MD5-derived prefix and the MachineGuid, separated by an
underscore. The MachineGuid is a registry string value, located under the key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography".
The hash prefix is derived by performing the following operations:
</p>
        <p>
1 - Obtain the name of the key container. The private key container name for a cert
can be obtained via the CertGetCertificateContextProperty API, specifying the CERT_KEY_PROV_INFO_PROP_ID
property. You can also obtain the key container name by using the <a href="/downloads/checkcert.zip">checkcert
utility</a> from my last post.<br />
2 - Convert the key container name to lower case.<br />
3 - Append a null character<br />
4 - Convert the string to ASCII bytes<br />
5 - Perform an MD5 hash of the ASCII bytes<br />
6 - Treat each 4 byte block of the hash as a 32-bit integer, reversing each<br />
7 - Convert the resulting bytes to a hex string<br /></p>
        <p>
I'm including a sample class that demonstrates the code necessary to calculate the
full path and filename of an RSA key container. The class exposes a static method
called "GetRsaKeyContainerFilename" as well as methods that will allow you
to perform each step of this operation separately.
</p>
        <p>
There may be an API to do this, but I haven't been able to find it. I wasn't as concerned
with an easy way to do this as much as understanding the process, anyway.
</p>
        <p>
Download: <a href="/downloads/RsaUtil.zip">RsaUtil.zip</a></p>
        <img width="0" height="0" src="http://www.stevestechspot.com/aggbug.ashx?id=9e9c347f-da37-4997-969b-015bc560a4a7" />
      </body>
      <title>SSL Certificates - Wrap-up</title>
      <guid isPermaLink="false">http://www.stevestechspot.com/PermaLink,guid,9e9c347f-da37-4997-969b-015bc560a4a7.aspx</guid>
      <link>http://www.stevestechspot.com/SSLCertificatesWrapup.aspx</link>
      <pubDate>Sun, 20 Nov 2005 06:00:00 GMT</pubDate>
      <description>
		&lt;p&gt;
As indicated in my last post, I'm posting a wrap-up to the &lt;a href="http://www.stevestechspot.com/default.aspx?articleId=3f39efbd09e24beb9d5ae37ad2fb3862"&gt;SSL
cert saga&lt;/a&gt;. Unfortunately, I've waited too long between posts and forgotten some
of what I had intended to write here. However, since I included more details in the
last post than I had intended, you're not missing much.
&lt;/p&gt;
&lt;p&gt;
One of the more interesting tasks involved in researching SSL cert problems was how
to locate the key containers. The manner in which key containers are persisted is
not documented anywhere that I know of, and I'm sure that's intentional as key container
persistence is an internal implementation detail. I knew from some work several years
ago that the MS RSA providers persist the key containers in the file system. I also
remembered the approximate location, but I couldn't remember all the details. I fired
up filemon and my memory was refreshed. The keys are stored in the common or user
profile, depending on whether the container is a machine or user keyset. However,
the containers are named in some bizarre guidish/hashy-looking format, so it's not
obvious at a glance which files belong to which key containers. I was able to locate
older key containers by opening them in TextPad because the name of the container
is embedded in ASCII text within the file itself. New containers were easy to locate
simply by sorting the files. However, I wanted to know how the filenames are derived.
I have a sick mind that way. I always want to know how things work behind the scenes.
After a few hours with FileMon, RegMon and the disassembler, I finally think I understand
how these filenames are derived. I'm going to document this process here for the curious
and so I can find this information the next time I need it. This information is applicable
to Win2K, WinXP and Win2K3. I don't yet have a Vista box to test this on, so I don't
know if it remains the same in that version of the OS.
&lt;/p&gt;
&lt;p&gt;
First of all, the key containers are persisted in the following locations:&lt;br /&gt;
User keys: %PROFILE%\Application Data\Microsoft\Crypto\RSA\[SID string]&lt;br /&gt;
Machine keys: %ALLUSERS%\Application Data\Microsoft\Crypto\RSA\MachineKeys
&lt;/p&gt;
&lt;p&gt;
The filenames look like so: d99e964c16600b1681cdfbad2d5d5eac_2f896382-3658-492e-9219-ce847feb6b8a
&lt;/p&gt;
&lt;p&gt;
The filename consists of a MD5-derived prefix and the MachineGuid, separated by an
underscore. The MachineGuid is a registry string value, located under the key &amp;quot;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography&amp;quot;.
The hash prefix is derived by performing the following operations:
&lt;/p&gt;
&lt;p&gt;
1 - Obtain the name of the key container. The private key container name for a cert
can be obtained via the CertGetCertificateContextProperty API, specifying the CERT_KEY_PROV_INFO_PROP_ID
property. You can also obtain the key container name by using the &lt;a href="/downloads/checkcert.zip"&gt;checkcert
utility&lt;/a&gt; from my last post.&lt;br /&gt;
2 - Convert the key container name to lower case.&lt;br /&gt;
3 - Append a null character&lt;br /&gt;
4 - Convert the string to ASCII bytes&lt;br /&gt;
5 - Perform an MD5 hash of the ASCII bytes&lt;br /&gt;
6 - Treat each 4 byte block of the hash as a 32-bit integer, reversing each&lt;br /&gt;
7 - Convert the resulting bytes to a hex string&lt;br /&gt;
&lt;p&gt;
I'm including a sample class that demonstrates the code necessary to calculate the
full path and filename of an RSA key container. The class exposes a static method
called &amp;quot;GetRsaKeyContainerFilename&amp;quot; as well as methods that will allow you
to perform each step of this operation separately.
&lt;/p&gt;
&lt;p&gt;
There may be an API to do this, but I haven't been able to find it. I wasn't as concerned
with an easy way to do this as much as understanding the process, anyway.
&lt;/p&gt;
&lt;p&gt;
Download: &lt;a href="/downloads/RsaUtil.zip"&gt;RsaUtil.zip&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.stevestechspot.com/aggbug.ashx?id=9e9c347f-da37-4997-969b-015bc560a4a7" /&gt;</description>
      <comments>http://www.stevestechspot.com/CommentView,guid,9e9c347f-da37-4997-969b-015bc560a4a7.aspx</comments>
      <category>AllContent</category>
    </item>
    <item>
      <trackback:ping>http://www.stevestechspot.com/Trackback.aspx?guid=3f39efbd-09e2-4beb-9d5a-e37ad2fb3862</trackback:ping>
      <pingback:server>http://www.stevestechspot.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.stevestechspot.com/PermaLink,guid,3f39efbd-09e2-4beb-9d5a-e37ad2fb3862.aspx</pingback:target>
      <dc:creator>Steve Johnson</dc:creator>
      <wfw:comment>http://www.stevestechspot.com/CommentView,guid,3f39efbd-09e2-4beb-9d5a-e37ad2fb3862.aspx</wfw:comment>
      <wfw:commentRss>http://www.stevestechspot.com/SyndicationService.asmx/GetEntryCommentsRss?guid=3f39efbd-09e2-4beb-9d5a-e37ad2fb3862</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
One of the joys Ive experienced in my recent dealings with the HTTP API and some lower-level
SChannel code is that of trying to generate proper SSL test certificates. During the
initial development phase of the product Im currently working on, we used one common
test certificate for all our test/dev servers. Later on, we began to generate different
certificates for each server so that we could test some cert verification code and
also verify that we knew exactly what was required of certificates to work with our
product. Needless to say (or I wouldnt have anything to write here), we immediately
began to have many problems. Some servers worked just fine, while others failed. On
the failing servers, test requests with WebRequest yielded the familiar but unhelpful
error "Could not establish secure channel for SSL/TLS". Attempts to connect from IE
produced the error "Cannot find server or DNS Error". In order to further troubleshoot,
I tried making a connection using a plain SChannel-based SSL socket. The connection
was established just fine and the client socket sent the hello message. As soon as
the client socket attempted to read the server response, an exception was thrown,
indicating that the connection had been closed by the server. Next, I enabled full
SChannel logging on the server and restarted. Attempts to connect left 2 messages
in the event logs: "Creating an SSL server credential", followed by "The SSL server
credentials private key has the following properties..." and NO error. Baffled, I
installed Microsofts <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=cabea1d0-5a10-41bc-83d4-06c814265282&amp;displaylang=en">SSL
Diagnostics</a> utility and attempted a handshake simulation. This yielded the error
"Unexpected error receiving data (0x80090304)", which error code is defined as SEC_E_INTERNAL_ERROR;
again, a most unhelpful description. This led me on a week-long study of X.509 certificates,
makecert.exe and the MS Crypto Providers key container implementation. Im going to
omit many details here in order to get to the point, which is to enumerate the problems
and solutions Ive found for our situation. Ill follow up with another post to describe
the gory details of this research in some depth. Anyway, simply stated, the problem
is that the certificate's private key is either inaccessible or the keyspec is incorrect.
</p>
        <p>
          <strong>Problems</strong>
        </p>
        <p>
Our problems basically boiled down to three root causes:
</p>
        <p>
1 - Improper import of good certificates, which caused them to appear faulty.
</p>
        <p>
2 - Use of a build of makecert.exe that generates key containers improperly
</p>
        <p>
3 - Failure to realize that makecert.exe does not, by default, generate certs that
use the correct keyspec for an SSL cert.
</p>
        <p>
Problem #1 - The problem with importing was that I sometimes imported the certificate
into the CurrentUser MY store and then, realizing that I'd imported into the wrong
store, copied the cert into the LocalMachine MY store. The problem is that once a
certificate is imported into a CurrentUser store, the private key container resides
in the users profile, where it cannot be found by a system process.
</p>
        <p>
Problem #2 - One of the first things I do when I create a development VM is to add
the path to the .NET SDK bin directory to my system path. I always want access to
the tools therein from any command prompt. Unfortunately, the makecert.exe in that
directory (v5.131.2157.1) wont work for generating SSL certs. The problem is that
even if you specify a LocalMachine store for the cert, the private key container it
generates is generated as a user key, not a machine key. Therefore, though everything
looks good, when you use the cert from a system process, you experience the symptoms
enumerated above. In order to use this build for SSL certs, youd have to pre-generate
the key container and reference the pre-created container on the makecert command
line.
</p>
        <p>
Problem #3 - There are two standard key types for RSA keys: signature and exchange.
Which key is used is defined by the keyspec property of the private key context belonging
to the certificate. The keyspec property must be set to "Exchange" in order for the
cert to work for SSL. This is obvious to me, but I never realized that makecert.exe
sets the keyspec to Signature by default, and there isnt a standard interface to view
this property of a certificate that Im aware of.
</p>
        <p>
          <strong>Solutions</strong>
        </p>
        <p>
Solution #1 - Import certificates intended for SSL usage into a LocalMachine store
directly. Dont try to copy a cert from a CurrentUser store into a LocalMachine store.
If youve mistakenly imported a cert into a CurrentUser store, you need to delete the
cert <em>and</em> the key container (deleting a certificate does not delete the key
container), and then import the cert into a LocalMachine store. See my next post for
details as to how to locate the key container and delete it.
</p>
        <p>
Solution #2 - Dont use v5.131.2157.1 of makecert.exe (the one in the .NET v1.1 SDK)
to generate SSL certificates. It always generates user key containers, which wont
work from a system process. Fortunately, the version of makecert.exe (v5.131.3790.0)
that ships with v2.0 of the .NET SDK, as well as the latest Platform SDKs, works properly.
</p>
        <p>
Solution #3 - Always use the command line option "-sky exchange" with makecert.exe
if youre generating SSL certificates. If you dont specify this, it will default to
the signature keyspec, which wont work for SSL.
</p>
        <p>
The difficulties Ive experienced have been compounded by the fact that any one or
more of these problems could be combined in a single situation, making it terribly
difficult to pinpoint precisely what is going on. To aid in the diagnosis of SSL certificate
problems, Im making available a little command line utility that I wrote for this
purpose.
</p>
        <p>
checkcert: <a href="/downloads/checkcert.zip">exe</a> <a href="/downloads/checkcert_source.zip">source</a></p>
        <p>
To use checkcert.exe, pass a store name and a cert subject search string (such as
the common name). Checkcert will display some key information about the cert that
is not available in the built-in tools (again, that Im aware of). Most importantly,
checkcert will display the private key container location and the keyspec. You want
to ensure that the key container location is "Machine" and that the keyspec is "Exchange"
for an SSL cert. I hope this information and the utility will save someone the hassle
of trying to unravel this mess from scratch.
</p>
        <img width="0" height="0" src="http://www.stevestechspot.com/aggbug.ashx?id=3f39efbd-09e2-4beb-9d5a-e37ad2fb3862" />
      </body>
      <title>SSL Certificates - Around in Circles</title>
      <guid isPermaLink="false">http://www.stevestechspot.com/PermaLink,guid,3f39efbd-09e2-4beb-9d5a-e37ad2fb3862.aspx</guid>
      <link>http://www.stevestechspot.com/SSLCertificatesAroundInCircles.aspx</link>
      <pubDate>Mon, 07 Nov 2005 06:00:00 GMT</pubDate>
      <description>
		&lt;p&gt;
One of the joys Ive experienced in my recent dealings with the HTTP API and some lower-level
SChannel code is that of trying to generate proper SSL test certificates. During the
initial development phase of the product Im currently working on, we used one common
test certificate for all our test/dev servers. Later on, we began to generate different
certificates for each server so that we could test some cert verification code and
also verify that we knew exactly what was required of certificates to work with our
product. Needless to say (or I wouldnt have anything to write here), we immediately
began to have many problems. Some servers worked just fine, while others failed. On
the failing servers, test requests with WebRequest yielded the familiar but unhelpful
error "Could not establish secure channel for SSL/TLS". Attempts to connect from IE
produced the error "Cannot find server or DNS Error". In order to further troubleshoot,
I tried making a connection using a plain SChannel-based SSL socket. The connection
was established just fine and the client socket sent the hello message. As soon as
the client socket attempted to read the server response, an exception was thrown,
indicating that the connection had been closed by the server. Next, I enabled full
SChannel logging on the server and restarted. Attempts to connect left 2 messages
in the event logs: "Creating an SSL server credential", followed by "The SSL server
credentials private key has the following properties..." and NO error. Baffled, I
installed Microsofts &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=cabea1d0-5a10-41bc-83d4-06c814265282&amp;amp;displaylang=en"&gt;SSL
Diagnostics&lt;/a&gt; utility and attempted a handshake simulation. This yielded the error
"Unexpected error receiving data (0x80090304)", which error code is defined as SEC_E_INTERNAL_ERROR;
again, a most unhelpful description. This led me on a week-long study of X.509 certificates,
makecert.exe and the MS Crypto Providers key container implementation. Im going to
omit many details here in order to get to the point, which is to enumerate the problems
and solutions Ive found for our situation. Ill follow up with another post to describe
the gory details of this research in some depth. Anyway, simply stated, the problem
is that the certificate's private key is either inaccessible or the keyspec is incorrect.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Problems&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Our problems basically boiled down to three root causes:
&lt;/p&gt;
&lt;p&gt;
1 - Improper import of good certificates, which caused them to appear faulty.
&lt;/p&gt;
&lt;p&gt;
2 - Use of a build of makecert.exe that generates key containers improperly
&lt;/p&gt;
&lt;p&gt;
3 - Failure to realize that makecert.exe does not, by default, generate certs that
use the correct keyspec for an SSL cert.
&lt;/p&gt;
&lt;p&gt;
Problem #1 - The problem with importing was that I sometimes imported the certificate
into the CurrentUser MY store and then, realizing that I'd imported into the wrong
store, copied the cert into the LocalMachine MY store. The problem is that once a
certificate is imported into a CurrentUser store, the private key container resides
in the users profile, where it cannot be found by a system process.
&lt;/p&gt;
&lt;p&gt;
Problem #2 - One of the first things I do when I create a development VM is to add
the path to the .NET SDK bin directory to my system path. I always want access to
the tools therein from any command prompt. Unfortunately, the makecert.exe in that
directory (v5.131.2157.1) wont work for generating SSL certs. The problem is that
even if you specify a LocalMachine store for the cert, the private key container it
generates is generated as a user key, not a machine key. Therefore, though everything
looks good, when you use the cert from a system process, you experience the symptoms
enumerated above. In order to use this build for SSL certs, youd have to pre-generate
the key container and reference the pre-created container on the makecert command
line.
&lt;/p&gt;
&lt;p&gt;
Problem #3 - There are two standard key types for RSA keys: signature and exchange.
Which key is used is defined by the keyspec property of the private key context belonging
to the certificate. The keyspec property must be set to "Exchange" in order for the
cert to work for SSL. This is obvious to me, but I never realized that makecert.exe
sets the keyspec to Signature by default, and there isnt a standard interface to view
this property of a certificate that Im aware of.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Solutions&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Solution #1 - Import certificates intended for SSL usage into a LocalMachine store
directly. Dont try to copy a cert from a CurrentUser store into a LocalMachine store.
If youve mistakenly imported a cert into a CurrentUser store, you need to delete the
cert &lt;em&gt;and&lt;/em&gt; the key container (deleting a certificate does not delete the key
container), and then import the cert into a LocalMachine store. See my next post for
details as to how to locate the key container and delete it.
&lt;/p&gt;
&lt;p&gt;
Solution #2 - Dont use v5.131.2157.1 of makecert.exe (the one in the .NET v1.1 SDK)
to generate SSL certificates. It always generates user key containers, which wont
work from a system process. Fortunately, the version of makecert.exe (v5.131.3790.0)
that ships with v2.0 of the .NET SDK, as well as the latest Platform SDKs, works properly.
&lt;/p&gt;
&lt;p&gt;
Solution #3 - Always use the command line option "-sky exchange" with makecert.exe
if youre generating SSL certificates. If you dont specify this, it will default to
the signature keyspec, which wont work for SSL.
&lt;/p&gt;
&lt;p&gt;
The difficulties Ive experienced have been compounded by the fact that any one or
more of these problems could be combined in a single situation, making it terribly
difficult to pinpoint precisely what is going on. To aid in the diagnosis of SSL certificate
problems, Im making available a little command line utility that I wrote for this
purpose.
&lt;/p&gt;
&lt;p&gt;
checkcert: &lt;a href="/downloads/checkcert.zip"&gt;exe&lt;/a&gt;&amp;nbsp;&lt;a href="/downloads/checkcert_source.zip"&gt;source&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
To use checkcert.exe, pass a store name and a cert subject search string (such as
the common name). Checkcert will display some key information about the cert that
is not available in the built-in tools (again, that Im aware of). Most importantly,
checkcert will display the private key container location and the keyspec. You want
to ensure that the key container location is "Machine" and that the keyspec is "Exchange"
for an SSL cert. I hope this information and the utility will save someone the hassle
of trying to unravel this mess from scratch.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.stevestechspot.com/aggbug.ashx?id=3f39efbd-09e2-4beb-9d5a-e37ad2fb3862" /&gt;</description>
      <comments>http://www.stevestechspot.com/CommentView,guid,3f39efbd-09e2-4beb-9d5a-e37ad2fb3862.aspx</comments>
      <category>AllContent</category>
    </item>
    <item>
      <trackback:ping>http://www.stevestechspot.com/Trackback.aspx?guid=c1f96ead-0baf-4d93-b969-5869bc8147dc</trackback:ping>
      <pingback:server>http://www.stevestechspot.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.stevestechspot.com/PermaLink,guid,c1f96ead-0baf-4d93-b969-5869bc8147dc.aspx</pingback:target>
      <dc:creator>Steve Johnson</dc:creator>
      <wfw:comment>http://www.stevestechspot.com/CommentView,guid,c1f96ead-0baf-4d93-b969-5869bc8147dc.aspx</wfw:comment>
      <wfw:commentRss>http://www.stevestechspot.com/SyndicationService.asmx/GetEntryCommentsRss?guid=c1f96ead-0baf-4d93-b969-5869bc8147dc</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I've been doing a fair bit of development against the MS HTTP API lately, and I'm
weary of the httpcfg.exe utility. First of all, it's a right pain in the neck to find
in the first place. Once located and downloaded, it's equally painful to use, IMO.
Having read several articles on the net about the woes others were also experiencing
in using this tool, I decided to write a simple GUI application against the Http configuration
APIs. It's called, quite simply, HttpConfig. It won't win any points for UI flash,
but I do hope it will make life easier for some as it already has for me. Enjoy!
</p>
        <p>
        </p>
        <p>
Download: <a href="/downloads/httpconfig.zip">exe</a> <a href="/downloads/httpconfig_source.zip">source</a></p>
        <img width="0" height="0" src="http://www.stevestechspot.com/aggbug.ashx?id=c1f96ead-0baf-4d93-b969-5869bc8147dc" />
      </body>
      <title>A Better httpcfg</title>
      <guid isPermaLink="false">http://www.stevestechspot.com/PermaLink,guid,c1f96ead-0baf-4d93-b969-5869bc8147dc.aspx</guid>
      <link>http://www.stevestechspot.com/ABetterHttpcfg.aspx</link>
      <pubDate>Fri, 28 Oct 2005 06:00:00 GMT</pubDate>
      <description>
		&lt;p&gt;
I've been doing a fair bit of development against the MS HTTP API lately, and I'm
weary of the httpcfg.exe utility. First of all, it's a right pain in the neck to find
in the first place. Once located and downloaded, it's equally painful to use, IMO.
Having read several articles on the net about the woes others were also experiencing
in using this tool, I decided to write a simple GUI application against the Http configuration
APIs. It's called, quite simply, HttpConfig. It won't win any points for UI flash,
but I do hope it will make life easier for some as it already has for me. Enjoy!&lt;p&gt;
&lt;p&gt;
Download:&amp;nbsp;&lt;a href="/downloads/httpconfig.zip"&gt;exe&lt;/a&gt;&amp;nbsp;&lt;a href="/downloads/httpconfig_source.zip"&gt;source&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.stevestechspot.com/aggbug.ashx?id=c1f96ead-0baf-4d93-b969-5869bc8147dc" /&gt;</description>
      <comments>http://www.stevestechspot.com/CommentView,guid,c1f96ead-0baf-4d93-b969-5869bc8147dc.aspx</comments>
      <category>AllContent</category>
    </item>
  </channel>
</rss>