<?xml version="1.0" encoding="utf-8" ?>

<rss version="2.0" 
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:admin="http://webns.net/mvcb/"
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
   xmlns:wfw="http://wellformedweb.org/CommentAPI/"
   xmlns:content="http://purl.org/rss/1.0/modules/content/"
   >
<channel>
    <title>Shog's Worklog - Tips</title>
    <link>http://shog9.com/log/</link>
    <description>Nothing lies still long</description>
    <dc:language>en</dc:language>
    <generator>Serendipity 1.3 - http://www.s9y.org/</generator>
    <pubDate>Mon, 25 Jun 2007 05:46:43 GMT</pubDate>

    <image>
        <url>/head.jpg</url>
        <title>RSS: Shog's Worklog - Tips - Nothing lies still long</title>
        <link>http://shog9.com/log/</link>
        <width>64</width>
        <height>52</height>
    </image>

<item>
    <title>Fit acceptance testing and OpenWiki</title>
    <link>http://shog9.com/log/archives/19-Fit-acceptance-testing-and-OpenWiki.html</link>
            <category>Tips</category>
            <category>Worklog</category>
    
    <comments>http://shog9.com/log/archives/19-Fit-acceptance-testing-and-OpenWiki.html#comments</comments>
    <wfw:comment>http://shog9.com/log/wfwcomment.php?cid=19</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://shog9.com/log/rss.php?version=2.0&amp;type=comments&amp;cid=19</wfw:commentRss>
    

    <author>nospam@example.com (Shog9)</author>
    <content:encoded>
    &lt;p&gt;&lt;img src=&quot;http://www.shog9.com/log/uploads/FitOutput.png&quot; style=&quot;float: right;&quot; alt=&quot;&quot;  /&gt;&lt;a href=&quot;http://www.nunit.org/&quot;&gt;NUnit&lt;/a&gt; now includes the &lt;a href=&quot;http://fit.c2.com/&quot;&gt;Framework for Integrated Test&lt;/a&gt; (Fit) engine. I&#039;m not entirely sure why (there seems to be some support for using it to run NUnit tests) but my curiosity upon seeing the new DLL led me to read more about Fit. And it couldn&#039;t have been more timely - the project I was working on had something like 47 test cases taken directly from sales orders, complete with supplier-provided &quot;known good&quot; outputs - a perfect &lt;em&gt;ahem&lt;/em&gt; fit for Fit testing. &lt;br /&gt;&lt;br /&gt;And what a beautiful thing it is. A few minutes work, and the Excel spreadsheet of test cases was a HTML document suitable for feeding into the .NET version of Fit - much preferable to the manual translation of each scenario into a NUnit test, or (&lt;em&gt;shudder&lt;/em&gt;) manually entering each case into my interactive testing app. I&#039;d been planning on creating a bulk-testing interface anyway, and this just seemed too good to be true - it was almost exactly what I&#039;d been planning, and saved me the time and effort of writing and debugging a custom CSV parser + test harness. &lt;br /&gt;&lt;br /&gt;The only thing lacking was integration with our wiki, which was the other part of my idle plan... Sure, there&#039;s &lt;a href=&quot;http://fitnesse.org/&quot;&gt;FitNesse&lt;/a&gt; - but that just solves one problem with yet another wiki to maintain. &lt;br /&gt;&lt;br /&gt;So I hacked together an ASP.NET runner for Fit, threw it on our build machine, and then built in a new processing instruction to let OpenWiki forward on a page to this service for processing. &lt;br /&gt;&lt;br /&gt;Satisfaction!&lt;br /&gt;&lt;br /&gt;In case anyone else has a use for it, here&#039;s the code required:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;OpenWiki #FITTESTS processing instruction (modify mywiki.asp)&lt;/i&gt;&lt;br /&gt;&lt;/p&gt;

