<?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 - Worklog</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>Wed, 17 Oct 2007 02:43:30 GMT</pubDate>

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

<item>
    <title>CruiseControl.NET: Configuration Error</title>
    <link>http://shog9.com/log/archives/22-CruiseControl.NET-Configuration-Error.html</link>
            <category>Worklog</category>
    
    <comments>http://shog9.com/log/archives/22-CruiseControl.NET-Configuration-Error.html#comments</comments>
    <wfw:comment>http://shog9.com/log/wfwcomment.php?cid=22</wfw:comment>

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

    <author>nospam@example.com (Shog9)</author>
    <content:encoded>
    &lt;p&gt;Just upgraded to CC.NET 1.3. And it didn&#039;t work. It &lt;i&gt;spectacularly &lt;/i&gt;didn&#039;t work. Ok, it just didn&#039;t work:&lt;br /&gt;&lt;/p&gt;

&lt;blockquote style=&quot;margin: 1em;&quot;&gt;&lt;span&gt;&lt;h2&gt;&lt;i&gt;Configuration Error&lt;/i&gt; &lt;/h2&gt;&lt;/span&gt;&lt;font face=&quot;Arial, Helvetica, Geneva, SunSans-Regular, sans-serif &quot;&gt;&lt;b&gt;Description:  &lt;/b&gt;An error occurred during the processing of a configuration file required to  service this request. Please review the specific error details below and modify  your configuration file appropriately. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Parser Error Message: &lt;/b&gt;The  format of the file &#039;ThoughtWorks.CruiseControl.WebDashboard&#039; is invalid.&lt;/font&gt;&lt;br /&gt;&lt;/blockquote&gt;

&lt;p&gt;Unfortunate, that. After a few fruitless web searches, I re-installed 1.2, and of course, that worked. Which gave me an idea...&lt;br /&gt;&lt;br /&gt;Loaded 1.3 again, checked InetInfo settings, and sure &#039;nuff - it was still set to the 1.1 framework (1.3 is the first .NET 2.0 version of CC.NET). Change it to 2.0, and all was right with the world. &lt;br /&gt;&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Tue, 16 Oct 2007 18:51:25 -0700</pubDate>
    <guid isPermaLink="false">http://shog9.com/log/archives/22-guid.html</guid>
    
</item>
<item>
    <title>I could cry</title>
    <link>http://shog9.com/log/archives/21-I-could-cry.html</link>
            <category>Worklog</category>
    
    <comments>http://shog9.com/log/archives/21-I-could-cry.html#comments</comments>
    <wfw:comment>http://shog9.com/log/wfwcomment.php?cid=21</wfw:comment>

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

    <author>nospam@example.com (Shog9)</author>
    <content:encoded>
    &lt;p&gt;After almost three days, i finally narrowed down an intermittent problem with a certain library. Turns out, it&#039;s contained within a rules engine we borrowed from another group. &lt;br /&gt;&lt;br /&gt;A rules engine that isn&#039;t thread-safe.&lt;br /&gt;&lt;br /&gt;It&#039;s 2007. We&#039;re using .NET. There&#039;s precious little need to make random variables static (er, rather, &quot;Shared&quot; - this is VB.NET). And it&#039;s trivially easy to add a bit of locking to avoid the problem, if you really &lt;i&gt;must&lt;/i&gt; share the current rule with every other instance. &lt;br /&gt;&lt;br /&gt;Worse yet, this isn&#039;t even the problem i was trying to track down. &lt;br /&gt;&lt;br /&gt;So now, i&#039;m tired, depressed, and no where near done. I know in my head that this isn&#039;t the fault of VB, but my heart still lays blame.&lt;br /&gt;&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Tue, 25 Sep 2007 16:10:57 -0700</pubDate>
    <guid isPermaLink="false">http://shog9.com/log/archives/21-guid.html</guid>
    