&lt;pre&gt;Function MyWikifyProcessingInstructions(pText)&lt;br /&gt;       &lt;br /&gt;   &#039; other custom processing instructions...&lt;br /&gt;   &lt;br /&gt;   &#039; Fit integration: detect Fit processing instruction, flag for later processing&lt;br /&gt;   dim FitPI, FitPILen&lt;br /&gt;   FitPI = &quot;#FITTESTS&quot;&lt;br /&gt;   FitPILen = Len(FitPI)&lt;br /&gt;   if m(pText, &quot;\n&quot; &amp;amp; FitPI &amp;amp; &quot;\s+&quot;, False, False) Then&lt;br /&gt;      dim lineStart, lineEnd&lt;br /&gt;      lineStart = InStr(pText, FitPI)&lt;br /&gt;      lineEnd = InStr(lineStart, pText, vbCR)&lt;br /&gt;      If lineEnd &amp;gt; lineStart+FitPILen Then&lt;br /&gt;         gFitTestPath = Trim(Mid(pText, lineStart+FitPILen, lineEnd - lineStart - FitPILen))&lt;br /&gt;      End If&lt;br /&gt;      pText = s(pText, &quot;\n&quot; &amp;amp; FitPI &amp;amp; &quot;[^\r\n]*\r*\n&quot;, &quot;&quot;, False, False)&lt;br /&gt;   End If&lt;br /&gt;&lt;br /&gt;   &#039; other custom processing instructions...&lt;br /&gt;   &lt;br /&gt;    MyWikifyProcessingInstructions = pText&lt;br /&gt;End Function&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Additional modifications to mywiki.asp - these actually call the testing web service after the page has been mostly built. &lt;/i&gt;&lt;br /&gt;&lt;/p&gt;

&lt;pre&gt;Function MyLastMinuteChanges(pText)&lt;br /&gt;&lt;br /&gt;   &#039; other custom last-minute changes...&lt;br /&gt;&lt;br /&gt;   &#039; Fit integration&lt;br /&gt;   If (gAction = &quot;view&quot; and Len(gFitTestPath) &amp;gt; 0 ) Then&lt;br /&gt;      dim TestResults&lt;br /&gt;      TestResults = RunFitTests(pText, gFitTestPath)&lt;br /&gt;      If ( err.number &amp;lt;&amp;gt; 0 ) then&lt;br /&gt;         pText = &quot;&amp;lt;i&amp;gt;Error running tests: &quot; &amp;amp; err.description &amp;amp; &quot;&amp;lt;/i&amp;gt;&amp;lt;br /&amp;gt;&quot; &amp;amp; pText&lt;br /&gt;      Elseif ( Len(TestResults) = 0 ) then&lt;br /&gt;         pText = &quot;&lt;i&gt;Unknown error running tests&lt;/i&gt;&quot; &amp;amp; pText&lt;br /&gt;      Else&lt;br /&gt;         pText = TestResults&lt;br /&gt;      End If&lt;br /&gt;   End If&lt;br /&gt;&lt;br /&gt;   MyLastMinuteChanges = pText&lt;br /&gt;End Function&lt;br /&gt;&lt;br /&gt;Function RunFitTests(pText, gFitTestPath)&lt;br /&gt;   dim url&lt;br /&gt;   dim verb&lt;br /&gt;   dim form&lt;br /&gt;&lt;br /&gt;   &#039; location of FIT service. Need not be local.&lt;br /&gt;   url = &quot;http://localhost:8088/FitService.ashx&quot;&lt;br /&gt;   verb = &quot;POST&quot;&lt;br /&gt;   form = &quot;ClassPath=&quot; &amp;amp; Server.URLEncode(gFitTestPath) _&lt;br /&gt;      &amp;amp; &quot;&amp;amp;TestData=&quot; &amp;amp; Server.URLEncode(pText)&lt;br /&gt;      &lt;br /&gt;   on error resume next  &lt;br /&gt;   &lt;br /&gt;   dim xmlhttp&lt;br /&gt;   set xmlhttp = Server.CreateObject(&quot;Msxml2.ServerXMLHTTP.4.0&quot;)&lt;br /&gt;   if ( xmlhttp is nothing or err.number &amp;lt;&amp;gt; 0 ) then&lt;br /&gt;      err.clear&lt;br /&gt;      set xmlhttp = Server.CreateObject(&quot;Msxml2.ServerXMLHTTP&quot;)&lt;br /&gt;   end if&lt;br /&gt;   &lt;br /&gt;   dim xmlDoc&lt;br /&gt;   if ( err.number = 0 ) then&lt;br /&gt;      xmlhttp.open verb, url, false &#039; synchronous&lt;br /&gt;   end if&lt;br /&gt;   &lt;br /&gt;   if ( err.number = 0 ) then&lt;br /&gt;      xmlhttp.setRequestHeader &quot;Content-Type&quot;, &quot;application/x-www-form-urlencoded&quot; &lt;br /&gt;      xmlhttp.send form&lt;br /&gt;   end if&lt;br /&gt;   &lt;br /&gt;   &#039; try to figure out if it worked or not. And if not, why. VBS error handling... yuck.&lt;br /&gt;   dim status&lt;br /&gt;   if ( err.number = 0 ) then&lt;br /&gt;      status = xmlhttp.status&lt;br /&gt;   end if&lt;br /&gt;   &lt;br /&gt;   if (err.number &amp;lt;&amp;gt; 0) then&lt;br /&gt;   elseif (status &amp;lt;&amp;gt; 200) then &lt;br /&gt;      Err.Raise 65000, &quot;&quot;, xmlhttp.statusText &amp;amp; &quot;(&quot; &amp;amp; status &amp;amp; &quot;)&quot;, &quot;&quot;, 0&lt;br /&gt;   else&lt;br /&gt;      &#039; clean up Fit html&lt;br /&gt;      RunFitTests = Replace(xmlhttp.ResponseText, &quot;&amp;amp;nbsp;&quot;, &quot; &quot;)&lt;br /&gt;      RunFitTests = Replace(RunFitTests, &quot;&amp;lt;br&amp;gt;&quot;, &quot;&amp;lt;br/&amp;gt;&quot;)&lt;br /&gt;      RunFitTests = Replace(RunFitTests, &quot;&amp;lt;hr&amp;gt;&quot;, &quot;&amp;lt;hr/&amp;gt;&quot;)&lt;br /&gt;      RunFitTests = Replace(RunFitTests, &quot;&amp;lt;font size=-1&quot;, &quot;&amp;lt;font size=&#039;-1&#039;&quot;)&lt;br /&gt;   end if  &lt;br /&gt;   &lt;br /&gt;   set xmlhttp = nothing  &lt;br /&gt;End Function&lt;br /&gt;&lt;/pre&gt;