</item>
<item>
    <title>New CPhog released</title>
    <link>http://shog9.com/log/archives/20-New-CPhog-released.html</link>
            <category>Worklog</category>
    
    <comments>http://shog9.com/log/archives/20-New-CPhog-released.html#comments</comments>
    <wfw:comment>http://shog9.com/log/wfwcomment.php?cid=20</wfw:comment>

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

    <author>nospam@example.com (Shog9)</author>
    <content:encoded>
    &lt;p&gt;&lt;img src=&quot;http://www.shog9.com/log/uploads/CPhog1.9.Png&quot; style=&quot;float:right;margin:.5em;border:none;&quot; alt=&quot;&quot;  /&gt;
I&#039;ve just uploaded the &lt;a href=&quot;http://www.greasespot.net/&quot;&gt;GreaseMonkey&lt;/a&gt; &quot;boot&quot; script for &lt;a href=&quot;http://www.shog9.com/greasemonkey/scripts/cphog.user.js&quot;&gt;CPhog 1.9.1&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;This will probably be the last release before I bite the bullet and go in for some major restructuring. I&#039;ve been using it for months now, and it&#039;s reasonable solid... but there are just too many remnants of the quick-and-dirty little script i threw together a couple of years ago.&lt;br /&gt;&lt;br /&gt;Notable changes with this release include the ability to load threads longer than 50 posts, &quot;QuickBio&quot; pop-up user profiles, and &quot;ForumWatch&quot; panels. &lt;br /&gt;&lt;br /&gt;Under the hood, changes include lots more reliance on &lt;a href=&quot;http://jquery.com/&quot;&gt;jQuery&lt;/a&gt; for DOM and plugin/content loading, some solid structure to new features (plugin-style loading rather than the &quot;one huge script&quot; style I&#039;d labored under for so long), and the use of &lt;font class=&quot;messagecontent&quot;&gt;&lt;a href=&quot;http://developer.mozilla.org/en/docs/DOM:Storage&quot;&gt;GlobalStorage&lt;/a&gt; instead of GM_setValue/GM_getValue (prefs.js). Many thanks to &lt;a href=&quot;http://weblogs.asp.net/dstone/&quot;&gt;David Stone&lt;/a&gt; for his work on all of this, not to mention cleaning up a lot of my old code.&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;More details &lt;a href=&quot;http://www.shog9.com/greasemonkey/CPhog.html&quot;&gt;here&lt;/a&gt;...&lt;br /&gt;&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Thu, 05 Jul 2007 14:30:29 -0700</pubDate>
    <guid isPermaLink="false">http://shog9.com/log/archives/20-guid.html</guid>
    
</item>
<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>The string '0000-00-00T00:00:00-05:00' is not a valid AllXsd value.</title>
    <link>http://shog9.com/log/archives/14-The-string-0000-00-00T000000-0500-is-not-a-valid-AllXsd-value..html</link>
            <category>Worklog</category>
    
    <comments>http://shog9.com/log/archives/14-The-string-0000-00-00T000000-0500-is-not-a-valid-AllXsd-value..html#comments</comments>
    <wfw:comment>http://shog9.com/log/wfwcomment.php?cid=14</wfw:comment>

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

    <author>nospam@example.com (Shog9)</author>
    <content:encoded>
    &lt;p&gt;This is one of several exceptions that started cropping up recently in a little web app I&#039;d written to display bugs in our &lt;a href=&quot;http://www.seapine.com/&quot;&gt;TestTrack&lt;/a&gt; database. &lt;br /&gt;Turns out, the value represented a null date (the server is located in CDT, GMT-5); however, the .NET SOAP framework doesn&#039;t seem to handle such things. I don&#039;t know enough about SOAP to say which party is in the wrong, but it turns out the value was part of a source control record that I wasn&#039;t particularly interested in anyway, so I just ditched the field altogether - filename + revision # should be enough. &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Sun, 17 Jun 2007 00:47:08 -0700</pubDate>
    <guid isPermaLink="false">http://shog9.com/log/archives/14-guid.html</guid>
    