&lt;p&gt;&lt;i&gt;FitService.ashx - quick&#039;n&#039;dirty Fit runner. You might want to add some error handling...&lt;/i&gt;&lt;br /&gt;&lt;/p&gt;

&lt;pre&gt;&amp;lt;%@ WebHandler Language=&quot;C#&quot; Class=&quot;FitService&quot; %&amp;gt;&lt;br /&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Web;&lt;br /&gt;using fit;&lt;br /&gt;&lt;br /&gt;public class FitService : IHttpHandler&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;   public void ProcessRequest(HttpContext context)&lt;br /&gt;   {&lt;br /&gt;      context.Response.ContentType = &quot;text/html&quot;;&lt;br /&gt;      context.Response.ContentEncoding = System.Text.Encoding.UTF8;&lt;br /&gt;&lt;br /&gt;      Fixture.assemblyDirs = context.Request.Form[&quot;ClassPath&quot;].Split(new char[]{&#039;;&#039;});&lt;br /&gt;      &lt;br /&gt;      Fixture fixture = new Fixture();&lt;br /&gt;      Parse tables = new Parse(context.Request.Form[&quot;TestData&quot;]);&lt;br /&gt;      fixture.doTables(tables);&lt;br /&gt;      tables.print(context.Response.Output);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public bool IsReusable&lt;br /&gt;   {&lt;br /&gt;      get&lt;br /&gt;      {&lt;br /&gt;         return false;&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;&lt;br /&gt;With these in place, i can add a line to the beginning of any wiki entry:&lt;br /&gt;&lt;/p&gt;

&lt;pre&gt;#FITTESTS c:\MfgEngineInterface\Current build\&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;...followed by a table containing the tests, and the tests will be automatically run and their results provided upon page generation.&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Sun, 24 Jun 2007 17:16:27 -0700</pubDate>
    <guid isPermaLink="false">http://shog9.com/log/archives/19-guid.html</guid>
    
</item>
<item>
    <title>Dump calls</title>
    <link>http://shog9.com/log/archives/3-Dump-calls.html</link>
            <category>Tips</category>
            <category>Worklog</category>
    
    <comments>http://shog9.com/log/archives/3-Dump-calls.html#comments</comments>
    <wfw:comment>http://shog9.com/log/wfwcomment.php?cid=3</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://shog9.com/log/rss.php?version=2.0&amp;type=comments&amp;cid=3</wfw:commentRss>
    

    <author>nospam@example.com (Shog9)</author>
    <content:encoded>
    &lt;p&gt;I&#039;m working with a 3rd-party library that does some machine-specific