</item>
<item>
    <title>Triple bug!</title>
    <link>http://shog9.com/log/archives/13-Triple-bug!.html</link>
            <category>Worklog</category>
    
    <comments>http://shog9.com/log/archives/13-Triple-bug!.html#comments</comments>
    <wfw:comment>http://shog9.com/log/wfwcomment.php?cid=13</wfw:comment>

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

    <author>nospam@example.com (Shog9)</author>
    <content:encoded>
    &lt;p&gt;The Interface called The Engine to verify The Data before passing The
Data to The Framework. This is redundant, as The Framework is already
responsible for verifying any data passed to it. Bug #1.&lt;br /&gt;&lt;br /&gt;The Framework called The Engine to verify The Data. Except, it skipped the call in all but two obscure scenarios. Bug #2. &lt;br /&gt;&lt;br /&gt;The Engine was broken, and would always fail anything passed to it for verification. Bug #3.&lt;br /&gt;&lt;br /&gt;None of this was unit tested, and so The Bugs lived in The Field for more than a year... Programmer Error!&lt;br /&gt;&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Mon, 11 Jun 2007 15:00:34 -0700</pubDate>
    <guid isPermaLink="false">http://shog9.com/log/archives/13-guid.html</guid>
    
</item>
<item>
    <title>WinInet ASYNC mode sucks</title>
    <link>http://shog9.com/log/archives/6-WinInet-ASYNC-mode-sucks.html</link>
            <category>Rants</category>
            <category>Worklog</category>
    
    <comments>http://shog9.com/log/archives/6-WinInet-ASYNC-mode-sucks.html#comments</comments>
    <wfw:comment>http://shog9.com/log/wfwcomment.php?cid=6</wfw:comment>

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

    <author>nospam@example.com (Shog9)</author>
    <content:encoded>
    &lt;p&gt;Spent most of the day wrestling with this wretched API. What a complete
waste of time. Tells me the request is complete, but wants me to wait
an unknown amount of time before actually letting me retrieve the
response. Ugh.&lt;br /&gt;&lt;br /&gt;Forget it. I&#039;ll just shove the whole thing off onto a separate thread and let that sit and wait for as long as it needs.&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Fri, 30 Mar 2007 13:59:00 -0700</pubDate>
    <guid isPermaLink="false">http://shog9.com/log/archives/6-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>Tables and numbers and colorful graphs and...</title>
    <link>http://shog9.com/log/archives/4-Tables-and-numbers-and-colorful-graphs-and....html</link>
            <category>Worklog</category>
    
    <comments>http://shog9.com/log/archives/4-Tables-and-numbers-and-colorful-graphs-and....html#comments</comments>
    <wfw:comment>http://shog9.com/log/wfwcomment.php?cid=4</wfw:comment>

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

    <author>nospam@example.com (Shog9)</author>
    <content:encoded>
    &lt;p&gt;A while back, I needed to generate some reports off of a small database
I maintain. I needed them to be updated frequently, and didn&#039;t want to
spend a lot of time putting them together. &lt;br /&gt;
&lt;br /&gt;
Of course, I could have used Crystal Reports. But it just didn&#039;t seem
right - I keep a large number of knives at home, and should I ever
desire death by a thousand cuts, I&#039;m sure it could be arranged on my
own time. No reason to mix such activities with work.&lt;br /&gt;
&lt;br /&gt;
So based on a recommendation, I decided to give SQL Server Reporting
Services a shot. Installed it on my desktop, threw together a few
reports, and that was it. It was quick and easy, and I was happy. Until
it suddenly stopped working. I messed around with keys and permissions
and database users, and after about a day it was all working again...
until, roughly a month later, it suddenly wasn&#039;t. This went on for some
time, and then, one day, it was time to bring the reports out of
development and make them available to other people. &lt;br /&gt;
&lt;br /&gt;
And I balked. Here it was, running on a local machine that had no other
users, no onerous loads, a machine that, most days, ran only one very
light application... and it was still breaking periodically. Did I &lt;em&gt;really &lt;/em&gt;want to put up with babysitting this thing on a remote server? No, I decided, I did not want that.&lt;br /&gt;
&lt;br /&gt;
So, back to the drawing board. Of course, I didn&#039;t exactly have time to
research and learn a whole new reporting framework. Heck, I didn&#039;t have
time to do much of anything - any work would have to be done while
waiting for builds to complete or tests to run on other projects. So I
buckled down and started coding: I needed a few basic statistical
routines, a histogram routine, some tables, and a few graphs. Some
quick-and-dirty C# took care of the stats, quick-and-dirty HTML for the
tables... and the &lt;a href=&quot;http://zedgraph.org/&quot;&gt;newest addition&lt;/a&gt; to my toolbox took care of the graphs.&lt;br /&gt;
&lt;br /&gt;
I&#039;d first run across ZedGraph a few years ago, when John Champion posted &lt;a href=&quot;http://www.codeproject.com/csharp/zedgraph.asp&quot;&gt;his article&lt;/a&gt;
on The CodeProject. While it looked nice enough, I had no need for such
a thing at the time, and forgot about it. But now, running across it in
a frantic &lt;a href=&quot;http://www.google.com/coop/cse?cx=008728878598828748424%3A32wunwqmfl8&quot;&gt;Google search&lt;/a&gt;,
it looked like just what I needed. A couple of hours spent playing with
it confirmed this notion: it fit my simple needs like a glove, quickly
turning the dry, drab reports into slick, colorful affairs, ready for
inclusion in any presentation. Best yet, &lt;a href=&quot;http://zedgraph.org/wiki/index.php?title=Use_RenderMode.RawImage_in_a_web_page&quot;&gt;it fit neatly&lt;/a&gt; into the quick-and-dirty ASP.NET code I&#039;d already written. &lt;br /&gt;
&lt;br /&gt;
A full day spent hacking (during the aforementioned gaps in
testing...), and the new reports were ready. Fast, ridiculously simple,
and perfectly suitable for XCOPY deployment.&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Mon, 26 Feb 2007 08:44:00 -0700</pubDate>
    <guid isPermaLink="false">http://shog9.com/log/archives/4-guid.html</guid>
    
</item>
<item>
    <title>Optimization: structure and algorithm</title>
    <link>http://shog9.com/log/archives/8-Optimization-structure-and-algorithm.html</link>
            <category>Worklog</category>
    
    <comments>http://shog9.com/log/archives/8-Optimization-structure-and-algorithm.html#comments</comments>
    <wfw:comment>http://shog9.com/log/wfwcomment.php?cid=8</wfw:comment>

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

    <author>nospam@example.com (Shog9)</author>
    <content:encoded>
    &lt;p&gt;I&#039;ve spent the past few weeks re-working a library that is used to