calculations. It&#039;s called through COM interop, and takes a &lt;em&gt;ton&lt;/em&gt;
of parameters. When something doesn&#039;t come out right, it&#039;s nice to be
able to quickly view what&#039;s being send in and returned without spending
an excessive amount of time in the debugger... so I use this
quick-and-dirty little wrapper to dump them to the output window:&lt;br /&gt;&lt;/p&gt;

&lt;pre&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Text;&lt;br /&gt;using System.Reflection;&lt;br /&gt;using System.Runtime.Remoting;&lt;br /&gt;using System.Runtime.Remoting.Proxies;&lt;br /&gt;using System.Runtime.Remoting.Messaging;&lt;br /&gt;using System.Runtime.InteropServices;&lt;br /&gt;using System.Diagnostics;&lt;br /&gt;&lt;br /&gt;public class DebugTraceProxy&lt;br /&gt;   : RealProxy&lt;br /&gt;{&lt;br /&gt;   readonly MarshalByRefObject target;&lt;br /&gt;&lt;br /&gt;   public static T NewObject&amp;lt;T&amp;gt;()&lt;br /&gt;   {&lt;br /&gt;      return (T)(new DebugTraceProxy(typeof(T)).GetTransparentProxy());&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private DebugTraceProxy(Type t)&lt;br /&gt;      : base(t)&lt;br /&gt;   {&lt;br /&gt;      target = (MarshalByRefObject)Activator.CreateInstance(t);&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   public override IMessage Invoke(IMessage msg)&lt;br /&gt;   {&lt;br /&gt;      IMethodCallMessage call = msg as IMethodCallMessage;&lt;br /&gt;&lt;br /&gt;      Debug.WriteLine(call.MethodName + &amp;quot;:&amp;quot;);&lt;br /&gt;      for (int i = 0; i &amp;lt; call.InArgCount; ++i)&lt;br /&gt;      {&lt;br /&gt;         string name = call.GetInArgName(i);&lt;br /&gt;         object arg = call.GetInArg(i);&lt;br /&gt;         Debug.WriteLine(&amp;quot;   &amp;quot; + name + &amp;quot;: &amp;quot; + DumpOb(arg));&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      IMethodReturnMessage ret = RemotingServices.ExecuteMessage(target, (IMethodCallMessage)msg);&lt;br /&gt;&lt;br /&gt;      Debug.WriteLine(&amp;quot;Returned:&amp;quot;);&lt;br /&gt;      for (int i = 0; i &amp;lt; ret.OutArgCount; ++i)&lt;br /&gt;      {&lt;br /&gt;         string name = ret.GetOutArgName(i);&lt;br /&gt;         object arg = ret.GetOutArg(i);&lt;br /&gt;         Debug.WriteLine(&amp;quot;   &amp;quot; + name + &amp;quot;: &amp;quot; + DumpOb(arg));&lt;br /&gt;      }&lt;br /&gt;            &lt;br /&gt;      return ret;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private string DumpOb(object ob)&lt;br /&gt;   {&lt;br /&gt;      Type t = ob.GetType();&lt;br /&gt;      if (t.IsPrimitive || t == typeof(string))&lt;br /&gt;         return ob.ToString();&lt;br /&gt;&lt;br /&gt;      string obDesc = &amp;quot;&amp;quot;;&lt;br /&gt;      FieldInfo[] infos = t.GetFields(BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance );&lt;br /&gt;      if (infos.Length == 0)&lt;br /&gt;         return ob.ToString();&lt;br /&gt;      foreach (FieldInfo field in infos)&lt;br /&gt;      {&lt;br /&gt;         if (obDesc != &amp;quot;&amp;quot;)&lt;br /&gt;            obDesc += &amp;quot;, &amp;quot;;&lt;br /&gt;         obDesc += field.Name + &amp;quot;: &amp;quot; + field.GetValue(ob).ToString();&lt;br /&gt;      }&lt;br /&gt;      return obDesc;&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;

&lt;p&gt;To use it, I create the object like so:&lt;br /&gt;&lt;/p&gt;

&lt;pre&gt;CrazyOb myCrazyOb = DebugTraceProxy.NewObject&amp;lt;crazyob&amp;gt;();&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;
Reflection... handy.&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Thu, 22 Mar 2007 11:56:00 -0700</pubDate>
    <guid isPermaLink="false">http://shog9.com/log/archives/3-guid.html</guid>
    
</item>
<item>
    <title>VS2005 DataTips for MFC collection classes (CMap, CArray, etc.)</title>
    <link>http://shog9.com/log/archives/2-VS2005-DataTips-for-MFC-collection-classes-CMap,-CArray,-etc..html</link>
            <category>Tips</category>
            <category>Worklog</category>
    
    <comments>http://shog9.com/log/archives/2-VS2005-DataTips-for-MFC-collection-classes-CMap,-CArray,-etc..html#comments</comments>
    <wfw:comment>http://shog9.com/log/wfwcomment.php?cid=2</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://shog9.com/log/rss.php?version=2.0&amp;type=comments&amp;cid=2</wfw:commentRss>
    

    <author>nospam@example.com (Shog9)</author>
    <content:encoded>
    &lt;p&gt;&lt;a title=&quot;[fig. 3: the long, hard road through CMap]&quot; href=&quot;http://www.flickr.com/photos/shog9/416944121/&quot;&gt;&lt;img width=&quot;502&quot; height=&quot;359&quot; border=&quot;2&quot; align=&quot;right&quot; alt=&quot;dbgtip_fig3&quot; src=&quot;http://farm1.static.flickr.com/131/416944121_d3a9f1bb55_o.png&quot; style=&quot;padding: 5px; margin-left: 5px;&quot; /&gt;&lt;/a&gt;I spend a lot of time debugging old code. Tracing through libraries written years ago, before the VC++ STL had reached maturity. And one of the often-frustrating aspects of this is how difficult it is to examine the contents of the old, MFC collection classes. &lt;code&gt;CDWordArray&lt;/code&gt;, &lt;code&gt;CStringArray&lt;/code&gt;, &lt;code&gt;CMapPtrToPtr&lt;/code&gt;... not to mention the various templatized versions of these classes. While sometimes these can be easily replaced with newer, better-supported STL equivalents, often the effort involved outweighs the benefit.&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;
At least for the array classes, it&#039;s only a minor inconvenience: the array pointer, and the size of the array are both readily available, and with these it&#039;s easy enough to view the contents.  &lt;br /&gt;
&lt;br /&gt;
But for the &lt;code&gt;CMap&lt;/code&gt; classes, things get ugly. Internally, these objects are hash tables, with an array of buckets and each bucket a linked list. Viewing the contents of one of these maps in the debugger requires manually tracing the list of each bucket, then backing up and trying another bucket, then another... until you&#039;ve found the item, or just given up.&lt;br /&gt;
&lt;br /&gt;
The &lt;code&gt;std::map&amp;lt;&amp;gt;&lt;/code&gt; class, implemented as a red-black tree, should be just as much of an annoyance to view - however, it gets flattened into what &lt;span style=&quot;font-style: italic;&quot;&gt;looks&lt;/span&gt; like an array:&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;
&lt;a title=&quot;[fig 4: std::map goodness]&quot; href=&quot;http://www.flickr.com/photos/shog9/416944134/&quot;&gt;&lt;img width=&quot;579&quot; height=&quot;240&quot; alt=&quot;dbgtip_fig4&quot; src=&quot;http://farm1.static.flickr.com/174/416944134_f4d123e9bc_o.png&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Handy, eh? So enough of tracing through buckets. &lt;br /&gt;
Open &lt;code&gt;\Program Files\Microsoft Visual Studio 8\Common7\Packages\Debugger\autoexp.dat&lt;/code&gt;, and at the end of the &lt;code&gt;[Visualizer]&lt;/code&gt; section, add:&lt;br /&gt;&lt;/p&gt;

&lt;pre&gt;;------------------------------------------------------------------------------&lt;br /&gt;;  CArray&lt;br /&gt;;------------------------------------------------------------------------------&lt;br /&gt;CArray&amp;lt;*&amp;gt;|CDWordArray|CWordArray|CByteArray|CUIntArray|CPtrArray|CObArray|CStringArray{&lt;br /&gt;   preview&lt;br /&gt;   (&lt;br /&gt;      #( &amp;quot;[&amp;quot;, [$c.m_nSize], &amp;quot;](&amp;quot;,&lt;br /&gt;         #array &lt;br /&gt;         (&lt;br /&gt;             expr : $c.m_pData[$i],&lt;br /&gt;             size : $c.m_nSize&lt;br /&gt;         ),&lt;br /&gt;      &amp;quot;)&amp;quot;)&lt;br /&gt;   )&lt;br /&gt;   &lt;br /&gt;   children&lt;br /&gt;   (&lt;br /&gt;      #(&lt;br /&gt;         #array &lt;br /&gt;         (&lt;br /&gt;             expr : $c.m_pData[$i],&lt;br /&gt;             size : $c.m_nSize&lt;br /&gt;         )&lt;br /&gt;      )   &lt;br /&gt;   )&lt;br /&gt;}&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;
Start a debug session. You should now be able to quickly examine the various &lt;code&gt;CArray &lt;/code&gt;(&lt;code&gt;CDWordArray&lt;/code&gt;...) objects as easily as &lt;code&gt;std::vector&amp;lt;...&amp;gt;&lt;/code&gt;s. Note that the &lt;code&gt;preview (...)&lt;/code&gt; section controls what&#039;s viewed in the initial DataTip or watch line, while the &lt;code&gt;children(...)&lt;/code&gt; section controls what&#039;s displayed when you expand it.&lt;br /&gt;
&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a title=&quot;[fig 5: visible CArray data]&quot; href=&quot;http://www.flickr.com/photos/shog9/416944139/&quot;&gt;&lt;img width=&quot;405&quot; height=&quot;242&quot; alt=&quot;dbgtip_fig5&quot; src=&quot;http://farm1.static.flickr.com/188/416944139_675869ded2_o.png&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Now for the fun one. Start with:&lt;br /&gt;&lt;/p&gt;

&lt;pre&gt;;------------------------------------------------------------------------------&lt;br /&gt;;  CMap&lt;br /&gt;;------------------------------------------------------------------------------&lt;br /&gt;CMap&amp;lt;*&amp;gt;|CMapPtrToPtr|CMapPtrToWord|CMapWordToPtr|CMapWordToOb|CMapStringToPtr|CMapStringToOb|CMapStringToString{&lt;br /&gt;   preview&lt;br /&gt;   (&lt;br /&gt;      #( &amp;quot;[&amp;quot;, [$c.m_nCount], &amp;quot;](&amp;quot;,&lt;br /&gt;         #array &lt;br /&gt;         (&lt;br /&gt;             expr : $c.m_pHashTable[$i],&lt;br /&gt;             size : $c.m_nHashTableSize&lt;br /&gt;         ) : #list (&lt;br /&gt;                 head : &amp;amp;$e,&lt;br /&gt;                 next : pNext&lt;br /&gt;             ) : $e,&lt;br /&gt;      &amp;quot;)&amp;quot;)&lt;br /&gt;   )&lt;br /&gt;   &lt;br /&gt;   children&lt;br /&gt;   (&lt;br /&gt;      #(&lt;br /&gt;         #array &lt;br /&gt;         (&lt;br /&gt;             expr : $e.m_pHashTable[$i],&lt;br /&gt;             size : $e.m_nHashTableSize&lt;br /&gt;         ) : #list (&lt;br /&gt;                 head : &amp;amp;$e,&lt;br /&gt;                 next : pNext&lt;br /&gt;             ) : $e&lt;br /&gt;      )         &lt;br /&gt;   )&lt;br /&gt;}&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;
Ah, now this one will save some serious time - it&#039;ll flatten the various &lt;code&gt;CMap&lt;/code&gt; objects such that they look like arrays in the debugger. A &lt;code&gt;CMap&lt;/code&gt; with 3000 items will show 3000 children, numbered 0-2999. &lt;br /&gt;
&lt;br /&gt;
&lt;a title=&quot;[fig 6: visible CMap pairs]&quot; href=&quot;http://www.flickr.com/photos/shog9/416944157/&quot;&gt;&lt;img width=&quot;370&quot; height=&quot;240&quot; alt=&quot;dbgtip_fig6&quot; src=&quot;http://farm1.static.flickr.com/161/416944157_001c545ad3_o.png&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
But it can still be better: each of those children is a key-value pair, specifically a &lt;code&gt;CMap::CAssoc&lt;/code&gt; object. It&#039;d be nice if we could get a preview of those keys and values as we scroll through those 3000 items, rather than having to expand each one...&lt;br /&gt;&lt;/p&gt;

&lt;pre&gt;CMap&amp;lt;*&amp;gt;::CAssoc|CMapPtrToPtr::CAssoc|CMapPtrToWord::CAssoc|CMapWordToPtr::CAssoc|CMapWordToOb::CAssoc|CMapStringToPtr::CAssoc|CMapStringToOb::CAssoc|CMapStringToString::CAssoc {&lt;br /&gt;   preview&lt;br /&gt;   (&lt;br /&gt;      #( &lt;br /&gt;         &amp;quot;(&amp;quot;, &lt;br /&gt;         $e.key, &lt;br /&gt;         &amp;quot;,&amp;quot;, &lt;br /&gt;         $e.value, &lt;br /&gt;         &amp;quot;)&amp;quot;&lt;br /&gt;      )&lt;br /&gt;   )&lt;br /&gt;   &lt;br /&gt;   children&lt;br /&gt;   (&lt;br /&gt;     #(&lt;br /&gt;         key: $c.key,&lt;br /&gt;         value: $c.value&lt;br /&gt;     )&lt;br /&gt;   )&lt;br /&gt;}&lt;/pre&gt;

&lt;p&gt;&lt;br /&gt;
&lt;a title=&quot;[fig 7: visible CMap data]&quot; href=&quot;http://www.flickr.com/photos/shog9/416944168/&quot;&gt;&lt;img width=&quot;369&quot; height=&quot;240&quot; border=&quot;2&quot; align=&quot;right&quot; alt=&quot;dbgtip_fig7&quot; src=&quot;http://farm1.static.flickr.com/134/416944168_ca4854cd26_o.png&quot; style=&quot;padding: 5px; margin-left: 5px;&quot; /&gt;&lt;/a&gt; There! All happy.  &lt;br clear=&quot;all&quot; /&gt;
&lt;br /&gt;
Of course, you can write rules for your own datatypes too, if you want them to be immediately visible in the preview. For a good reference, see the excellent writeup over at &lt;a href=&quot;http://www.virtualdub.org/blog/pivot/entry.php?id=120&quot; style=&quot;font-weight: bold;&quot;&gt;virtualdub.org&lt;/a&gt;&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Sat, 10 Mar 2007 17:19:00 -0700</pubDate>
    <guid isPermaLink="false">http://shog9.com/log/archives/2-guid.html</guid>
    
</item>
<item>
    <title>Faster C++ compilation on VS2005</title>
    <link>http://shog9.com/log/archives/9-Faster-C++-compilation-on-VS2005.html</link>
            <category>Tips</category>
            <category>Worklog</category>
    
    <comments>http://shog9.com/log/archives/9-Faster-C++-compilation-on-VS2005.html#comments</comments>
    <wfw:comment>http://shog9.com/log/wfwcomment.php?cid=9</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://shog9.com/log/rss.php?version=2.0&amp;type=comments&amp;cid=9</wfw:commentRss>
    

    <author>nospam@example.com (Shog9)</author>
    <content:encoded>
    &lt;p&gt;So after a couple years of putting up with very slow build times, i
couldn&#039;t take it anymore. We&#039;re preparing to migrate to VS2005 for
primary C++ development, and a 20x increase in the time needed for a
full build just isn&#039;t gonna cut it. So i started going through the
options, hoping there was an option or something, hoping that they
hadn&#039;t made the compiler itself &lt;em&gt;that much slower&lt;/em&gt; in the process of adding new features and increasing standards compliance. &lt;br /&gt;
&lt;br /&gt;
Sure enough, there was a simple solution. Seems the &amp;quot;automatic&amp;quot; option
for using pre-compiled headers isn&#039;t available anymore, and so during
the conversion PCH was just turned off for all projects. &lt;br /&gt;
&lt;br /&gt;
At this point, i&#039;m going to admit that i&#039;ve never given too much
thought to PCH support in VC++. The only other time i&#039;ve used PCH at
all was with Borland&#039;s C++ compiler, where manually specifying what you
wanted pre-compiled was the only option (at the time anyway). That It
Just Worked on VC++ was enough for me - why mess with what works? But
the downside was, i didn&#039;t have a very clear idea of what was actually
going on. Put the system headers in STDAFX.H, rebuild all, check in and
forget it. Upon realizing that this was no longer an option, i didn&#039;t
really know what to do...&lt;br /&gt;
&lt;br /&gt;
Then i found &lt;a href=&quot;http://www.cygnus-software.com/papers/precompiledheaders.html&quot;&gt;Bruce Dawson&#039;s excellent article&lt;/a&gt; on the subject. Going well beyond MSDN&#039;s dry descriptions of &lt;em&gt;how&lt;/em&gt;, Bruce details the various methods for configuring, optimizing, and using PCH in VC++. &lt;br /&gt;
&lt;br /&gt;
With this, i enabled PCH manually on our various projects, and brought
build times back down to something acceptable (roughly 1.5x what it
takes in VS6). VS2K5 is usable at last!&lt;br /&gt;
&lt;br /&gt;
Now, if i could just do something about that annoying &amp;quot;Updating Intellisense...&amp;quot;&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Thu, 02 Mar 2006 17:02:00 -0700</pubDate>
    <guid isPermaLink="false">http://shog9.com/log/archives/9-guid.html</guid>
    
</item>
<item>
    <title>Painless NTLM authentication in Firefox</title>
    <link>http://shog9.com/log/archives/7-Painless-NTLM-authentication-in-Firefox.html</link>
            <category>Tips</category>
            <category>Worklog</category>
    
    <comments>http://shog9.com/log/archives/7-Painless-NTLM-authentication-in-Firefox.html#comments</comments>
    <wfw:comment>http://shog9.com/log/wfwcomment.php?cid=7</wfw:comment>

    <slash:comments>2</slash:comments>
    <wfw:commentRss>http://shog9.com/log/rss.php?version=2.0&amp;type=comments&amp;cid=7</wfw:commentRss>
    

    <author>nospam@example.com (Shog9)</author>
    <content:encoded>
    &lt;p&gt;I&#039;ve used Firefox heavily at work ever since they built NTLM
authentication in, but have always been rather annoyed at how limited
it is compared to the support built into IE. With IE there is no
difference between accessing an intranet site that requires NTLM, and
one that requires no authentication, assuming you&#039;re already logged
into the network on your machine. Firefox on the other hand, would
bring up its authentication dialog for each site, prompting for a
username and password. Although allowing Firefox to save the password
helped reduce the trouble to simply hitting Enter whenever such a box
appeared, it was still annoying, and worse yet, slowed access to these
servers.&lt;/p&gt;

&lt;p&gt;After being notified by a server admin here that i was causing
frequent authentication errors to show up in the logs, i decided it was
time to investigate this problem further. Fortunately, a quick Google
search brought me several hints at a solution, which was soon put in
place.&lt;/p&gt;

&lt;h2&gt;The fix&lt;/h2&gt;

&lt;ol&gt;&lt;li&gt;In Firefox, type about:config into the address bar and hit enter.  You should see a huge list of configuration properties. &lt;/li&gt;&lt;li&gt;Find
the setting named network.automatic-ntlm-auth.trusted-uris (the easiest
way to do this is to type that into the filter box at top).&lt;/li&gt;&lt;li&gt;Double-click
this line, and enter the names of all servers for which NTLM is
desired, separated by commas. Then press ‘OK’ to confirm. &lt;/li&gt;&lt;li&gt;Open
the options dialog (Tools-&amp;gt;Options menu), and on the General page
press the Connection Settings button to get the proxy configuration
dialog: &lt;/li&gt;&lt;li&gt;Make sure the correct proxy server is
configured, and that the same list of servers are listed in the No
Proxy for: entryfield as were set in step #3. &lt;/li&gt;&lt;li&gt;Done. &lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;Result? No more slow access, no more authentication errors, no more
clearing the list of saved passwords when i change my network password
(or worse yet, having to call support and have my password reset
because i forgot to do this...)&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Wed, 09 Mar 2005 14:23:00 -0700</pubDate>
    <guid isPermaLink="false">http://shog9.com/log/archives/7-guid.html</guid>
    
</item>

</channel>
</rss>