construct 3D models of machines. The library accepts as input a set of
options for the machine - the components that are required for it,
basic dimensions, etc. - and uses several sets of rules written by the
manufacturer to calculate exact positions and dimensions for each
aspect of the machine. &lt;br /&gt;&lt;br /&gt;This
is a heavily-used library: not only is it used to display several
different preview images of the machine as its being specified, but the
output is also used as a base for several other important calculations,
as well as the generation of a final set of detailed construction
drawings and measurements used as input in the manufacturing process.
In short, those rules are processed frequently, and there are &lt;i&gt;many&lt;/i&gt; of them. &lt;br /&gt;&lt;br /&gt;Therein
lies the problem. This system had been in place for nearly a decade,
and while it had been tweaked over the years to better handle the
ever-growing library of rules and options, the heart of the beast was
still chained to a decision made early on: the rules were to be pulled
from the database periodically and cached, stored on disk and in-memory
in nearly the same way they were stored in the DB - flat tables. While
this did go a long way towards eliminating the problems of latency when
communicating with a remote, heavily-loaded database, it strongly
encouraged the use of some very bad algorithms. When i first started
profiling, the calculations involved anywhere from several hundred
thousand to several million iterations over some of the tables, with
each iteration involving at least one look-up into the hash table used
to store the options specified for the machine.&lt;br /&gt;&lt;br /&gt;And remember, these calculations happen &lt;i&gt;often&lt;/i&gt;.
Even on a fast machine with plenty of memory, making non-trivial
changes to the machine quickly became very, very slow. To say nothing
of operations that involved a series of changes, with each change
dependent on an accurate model of the machine having been calculated
following the previous change!&lt;br /&gt;&lt;br /&gt;After spending a few days
analyzing the system, it became obvious that it cried for a thorough
re-design and re-implementation of the class structure. Not only was
nearly everything stored in a list of some sort (slowing iteration
beyond even what a flat array would have provided), and nearly devoid
of any intelligent indexing, but guessing at the cost of a routine was
made frustrating by the reliance on MFC&#039;s old, non-type-safe collection
classes: all objects were stored by void* or CObject*, all IDs were
LONGs (or worse yet, CStrings!). Even identifying the purpose of a
routine became an exercise in searching through code for the source of
every parameter, then searching the rest of the code to extract the
(otherwise implicit) requirements and constraints.&lt;br /&gt;&lt;br /&gt;Unfortunately, I&#039;ve nowhere &lt;i&gt;near&lt;/i&gt;
enough time to do a thorough analysis of the system as a whole, much
less a re-write. One month is barely enough time to properly document
such a system, and I knew the more changes I made to it, the less
likely they would be properly tested before release. And this was
hardly the only urgent project on my plate. &lt;br /&gt;&lt;br /&gt;And this is where
templates and the STL really come into their own. One piece at a time,
I took the slowest routines, identified a better (usually
non-iterative!) algorithm, and re-wrote &lt;i&gt;just those routines&lt;/i&gt;.
Since the new routines depended on having either an index or a fast
method of filtering the rules they were driven from, I then wrote
specialized containers for that data, taking into account the
requirements of the newly re-designed routines that used them. LONGs
became RuleID, lists of arrays became std::multimap combined with
std::vector, complex filtering routines became simple look-ups on
containers with complex keys. Finally, I wrote adapters for the new
types that would allow them to be used with the old, un-changed
routines: ID types converted to / from LONGs / CStrings as necessary,
routines were provided for iteration / serialization / etc. In this
way, one set of routines could be re-written, profiled and regression
tested, without worrying about the rest of the system. &lt;br /&gt;&lt;br /&gt;By the
time I was seeing acceptable speed, I&#039;d modified probably 30% of the
entire library, one small piece at a time. And a good number of those
changes were things like making parameters or access methods const,
just so I could have a better idea of where things were actually being
modified. &lt;br /&gt;&lt;br /&gt;It&#039;s hard to be proud of work like this. The library
is still a mess. In some ways, it&#039;s a bigger mess than it was before,
since now there&#039;s a mix of new, type-safe, near-orthogonal code, in
with the old; it&#039;s harder to know what to expect. If given the chance,
I&#039;d spend a lot more time cleaning things up... but for now, I&#039;ve
accomplished my primary goal in time for release. Proud? No. But satisfied.&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Sun, 25 Feb 2007 08:32:00 -0700</pubDate>
    <guid isPermaLink="false">http://shog9.com/log/archives/8-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>123 files modified</title>
    <link>http://shog9.com/log/archives/10-123-files-modified.html</link>
            <category>Worklog</category>
    
    <comments>http://shog9.com/log/archives/10-123-files-modified.html#comments</comments>
    <wfw:comment>http://shog9.com/log/wfwcomment.php?cid=10</wfw:comment>

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

    <author>nospam@example.com (Shog9)</author>
    <content:encoded>
    &lt;p&gt;...but now, The App builds under VS2k5.
&lt;/p&gt;

&lt;p&gt; Most of it came down to code that took advantage of the broken scoping rules for &lt;code&gt;for&lt;/code&gt;
loops in previous versions of VC++. A few interesting changes though:
code that had mistakenly been using the address of a function rather
than the return value was my favorite. &lt;/p&gt;
 
    </content:encoded>

    <pubDate>Thu, 05 Jan 2006 17:28:00 -0700</pubDate>
    <guid isPermaLink="false">http://shog9.com/log/archives/10-guid.html</guid>
    
</item>
<item>
    <title>No mapping between account names and security IDs was done</title>
    <link>http://shog9.com/log/archives/1-No-mapping-between-account-names-and-security-IDs-was-done.html</link>
            <category>Worklog</category>
    
    <comments>http://shog9.com/log/archives/1-No-mapping-between-account-names-and-security-IDs-was-done.html#comments</comments>
    <wfw:comment>http://shog9.com/log/wfwcomment.php?cid=1</wfw:comment>

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

    <author>nospam@example.com (Shog9)</author>
    <content:encoded>
    &lt;h4&gt;Or, Friday Afternoon Stupidity&lt;/h4&gt;

&lt;p&gt;I spent a good two hours staring at that message.&lt;/p&gt;

&lt;p&gt;Well, ok, i did a lot of other things during that time also, but
still, for those two hours, staring at that message was happening
fairly often.&lt;/p&gt;

&lt;p&gt;See, i was throwing in a bit of code that would disable certain
features if the user wasn&#039;t a member of certain groups on the domain.
The idea seemed slick, we&#039;d use build-in Windows authentication, and so
wouldn&#039;t have to distribute encrypted files, or set up our own server,
or anything troublesome like that... just check if the user is in this
group, and if not disable stuff.&lt;/p&gt;

&lt;p&gt;Well, it sounded easy. And it would have been too, except i&#039;ve never
worked with any of this before. The most i&#039;ve ever done with regards to
Windows security was to do a string comparison to the result of &lt;code&gt;GetUserName()&lt;/code&gt;.  So i started Googling for info on it, and after maybe an hour of reading about &lt;code&gt;LookupAccountName()&lt;/code&gt; and &lt;code&gt;CheckTokenMembership()&lt;/code&gt;,
i had a routine that seemed to do what i wanted, at least with local
groups. Smiling, i changed the group to check against to one on the
domain... Failure. &amp;quot;No mapping between account names and security IDs
was done.&amp;quot; To quote a veteran Windows developer, &amp;quot;Blast!&amp;quot;&lt;/p&gt;

&lt;p&gt;So now what? I go and bring up the MSDN page for each function i&#039;m
calling, double check that the parameters are of the right type and of
the right size. I re-write the memory allocation to simplify it, just
in case that&#039;s causing problems. I start searching newsgroups for that
error message. I list all the groups available on the domain, just in
case i&#039;d gotten the name wrong for the one i&#039;d tried.&lt;/p&gt;

&lt;p&gt;Finally, i read a thread that ends with the original author seeing
success and admitting that it was due to a rogue space in the username.
Well, i think, that can&#039;t be it, &#039;cause the name is hard-coded, and any
spaces would be obvious next to the quotes... and as i&#039;m thinking this,
i&#039;m already seeing the problem. &lt;/p&gt;

&lt;p&gt;Yup.  I&#039;d only used one backslash to separate the domain and the group.  Once that was escaped, everything works beautifully.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;sigh&lt;/i&gt;... Time for a beer, a pizza, and a weekend away from staring at code.&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Sat, 23 Apr 2005 15:02:00 -0700</pubDate>
    <guid isPermaLink="false">http://shog9.com/log/archives/1-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>