<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Parks Computing &#187; C#</title>
	<atom:link href="http://www.parkscomputing.com/labels/c/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.parkscomputing.com</link>
	<description>Pedagogy for the autodidactic programmer</description>
	<lastBuildDate>Thu, 12 Jan 2012 22:48:30 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>A Keyword I&#8217;d Like To See in C#</title>
		<link>http://www.parkscomputing.com/2011/02/a-feature-id-like-to-see-in-c/</link>
		<comments>http://www.parkscomputing.com/2011/02/a-feature-id-like-to-see-in-c/#comments</comments>
		<pubDate>Fri, 18 Feb 2011 16:37:38 +0000</pubDate>
		<dc:creator>Paul Parks</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.parkscomputing.com/?p=408</guid>
		<description><![CDATA[Although I use C# more and more these days, I still consider myself primarily a C++ developer. C# has a few really neat language features that are just now being added to C++ (like lambdas), but I still find C++ to be more expressive, with terser syntax, than C#. One example of this is deterministic [...]]]></description>
			<content:encoded><![CDATA[<p>Although I use C# more and more these days, I still consider myself primarily a C++ developer. C# has a few really neat language features that are just now being added to C++ (like lambdas), but I still find C++ to be more expressive, with terser syntax, than C#.</p>
<p>One example of this is deterministic disposal in C#. For classes that implement <em>IDispose</em> this is accomplished with the <em>using</em> statement. One example from MSDN follows:</p>
<div class="example">
<pre>using (Font font1 = new Font(&quot;Arial&quot;, 10.0f))
{
    byte charset = font1.GdiCharSet;
}</pre>
</div>
<p>Seems simple enough, right? What could I possibly have to complain about in that code?</p>
<p><span id="more-408"></span></p>
<p>This is an example of a programming practice known by the clumsy acronym RAII, which stands for <a title="Wikipedia: Resource Acquisition Is Initialization" href="http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization" target="_blank">Resource Acquisition Is Initialization</a>. No matter what happens inside the scope defined by the braces (short of abnormal termination), the <em>font1</em> object will be properly disposed when execution leaves the scope.</p>
<p>In C++ this idiom is very common. For example, if you need to define a temporary buffer but you won&#8217;t know the size of the buffer until runtime, you can use a <em>std::vector&lt;T&gt;</em>. You don&#8217;t have to worry about allocating or freeing memory because the <em>vector</em> class takes care of it for you. Here&#8217;s an utterly contrived example:</p>
<div class="example">
<pre>{
   // Create a byte buffer of size n. We'll assume n >= 4 here.
   std::vector<char> buffer(n);
   &#038;buffer[0] = 'H';
   &#038;buffer[1] = 'i';
   &#038;buffer[2] = '!';
   &#038;buffer[3] = '\0';
   UseBuffer(&#038;buffer[0]);
}
</char></pre>
</div>
<p>When execution reaches the end of scope, the <em>vector</em> destructor takes care of deleting the memory it allocated in the constructor. What&#8217;s nice about the C++ way of doing things is that there&#8217;s no <em>using</em> statement or other special syntax decorations. This is just how C++ works.</p>
<p>Now, C# doesn&#8217;t have true destructors like C++, so this exact syntax can&#8217;t work in C#. It only has finalizers, and there&#8217;s no way to predict whether, or even <strong><em>if</em></strong>, finalizers will be executed. This is why .NET provides the <em>IDispose</em> pattern. The thing is, I find the syntax for deterministic disposal to be clumsy. I think it would be a little easier to use if there were a keyword that I could use to decorate objects that I want to deterministically dispose. We could name this mythical keyword <em>raii</em>. Applied to the first example, it would look like this:</p>
<div class="example">
<pre>{
   raii Font font1 = new Font(&quot;Arial&quot;, 10.0f);
   byte charset = font1.GdiCharSet;
}
</pre>
</div>
<p>The <em>raii</em> keyword would instruct the compiler to emit the same code that it would emit for the <em>using</em> statement, so that the object would be disposed at the end of scope, but the syntax is a little cleaner. You could even stack more than one disposable object in the same block with little effort:</p>
<div class="example">
<pre>{
   raii Font font1 = new Font(&quot;Arial&quot;, 10.0f);
   raii var foo = new SomeOtherDisposableThing();
   foo.use(font1);
}
</pre>
</div>
<p>Both <em>font1</em> and <em>foo</em> would be disposed, in reverse order, at end of scope.</p>
<p>I can&#8217;t find a reason not to do this. Can anyone else think of some downside that I&#8217;ve missed?</p>
<p><strong>UPDATE:</strong> Roger Pate points out below that a new keyword isn&#8217;t necessary; just make the using statement affect the rest of the current block rather than requiring a new block below it, and you&#8217;re there.</p>
<div class="example">
<pre>
{
   using Font font1 = new Font(&quot;Arial&quot;, 10.0f);
   using var foo = new SomeOtherDisposableThing();
   foo.use(font1);
}
</pre>
</div>
<p>While I wish they&#8217;d picked a better keyword than &#8220;using&#8221; to begin with, this change would still make it a little less clumsy.</p>
<p>I&#8217;ve also learned, since writing this article, that it&#8217;s possible to stack the using statements so that they enclose a single block. This should be obvious, but it never occurred to me.</p>
<div class="example">
<pre>
{
   using (Font font1 = new Font(&quot;Arial&quot;, 10.0f))
   using (var foo = new SomeOtherDisposableThing())
   {
      foo.use(font1);
   }
}
</pre>
</div>
<a href="http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.parkscomputing.com%2F2011%2F02%2Fa-feature-id-like-to-see-in-c%2F&amp;t=A%20Keyword%20I%27d%20Like%20To%20See%20in%20C%23" id="facebook_share_button_408" style="font-size:11px; line-height:13px; font-family:'lucida grande',tahoma,verdana,arial,sans-serif; text-decoration:none; display: -moz-inline-block; display:inline-block; padding:1px 20px 0 5px; margin: 5px 0; height:15px; border:1px solid #d8dfea; color: #3B5998; background: #fff url(http://b.static.ak.fbcdn.net/images/share/facebook_share_icon.gif) no-repeat top right;">Share</a>
	<script type="text/javascript">
	<!--
	var button = document.getElementById('facebook_share_link_408') || document.getElementById('facebook_share_icon_408') || document.getElementById('facebook_share_both_408') || document.getElementById('facebook_share_button_408');
	if (button) {
		button.onclick = function(e) {
			var url = this.href.replace(/share\.php/, 'sharer.php');
			window.open(url,'sharer','toolbar=0,status=0,width=626,height=436');
			return false;
		}
	
		if (button.id === 'facebook_share_button_408') {
			button.onmouseover = function(){
				this.style.color='#fff';
				this.style.borderColor = '#295582';
				this.style.backgroundColor = '#3b5998';
			}
			button.onmouseout = function(){
				this.style.color = '#3b5998';
				this.style.borderColor = '#d8dfea';
				this.style.backgroundColor = '#fff';
			}
		}
	}
	-->
	</script>
	]]></content:encoded>
			<wfw:commentRss>http://www.parkscomputing.com/2011/02/a-feature-id-like-to-see-in-c/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Update on Ripsaw</title>
		<link>http://www.parkscomputing.com/2010/04/update-on-ripsaw/</link>
		<comments>http://www.parkscomputing.com/2010/04/update-on-ripsaw/#comments</comments>
		<pubDate>Thu, 22 Apr 2010 18:39:00 +0000</pubDate>
		<dc:creator>Paul Parks</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[ripsaw]]></category>
		<category><![CDATA[utilities]]></category>
		<category><![CDATA[visual studio]]></category>

		<guid isPermaLink="false">http://nightowl/?p=46</guid>
		<description><![CDATA[A while back I started an article series on a utility named Ripsaw. I have since gotten pretty busy with other projects, and the only extracurricular thing I&#8217;ve worked on in the meantime is the lesson series on how to play &#8220;Spanish Fly&#8221;. I was also waiting for Visual Studio 2010 to hit release, but [...]]]></description>
			<content:encoded><![CDATA[<p>A while back I started <a href="/labels/ripsaw.html">an article series on a utility named Ripsaw</a>. I have since gotten pretty busy with other projects, and the only extracurricular thing I&#8217;ve worked on in the meantime is the <a href="http://www.parkscomputing.com/2010/03/new-guitar-tutorial-videos.html">lesson series on how to play &#8220;Spanish Fly&#8221;</a>. I was also waiting for Visual Studio 2010 to hit release, but I haven&#8217;t moved up to Professional yet, so I may actually drop the whole project back down to VS 2008 when I start it up again.</p>
<p>On top of all that, Blogger is yanking the rug out from under me with some changes to how it updates certain sites, and I want to get that resolved before I add any significant new content. I just wanted to let everyone know that the project isn&#8217;t dead; in fact, there have been several times over the last few weeks when I&#8217;ve needed a utility like Ripsaw, so this is definitely going to get done eventually.</p>
<a href="http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.parkscomputing.com%2F2010%2F04%2Fupdate-on-ripsaw%2F&amp;t=Update%20on%20Ripsaw" id="facebook_share_button_46" style="font-size:11px; line-height:13px; font-family:'lucida grande',tahoma,verdana,arial,sans-serif; text-decoration:none; display: -moz-inline-block; display:inline-block; padding:1px 20px 0 5px; margin: 5px 0; height:15px; border:1px solid #d8dfea; color: #3B5998; background: #fff url(http://b.static.ak.fbcdn.net/images/share/facebook_share_icon.gif) no-repeat top right;">Share</a>
	<script type="text/javascript">
	<!--
	var button = document.getElementById('facebook_share_link_46') || document.getElementById('facebook_share_icon_46') || document.getElementById('facebook_share_both_46') || document.getElementById('facebook_share_button_46');
	if (button) {
		button.onclick = function(e) {
			var url = this.href.replace(/share\.php/, 'sharer.php');
			window.open(url,'sharer','toolbar=0,status=0,width=626,height=436');
			return false;
		}
	
		if (button.id === 'facebook_share_button_46') {
			button.onmouseover = function(){
				this.style.color='#fff';
				this.style.borderColor = '#295582';
				this.style.backgroundColor = '#3b5998';
			}
			button.onmouseout = function(){
				this.style.color = '#3b5998';
				this.style.borderColor = '#d8dfea';
				this.style.backgroundColor = '#fff';
			}
		}
	}
	-->
	</script>
	]]></content:encoded>
			<wfw:commentRss>http://www.parkscomputing.com/2010/04/update-on-ripsaw/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ripsaw Library Implementation</title>
		<link>http://www.parkscomputing.com/2009/11/ripsaw-library-implementation/</link>
		<comments>http://www.parkscomputing.com/2009/11/ripsaw-library-implementation/#comments</comments>
		<pubDate>Tue, 24 Nov 2009 08:00:00 +0000</pubDate>
		<dc:creator>Paul Parks</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[ripsaw]]></category>
		<category><![CDATA[visual studio]]></category>

		<guid isPermaLink="false">http://nightowl/?p=39</guid>
		<description><![CDATA[In this installment of the Ripsaw article series we'll start putting some actual code into an implementation of the COM interfaces that we specified in the last article. For those of you who just joined the series, Ripsaw is a log viewer for Windows, similar to the Unix tail utility. This series of articles details my rewrite of the application from the ground up.]]></description>
			<content:encoded><![CDATA[<p>In this installment of the <a href="http://www.parkscomputing.com/labels/ripsaw.html">Ripsaw article series</a> we&#8217;ll start putting some actual code into an implementation of the COM interfaces that we specified in <a href="http://www.parkscomputing.com/2009/11/ripsaw-com-interface-first-pass.html">the last article</a>. For those of you who just joined the series, Ripsaw is a log viewer for Windows, similar to the Unix <code>tail</code> utility. This series of articles details my rewrite of the application from the ground up.<br />
<span id="more-39"></span><br />
So far, we have a test script implemented in JavaScript (or JScript, if you want to be really picky) that is intended to exercise our COM interfaces. There is a base interface that represents a generic log that a client might wish to follow, a more specific interface representing a file, and a <code>dispinterface</code> declaring the events that a Ripsaw library object can fire. In this article we&#8217;ll start implementing these interfaces, with the goal of providing just enough functionality to allow us to execute the test script.</p>
<p>I&#8217;m implementing this project with Visual Studio 2010, which is still in beta as of this writing. You may download the <a href="http://www.parkscomputing.com/ripsaw/articles/RipsawSource_20091124.zip">solution, projects, and source code</a> if you&#8217;d like to follow along, but if you haven&#8217;t <a href="http://msdn.microsoft.com/en-us/vstudio/dd582936.aspx">downloaded and installed the 2010 beta</a> yet, you&#8217;ll need to adapt the code to your IDE and C++ compiler of choice if you wish to build it (I recommend <a href="http://www.microsoft.com/exPress/download/">Visual Studio 2008</a>).</p>
<div class="fullpost">
<h3>Implementing the COM Interfaces</h3>
<p>To briefly recap the design, there will be a Ripsaw COM library that exports objects representing sources of updates, and a Ripsaw client (such as a log viewer or a script) will create objects that fire events whenever the source changes its status. Now that we&#8217;ve specified the interfaces, it&#8217;s time to implement them just enough to run the test script that we created <a href="http://www.parkscomputing.com/2009/11/ripsaw-com-interface-first-pass.html">in the last installment</a>. I like to use ATL to implement the low-level, boilerplate code that&#8217;s necessary for <code>IUnknown</code> and <code>IDispatch</code>, though once the wizard is done I usually take over and move all the generated code around. I&#8217;ve never liked round-trip development with code generators.</p>
<p>There are three interfaces (for now) that need to be implemented: <code>IRipsawObject</code>, <code>IRipsawFile</code>, and <code>_IRipsawEvents</code>. The first interface is the base interface for not only <code>IRipsawFile</code> but other potential interfaces that might be added later on as the library is developed. That means I want to create the implementation in such a way that I can easily extend it to other sources of data that Ripsaw might use. Unfortunately, if I took the code that the ATL wizard spat out, I&#8217;d have a really difficult time reusing it. I need to split the ATL code into a generic interface implementation and a concrete object implementation.</p>
<p>In ATL, when implementing an object derived from <code>IDispatch</code>, you usually get a class definition that looks like this:</p>
<div class="example">
<pre>class ATL_NO_VTABLE RipsawFile :
   public CComObjectRootEx&lt;CComMultiThreadModel&gt;,
   public CComCoClass&lt;RipsawFile, &amp;CLSID_RipsawFile&gt;,
   public ISupportErrorInfo,
   public IConnectionPointContainerImpl&lt;RipsawFile&gt;,
   public CProxy_IRipsawEvents&lt;RipsawFile&gt;,
   public IDispatchImpl&lt;IRipsawFile, &amp;IID_IRipsawFile, &amp;LIBID_RipLib, /*wMajor =*/ 1, /*wMinor =*/ 0&gt;</pre>
</div>
<p>That works fine, until it doesn&#8217;t. If you ever want to derive a class from <code>RipsawFile</code>, you&#8217;re going to run into problems. What I usually do is replace <code>IDispatchImpl</code> with my own template class that derives from <code>IDispatchImpl</code> and implements the interface that my object is going to expose. In this case, I want my object to expose both <code>IRipsawFile</code> and <code>IRipsawObject</code>, so I&#8217;ll start by creating a generic template implementation of the base <code>IRipsawObject</code> interface. The template will be defined in a header file named <strong>IRipsawObjectImpl.h</strong>.</p>
<div class="example">
<pre>#pragma once
#include &lt;comutil.h&gt;

template &lt;class Root, class T, const IID* piid = &amp;__uuidof(T),
   const GUID* plibid = &amp;ATL::CAtlModule::m_libid,
   WORD wMajor = 1, WORD wMinor = 0,
   class tihclass = ATL::CComTypeInfoHolder&gt;
class IRipsawObjectImpl :
   public Root,
   public ATL::IDispatchImpl&lt;T, piid, plibid, wMajor, wMinor, tihclass&gt;
{
public:
   /* Internal public implementation */
   IRipsawObjectImpl() : isOpen(FALSE)
   {
   }

   virtual ~IRipsawObjectImpl()
   {
   }

public:
   /* IRipsawObject interface */
   HRESULT STDMETHODCALLTYPE get_Name(
      __out BSTR* pName)
   {
      if (!pName)
      {
         return E_INVALIDARG;
      }

      {
         ObjectLock(this);
         *pName = NULL;
      }
      return S_OK;
   }

   HRESULT STDMETHODCALLTYPE get_IsOpen(
      __out VARIANT_BOOL* pRetVal)
   {
      if (!pRetVal)
      {
         return E_INVALIDARG;
      }

      LONG retVal = 0;
      InterlockedExchange(&amp;retVal, isOpen);
      *pRetVal = retVal ? VARIANT_TRUE : VARIANT_FALSE;
      return S_OK;
   }

   HRESULT STDMETHODCALLTYPE Close()
   {
      _bstr_t fileName;

      VARIANT_BOOL tmpIsOpen = VARIANT_FALSE;
      get_IsOpen(&amp;tmpIsOpen);

      if (tmpIsOpen)
      {
         ObjectLock(this);
         put_IsOpen(FALSE);
         BSTR name = 0;
         get_Name(&amp;name);
         Notify_Close(name);
         SysFreeString(name);
      }

      return S_OK;
   }

   HRESULT STDMETHODCALLTYPE WaitForUpdate(
      __in ULONG timeout,
      __out BSTR* pNewData)
   {
      if (!pNewData)
      {
         return E_INVALIDARG;
      }

      *pNewData = NULL;
      return S_OK;
   }

protected:
   /* Internal protected implementation */
   HRESULT STDMETHODCALLTYPE put_IsOpen(
      __in VARIANT_BOOL value)
   {
      InterlockedExchange(&amp;isOpen, value);
      return S_OK;
   }

   virtual HRESULT Notify_Open(BSTR fileName)
   {
      return S_OK;
   }

   virtual HRESULT Notify_Close(BSTR fileName)
   {
      return S_OK;
   }

   virtual HRESULT Notify_Update(BSTR updateData)
   {
      return S_OK;
   }

   LONG isOpen;
};</pre>
<p><span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; line-height: 19px; white-space: normal; font-size: 13px;">There is quite a bit going on in this template, so let&#8217;s go over its various parts.</span></p>
</div>
<h3>The <code>Root</code> Type</h3>
<p>If you look back at the example class definition for <code>RipsawFile</code>, you&#8217;ll see that it derived from <code>CComObjectRootEx&lt;CComMultiThreadModel&gt;</code>. This is because, when the wizard generated the code, the user selected the option to generate an object that was free-threaded. This is an implementation detail of the <em>object</em>, not of the <em>interface</em>, so that&#8217;s the first thing we need to abstract away from our generic implementation of the <code>IRipsawObject</code> interface. The problem, however, is that <code>CComObjectRootEx</code> provides a lot of useful types that we should take advantage of, such as methods for guarding blocks of code that need to be serialized when accessed from multiple threads. What I decided to do was make <code>Root</code> a template parameter and derive the implementation from that type. The concrete implementation may provide any type for this parameter as long as it implements the definitions expected from that type, such as <code>ObjectLock</code>.</p>
<h3>The <code>IDispatchImpl</code> Type</h3>
<p>This is a class that is provided by ATL to implement the ugly details of <code>IDispatch</code>. While the average COM developer can (usually) implement a workable <code>IUnknown</code> rather easily, implementing <code>IDispatch</code> is a good deal more complicated. We know, based on our IDL, that <code>IRipsawObject</code> is derived from <code>IDispatch</code>, so this is an implementation detail that&#8217;s appropriate for our generic implementation. Classes that derive from <code>IRipsawObject</code> will also pick up the <code>IDispatch</code> implementation. All of the template parameters to <code>IRipsawObjectImpl</code> after <code>Root</code> are passed along to <code>IDispatchImpl</code>.</p>
<h3><code>Notify_Open</code>, <code>Notify_Close</code>, and <code>Notify_Update</code></h3>
<p>All objects that implement the <code>IRipsawObject</code> interface are expected to fire events to notify clients about open, close, and update events. How these events are generated is an implementation detail best left to the concrete object implementation, but I may need to fire events from the generic implementation. I decided to create stub methods that will be overridden in the concrete implementation.</p>
<h3>The Rest of the Code</h3>
<p>The remainder of the header is devoted to minimal implementations of the methods and properties defined in the <code>IRipsawObject</code> interface. Most of these will be overridden in <code>IRipsawFile</code> and other derived interfaces. Note that the implementations use <code>InterlockedExchange</code> and <code>ObjectLock</code> to serialize access to internal data. This is because we want to allow the generic implementation to work for free-threaded object implementations, which may be called by more than one thread at a time. The <code>ObjectLock</code> type is expected to be provided by the <code>Root</code> template parameter.</p>
<h3>I Could Use Some <a href="http://en.wikipedia.org/wiki/More_cowbell">More Cowbell</a></h3>
<p>This still isn&#8217;t enough code to create a usable <code>IRipsawFile</code> implementation, but since that&#8217;s the default interface that we need to expose from our COM object we&#8217;ll have to derive another generic implementation from <code>IRipsawObject</code> that will let us finally execute our test script. We&#8217;ll tackle that template class in the next installment in the series. If you want to cheat and peek ahead, look at the file <strong>IRipsawFileImpl.h</strong> in the <a href="http://www.parkscomputing.com/ripsaw/articles/RipsawSource_20091124.zip">source code</a>.</p>
</div>
<a href="http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.parkscomputing.com%2F2009%2F11%2Fripsaw-library-implementation%2F&amp;t=Ripsaw%20Library%20Implementation" id="facebook_share_button_39" style="font-size:11px; line-height:13px; font-family:'lucida grande',tahoma,verdana,arial,sans-serif; text-decoration:none; display: -moz-inline-block; display:inline-block; padding:1px 20px 0 5px; margin: 5px 0; height:15px; border:1px solid #d8dfea; color: #3B5998; background: #fff url(http://b.static.ak.fbcdn.net/images/share/facebook_share_icon.gif) no-repeat top right;">Share</a>
	<script type="text/javascript">
	<!--
	var button = document.getElementById('facebook_share_link_39') || document.getElementById('facebook_share_icon_39') || document.getElementById('facebook_share_both_39') || document.getElementById('facebook_share_button_39');
	if (button) {
		button.onclick = function(e) {
			var url = this.href.replace(/share\.php/, 'sharer.php');
			window.open(url,'sharer','toolbar=0,status=0,width=626,height=436');
			return false;
		}
	
		if (button.id === 'facebook_share_button_39') {
			button.onmouseover = function(){
				this.style.color='#fff';
				this.style.borderColor = '#295582';
				this.style.backgroundColor = '#3b5998';
			}
			button.onmouseout = function(){
				this.style.color = '#3b5998';
				this.style.borderColor = '#d8dfea';
				this.style.backgroundColor = '#fff';
			}
		}
	}
	-->
	</script>
	]]></content:encoded>
			<wfw:commentRss>http://www.parkscomputing.com/2009/11/ripsaw-library-implementation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ripsaw COM Interface, First Pass</title>
		<link>http://www.parkscomputing.com/2009/11/ripsaw-com-interface-first-pass/</link>
		<comments>http://www.parkscomputing.com/2009/11/ripsaw-com-interface-first-pass/#comments</comments>
		<pubDate>Tue, 10 Nov 2009 02:40:00 +0000</pubDate>
		<dc:creator>Paul Parks</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[ripsaw]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://nightowl/?p=35</guid>
		<description><![CDATA[In this installment of the Ripsaw article series we&#8217;ll finally get to write some code. We&#8217;ve already gotten a pretty good idea about how we want to implement the core Ripsaw library, so now we&#8217;re going to define enough of the COM interface that we can create a simple test script that will eventually be [...]]]></description>
			<content:encoded><![CDATA[<p>In this installment of the <a href="/labels/ripsaw.html">Ripsaw article series</a> we&#8217;ll finally get to write some code. We&#8217;ve already gotten a pretty good idea about how we want to implement the core Ripsaw library, so now we&#8217;re going to define enough of the COM interface that we can create a simple test script that will eventually be used to exercise the library.</p>
<p><span id="more-35"></span></p>
<p>To be callable from script, the object&#8217;s interface should be OLE-automation compatible, so we&#8217;ll declare it as such in our <a href="http://msdn.microsoft.com/en-us/library/aa367091%28VS.85%29.aspx">IDL</a>:</p>
<div class="example">
<pre>[
   oleautomation,
   uuid(2D486A73-E912-4078-9F38-678226E4A0BD),
   dual,
   pointer_default(unique)
]
interface IRipsawFile : IDispatch
{
}</pre>
</div>
<p>The interface is also derived from <code>IDispatch</code> to support late-binding, which means that scripting languages can discover the methods and properties of the interface at runtime.</p>
<p>Before we can write the test script we&#8217;ll need decide what basic methods a Ripsaw object needs to implement. A single Ripsaw object will represent a connection to a file, and the object will fire events whenever the file changes so that listeners can take an action based on the update (change the display, parse the update, etc.). At a minimum, then, we need to be able to open a file and close a file.</p>
<div class="example">
<pre>interface IRipsawFile : IDispatch
{
   [id(1)] HRESULT Open(
      [in] BSTR fileName,
      [out,retval] VARIANT_BOOL* pSuccess);

   [id(2)] HRESULT Close();
}</pre>
</div>
<p>The <code>Open</code> method will accept a path to a file and return a Boolean indicating the success or failure of the method call. The <code>Close</code> method will close any existing connection, and we won&#8217;t bother to check for a return code from that method.</p>
<p>Now, it would probably be useful to be able to query a property of the object for the name of the file to which it is connected, and perhaps another property to check if the object is currently opened or closed. Let&#8217;s add those properties:</p>
<div class="example">
<pre>interface IRipsawFile : IDispatch
{
   [id(1), propget] HRESULT Name(
      [out,retval] BSTR* pName);

   [id(2), propget] HRESULT IsOpen(
      [out,retval] VARIANT_BOOL* pRetVal);

   [id(3)] HRESULT Open(
      [in] BSTR fileName,
      [out,retval] VARIANT_BOOL* pSuccess);

   [id(4)] HRESULT Close();
}</pre>
</div>
<p>Okay, not bad so far. We can open a file, query for the status, query for the name, and close the file. That&#8217;s no good if we can&#8217;t catch events fired by the object. We need to define a <code>dispinterface</code> that specifies the events that the object can fire at its clients:</p>
<div class="example">
<pre>[ uuid(6671C129-C761-42F3-AB2F-D12C33D95160) ]
dispinterface _IRipsawEvents
{
properties:
methods:
   [id(1)] HRESULT Open([in] BSTR fileName);
   [id(2)] HRESULT Close([in] BSTR fileName);
   [id(3)] HRESULT Update([in] BSTR updateData);
};</pre>
</div>
<p>The <code>Open</code> event fires when a file is opened successfully, of course. <code>Close</code> fires when a file is closed, and <code>Update</code> naturally fires when the file changes. The <code>Update</code> notification will also pass along the data that was gathered from the last file update.</p>
<p>Okay, based on those interfaces, our script might look like this:</p>
<div class="example">
<pre>var ripsaw = WScript.CreateObject("PMP.RipsawFile", "ripsaw_");

if (ripsaw)
{
   ripsaw.Open("testfile.log");

   if (ripsaw.IsOpen)
   {
      WScript.Echo("Ripsaw file is open: '" + ripsaw.Name + "'");

      /* Uh-oh... */

      ripsaw.Close();

      if (!ripsaw.IsOpen)
      {
         WScript.Echo("Ripsaw file is closed: '" + ripsaw.Name + "'");
      }
      else
      {
         WScript.Echo("ERROR: Ripsaw file reported open");
      }
   }
   else
   {
      WScript.Echo("ERROR: Ripsaw file reported closed");
   }
}
else
{
   WScript.Echo("ERROR: Failed to create Ripsaw file");
}

function ripsaw_Open(fileName)
{
   WScript.Echo("ripsaw_Open(" + fileName + ")")
}

function ripsaw_Close(fileName)
{
   WScript.Echo("ripsaw_Close(" + fileName + ")")
}

function ripsaw_Update(data)
{
   WScript.Echo("ripsaw_Update(" + data + ")")
}</pre>
</div>
<p>First of all, I&#8217;ll explain what all this means for those of you that are new to JavaScript — err, JScript — under <a href="http://msdn.microsoft.com/en-us/library/9bbdkx3k%28VS.85%29.aspx">Windows Script Host</a> (WSH). The first line creates a COM object based on its <a href="http://msdn.microsoft.com/en-us/library/dd542719%28VS.85%29.aspx">ProgID</a>, or programmatic identifier. This is a string that resolves, through the registry, to a <a href="http://en.wikipedia.org/wiki/Globally_Unique_Identifier">GUID</a> that uniquely identifies a COM library that provides the requested functionality.</p>
<p>The second parameter to <code>CreateObject</code> tells the scripting engine to wire events provided by the object to functions that start with the specified prefix. In our script, we want to handle the Open, Close, and Update notifications, so we created functions named <code>ripsaw_Open</code>, <code>ripsaw_Close</code>, and <code>ripsaw_Update</code> to catch these events. Since they all start with the &#8220;ripsaw_&#8221; prefix, the script engine will call them when any of the corresponding events are fired by our object.</p>
<p>If you looked carefully at the script, you noticed that I inserted a comment: &#8220;Uh-oh.&#8221; That&#8217;s because the script has no way of sitting and waiting for an update other than looping in a tight loop, and that is almost never a good idea. The script would waste CPU time doing nothing while we wait for the file to be updated. In other languages we have access to message loops, <code>WaitForSingleObject</code>, and other means of yielding CPU until an event occurs, but not in WSH. We need something better. What we&#8217;ll do is add a method to our object which, when called, will do absolutely nothing until an update occurs. We&#8217;ll call it <code>WaitForUpdate</code>.</p>
<div class="example">
<pre>interface IRipsawFile : IDispatch
{
   [id(1), propget] HRESULT Name(
      [out,retval] BSTR* pName);

   [id(2), propget] HRESULT IsOpen(
      [out,retval] VARIANT_BOOL* pRetVal);

   [id(3)] HRESULT Open(
      [in] BSTR fileName,
      [out,retval] VARIANT_BOOL* pSuccess);

   [id(4)] HRESULT Close();

   [id(5)] HRESULT WaitForUpdate(
      [in] ULONG timeout,
      [out,retval] BSTR* pNewData);
}</pre>
</div>
<p>The first parameter is a timeout, in milliseconds, so that the function will return if no updates arrive in the specified amount of time. We&#8217;ll take a page from Win32 and say that a value of 0xFFFFFFFF will tell the method to wait forever. If the timeout expires, the method will return a null <code>BSTR</code>; otherwise, the return value will be the new data from the last file update. We&#8217;ll modify the heart of our script to call the new method:</p>
<div class="example">
<pre>      WScript.Echo("Ripsaw file is open: '" + ripsaw.Name + "'");

      var timeout = 5000;
      WScript.Echo("Waiting for data...");
      var newData = ripsaw.WaitForUpdate(timeout);

      if (newData)
      {
         WScript.Echo("Waited for data:", newData);
      }
      else
      {
         WScript.Echo("Timed out after waiting for data for " + timeout + " milliseconds");
      }

      ripsaw.Close();</pre>
</div>
<p>In a real script we&#8217;ll probably call <code>WaitForUpdate</code> in a loop, but for now we&#8217;ll just wait for one update before exiting.</p>
<h3>Generalizing the Interface</h3>
<p>This looks good for files, but perhaps later on we&#8217;d like to extend Ripsaw to listen to other sources of events, like the <a href="http://msdn.microsoft.com/en-us/library/aa385780%28VS.85%29.aspx">Windows Event Log</a> (the first Ripsaw actually did that for a while, but I backed out the feature to focus on files). It would be a good idea to go ahead and factor out the common methods and properties into a base interface that could be extended by other event sources.</p>
<div class="example">
<pre>[
   oleautomation,
   uuid(0270FDFF-56AF-42ec-9971-AE8DCB0DAB36),
   dual,
   pointer_default(unique)
]
interface IRipsawObject : IDispatch
{
   [id(1), propget] HRESULT Name(
      [out,retval] BSTR* pName);

   [id(2), propget] HRESULT IsOpen(
      [out,retval] VARIANT_BOOL* pRetVal);

   [id(3)] HRESULT Close();

   [id(4)] HRESULT WaitForUpdate(
      [in] ULONG timeout,
      [out,retval] BSTR* pNewData);
};

[
   oleautomation,
   uuid(2D486A73-E912-4078-9F38-678226E4A0BD),
   dual,
   pointer_default(unique)
]
interface IRipsawFile : IRipsawObject
{
   [id(10)] HRESULT Open(
      [in] BSTR fileName,
      [out,retval] VARIANT_BOOL* pSuccess);
};</pre>
</div>
<p>Later on, if we define an interface for listening to event logs, we&#8217;ll derive that interface from <code>IRipsawObject</code> and define an <code>Open</code> method specific to event logs. We&#8217;ll also assign a special ProgID to event log objects so our client applications can create them:</p>
<div class="example">
<pre>var ripsaw = WScript.CreateObject("PMP.RipsawEventLog", "ripsaw_");</pre>
</div>
<h3>Next Steps</h3>
<p>Now we have an interface, and we have a script to exercise that interface. What we need next is some real code to implement the interface and a binary that the script can load and run. We&#8217;ll start on a preliminary implementation in the next article. Until then, you can download <a href="/ripsaw/articles/RipsawSource_20091109.zip">the IDL and the script file</a> and look them over. Please leave a comment with any suggestions you may have.</p>
<p><!-- fullpost --></p>
<a href="http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.parkscomputing.com%2F2009%2F11%2Fripsaw-com-interface-first-pass%2F&amp;t=Ripsaw%20COM%20Interface%2C%20First%20Pass" id="facebook_share_button_35" style="font-size:11px; line-height:13px; font-family:'lucida grande',tahoma,verdana,arial,sans-serif; text-decoration:none; display: -moz-inline-block; display:inline-block; padding:1px 20px 0 5px; margin: 5px 0; height:15px; border:1px solid #d8dfea; color: #3B5998; background: #fff url(http://b.static.ak.fbcdn.net/images/share/facebook_share_icon.gif) no-repeat top right;">Share</a>
	<script type="text/javascript">
	<!--
	var button = document.getElementById('facebook_share_link_35') || document.getElementById('facebook_share_icon_35') || document.getElementById('facebook_share_both_35') || document.getElementById('facebook_share_button_35');
	if (button) {
		button.onclick = function(e) {
			var url = this.href.replace(/share\.php/, 'sharer.php');
			window.open(url,'sharer','toolbar=0,status=0,width=626,height=436');
			return false;
		}
	
		if (button.id === 'facebook_share_button_35') {
			button.onmouseover = function(){
				this.style.color='#fff';
				this.style.borderColor = '#295582';
				this.style.backgroundColor = '#3b5998';
			}
			button.onmouseout = function(){
				this.style.color = '#3b5998';
				this.style.borderColor = '#d8dfea';
				this.style.backgroundColor = '#fff';
			}
		}
	}
	-->
	</script>
	]]></content:encoded>
			<wfw:commentRss>http://www.parkscomputing.com/2009/11/ripsaw-com-interface-first-pass/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Refining Ripsaw&#8217;s Design</title>
		<link>http://www.parkscomputing.com/2009/11/refining-ripsaws-design/</link>
		<comments>http://www.parkscomputing.com/2009/11/refining-ripsaws-design/#comments</comments>
		<pubDate>Fri, 06 Nov 2009 17:05:00 +0000</pubDate>
		<dc:creator>Paul Parks</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[ripsaw]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://nightowl/?p=34</guid>
		<description><![CDATA[In my last entry in the Ripsaw article series, I discussed some of the design goals for Ripsaw. In this article I&#8217;ll flesh out the design a little more and discuss specific implementation possibilities. To bring you up to speed, Ripsaw is a log-viewing utility for Windows that I initially wrote about six years ago, [...]]]></description>
			<content:encoded><![CDATA[<p>In my last entry in the <a href="/labels/ripsaw.html">Ripsaw article series</a>, I discussed some of the <a href="/2009/10/design-goals-for-ripsaw.html">design goals for Ripsaw</a>. In this article I&#8217;ll flesh out the design a little more and discuss specific implementation possibilities.</p>
<p>To bring you up to speed, Ripsaw is a log-viewing utility for Windows that I initially wrote about six years ago, but never released widely. I&#8217;ve decided to rewrite it and discuss each step of the rewrite here.<br />
<span id="more-34"></span></p>
<h3>Implementing the API</h3>
<p>The initial Ripsaw implementation was a monolithic (albeit small) application, but this time I want to separate the log-reading mechanism from the log-viewing UI. There are times when I&#8217;d like to use the log-reading capabilities of Ripsaw from JavaScript or <a href="http://technet.microsoft.com/en-us/scriptcenter/dd742419.aspx">PowerShell</a>, and I&#8217;d also like to write more than one viewer application around the log reader. There are at least three possible technologies for this API:</p>
<ol>
<li>C DLL</li>
<li>COM</li>
<li>.NET</li>
</ol>
<p>Okay, there are a lot more that I could choose from, but for the machines I&#8217;m targeting these are the most likely candidates. A DLL exporting C functions would be the simplest to write and would be easy to integrate with most programming languages, but in order to use that sort of API from JavaScript (or similar languages) I&#8217;d have to write a COM wrapper. A .NET implementation would be COM-callable, but it would require having .NET installed on the target machine, and sometimes the systems I debug don&#8217;t have .NET installed (hard to believe, I know, but true). COM, however, is ubiquitous on Windows, fairly straightforward, can be used from JavaScript with ease, and is easily callable from .NET if I had a reason to do so later on. Therefore, I&#8217;ll implement Ripsaw&#8217;s non-UI behavior in a COM library.</p>
<h3>What About Registration?</h3>
<p>I&#8217;d still like to be able to run Ripsaw from a USB drive without having to install anything on the machine I&#8217;m debugging or examining, which means I&#8217;d like to avoid the hassle of having to run <a href="http://technet.microsoft.com/en-us/library/bb490985.aspx">regsvr32</a> on the target machine before I can use Ripsaw. Fortunately, there is <a href="http://msdn.microsoft.com/en-us/library/ms973913.aspx">registration-free COM</a>, which will let me run a Ripsaw viewer that loads the Ripsaw COM library with the aid of a manifest. This will let me keep a viewer and the Ripsaw library in a directory on my USB drive so I can just plug it in and run the viewer without having to register or install anything.</p>
<h3>Supporting Scripting in the Viewer</h3>
<p>Since Ripsaw&#8217;s log-reading capability will be implemented in COM, I&#8217;ll be able to write JavaScript apps that can watch for data from a log file, and these scripts can either parse the data or take actions based on the data. Not only would this be useful apart from a viewer, but it might also be useful <em>inside</em> a viewer. I could define script actions to operate on log lines, highlight them, parse them, etc., while I&#8217;m watching a log in the viewer. To take advantage of this I&#8217;ll add JavaScript support to the Windows Ripsaw viewer, along with the capability to load pre-defined scripts that act on log data.</p>
<h3>Viewer Implementation</h3>
<p>In keeping with my requirement for making Ripsaw light and portable, I don&#8217;t want to use .NET for the main viewer implementation. I might create a <a href="http://msdn.microsoft.com/en-us/library/dd30h2yb.aspx">Windows Forms</a> or <a href="http://msdn.microsoft.com/en-us/library/aa663364.aspx">WPF</a> viewer later on once .NET becomes more widespread on the systems I mainly work on (point-of-sale terminals and servers for grocery stores), or for when I&#8217;m debugging in a controlled environment, but for the main console and GUI viewers I&#8217;ll use C++ as the development language. COM is still a bit of a pain to use from C++, at least compared to JavaScript or .NET, but it won&#8217;t be too bad.</p>
<h3>Multiprocessor Support</h3>
<p>Fortunately, the newer POS terminals and servers that are being installed today have multi-core processors, and I definitely want to take advantage of that today. I want to architect the core Ripsaw library to take advantage of multiple threads of execution spread across multiple processors or processor cores. I already write multi-threaded, multi-process systems for these machines, and these systems tend to be heavily instrumented, so sometimes I&#8217;m watching several different log files at once during a testing or debugging session. I don&#8217;t want to slow a system down too much when I start up the viewer, and loading down one core of a multi-core processor with a log viewer would certainly be a bad thing.</p>
<h3>Okay, Can We Start Coding Now?</h3>
<p>Actually, I already have been doing some prototyping, which helped me decide on the details I&#8217;ve described above. Now that I&#8217;ve sorted out some of the lower-level requirements, in the next article I&#8217;ll start defining the Ripsaw log-reader COM interface.</p>
<a href="http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.parkscomputing.com%2F2009%2F11%2Frefining-ripsaws-design%2F&amp;t=Refining%20Ripsaw%27s%20Design" id="facebook_share_button_34" style="font-size:11px; line-height:13px; font-family:'lucida grande',tahoma,verdana,arial,sans-serif; text-decoration:none; display: -moz-inline-block; display:inline-block; padding:1px 20px 0 5px; margin: 5px 0; height:15px; border:1px solid #d8dfea; color: #3B5998; background: #fff url(http://b.static.ak.fbcdn.net/images/share/facebook_share_icon.gif) no-repeat top right;">Share</a>
	<script type="text/javascript">
	<!--
	var button = document.getElementById('facebook_share_link_34') || document.getElementById('facebook_share_icon_34') || document.getElementById('facebook_share_both_34') || document.getElementById('facebook_share_button_34');
	if (button) {
		button.onclick = function(e) {
			var url = this.href.replace(/share\.php/, 'sharer.php');
			window.open(url,'sharer','toolbar=0,status=0,width=626,height=436');
			return false;
		}
	
		if (button.id === 'facebook_share_button_34') {
			button.onmouseover = function(){
				this.style.color='#fff';
				this.style.borderColor = '#295582';
				this.style.backgroundColor = '#3b5998';
			}
			button.onmouseout = function(){
				this.style.color = '#3b5998';
				this.style.borderColor = '#d8dfea';
				this.style.backgroundColor = '#fff';
			}
		}
	}
	-->
	</script>
	]]></content:encoded>
			<wfw:commentRss>http://www.parkscomputing.com/2009/11/refining-ripsaws-design/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Design Goals for Ripsaw</title>
		<link>http://www.parkscomputing.com/2009/10/design-goals-for-ripsaw/</link>
		<comments>http://www.parkscomputing.com/2009/10/design-goals-for-ripsaw/#comments</comments>
		<pubDate>Wed, 28 Oct 2009 00:47:00 +0000</pubDate>
		<dc:creator>Paul Parks</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[ripsaw]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://nightowl/?p=31</guid>
		<description><![CDATA[In this installment of the Ripsaw project series I&#8217;ll sketch out some of my design goals for the new version of Ripsaw, and the rationale for those goals. Split the App Into DLLs The original Ripsaw was a 32-bit Windows application contained in a single executable. This made it easy to carry around on a [...]]]></description>
			<content:encoded><![CDATA[<p>In this installment of the <a href="/2009/10/a-new-article-series-ripsaw/">Ripsaw</a> project series I&#8217;ll sketch out some of my design goals for the new version of Ripsaw, and the rationale for those goals.<br />
<span id="more-31"></span></p>
<h3>Split the App Into DLLs</h3>
<p>The original Ripsaw was a 32-bit Windows application contained in a single executable. This made it easy to carry around on a USB drive and run on machines that I needed to debug. The downsides were that I had to link the C runtime library into the executable, and application was one monolithic entity that couldn&#8217;t be easily extended.</p>
<p>For the new Ripsaw I&#8217;m going to build it to use the C runtime in a DLL. For most of the machines I work with this will require carrying around the C runtime distributable, but I&#8217;m willing to do that as long as I don&#8217;t have to install anything on the terminal. I&#8217;m not completely up to speed with side-by-side assemblies; I prefer to just place the VS 2010 C runtime DLL in the same directory as the executable and run the app, but I&#8217;ll have to verify that&#8217;s still supported. (Edit: It is. <em>Duh!</em>) So far SxS has caused me a lot of grief, but that&#8217;s probably because I haven&#8217;t bothered to really understand it.</p>
<h3>Create a Ripsaw API</h3>
<p>Since I&#8217;m splitting out the C runtime, I&#8217;m also going to separate most of Ripsaw&#8217;s non-visual functionality into a separate API DLL. Not only will this make the core functionality more testable and enforce separation of UI, but I&#8217;ll be able to build more than one user interface around it. I&#8217;d like to build a command-line application as well as a graphical application. Sometimes you just can&#8217;t beat raw text.</p>
<h3>Embrace 64-bit</h3>
<p>Even though nearly all of my professional development is still 32-bit, I want to build Ripsaw to compile for both 32-bit and 64-bit architectures. I&#8217;ll need to do this eventually anyway, and this is a good time to start.</p>
<h3>Support Extensibility</h3>
<p>My original plans for Ripsaw included the ability to create filters for processing log output as it arrived in the application. Perhaps only lines containing certain values would be displayed, or maybe certain words would be shown in a particular color or font. Rather than trying to build every possible behavior into Ripsaw, I&#8217;ll publish an extensibility interface so that I can add features later on (or <em>you</em> can add them) without having to change the core API or UI.</p>
<h3>Create a Windows 7 UI</h3>
<p>The main UI that I&#8217;ll use will be a 32-bit graphical application targeting Windows XP, but I&#8217;d also like to take advantage of some of the new Windows 7 user interface controls such as the ribbon. I&#8217;m not inclined to try to serve both interface styles from one application, so after I finish the primary UI I&#8217;ll create a version that is specific to Windows 7. Since I&#8217;m putting most of the non-visual behavior into a separate DLL I&#8217;ll be free to experiment with different interfaces anyway.</p>
<h3>Coming Up</h3>
<p>In the next few articles I&#8217;ll delve into some more development specifics such as language and library choices.</p>
<a href="http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.parkscomputing.com%2F2009%2F10%2Fdesign-goals-for-ripsaw%2F&amp;t=Design%20Goals%20for%20Ripsaw" id="facebook_share_button_31" style="font-size:11px; line-height:13px; font-family:'lucida grande',tahoma,verdana,arial,sans-serif; text-decoration:none; display: -moz-inline-block; display:inline-block; padding:1px 20px 0 5px; margin: 5px 0; height:15px; border:1px solid #d8dfea; color: #3B5998; background: #fff url(http://b.static.ak.fbcdn.net/images/share/facebook_share_icon.gif) no-repeat top right;">Share</a>
	<script type="text/javascript">
	<!--
	var button = document.getElementById('facebook_share_link_31') || document.getElementById('facebook_share_icon_31') || document.getElementById('facebook_share_both_31') || document.getElementById('facebook_share_button_31');
	if (button) {
		button.onclick = function(e) {
			var url = this.href.replace(/share\.php/, 'sharer.php');
			window.open(url,'sharer','toolbar=0,status=0,width=626,height=436');
			return false;
		}
	
		if (button.id === 'facebook_share_button_31') {
			button.onmouseover = function(){
				this.style.color='#fff';
				this.style.borderColor = '#295582';
				this.style.backgroundColor = '#3b5998';
			}
			button.onmouseout = function(){
				this.style.color = '#3b5998';
				this.style.borderColor = '#d8dfea';
				this.style.backgroundColor = '#fff';
			}
		}
	}
	-->
	</script>
	]]></content:encoded>
			<wfw:commentRss>http://www.parkscomputing.com/2009/10/design-goals-for-ripsaw/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A New Article Series: Ripsaw</title>
		<link>http://www.parkscomputing.com/2009/10/a-new-article-series-ripsaw/</link>
		<comments>http://www.parkscomputing.com/2009/10/a-new-article-series-ripsaw/#comments</comments>
		<pubDate>Mon, 26 Oct 2009 23:43:00 +0000</pubDate>
		<dc:creator>Paul Parks</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[ripsaw]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[utilities]]></category>
		<category><![CDATA[visual studio]]></category>

		<guid isPermaLink="false">http://nightowl/?p=30</guid>
		<description><![CDATA[Several years ago I wrote a Windows application called &#8220;Ripsaw&#8221; that implemented the basic functionality of the Unix tail utility in a graphical application, with a few twists of my own. I had intended to release the application as an open-source project, and although I still use the tool quite a bit I never got [...]]]></description>
			<content:encoded><![CDATA[<p>Several years ago I wrote a Windows application called &#8220;Ripsaw&#8221; that implemented the basic functionality of the Unix <a href="http://en.wikipedia.org/wiki/Tail_%28Unix%29">tail</a> utility in a graphical application, with a few twists of my own. I had intended to release the application as an open-source project, and although I still use the tool quite a bit I never got around to giving it the necessary polish for a public release. I&#8217;ve only shared it with a few friends and co-workers.</p>
<p>I&#8217;ve just downloaded Beta 2 of <a href="http://www.microsoft.com/visualstudio/en-us/products/2010/default.mspx">Microsoft Visual Studio 2010</a>, and I&#8217;ve decided to create a new version of Ripsaw from the ground up so that I can become familiar with the new IDE and compiler. Besides being a chance to finally get Ripsaw right, this will also be an opportunity to create a series of articles on how I develop a complete application, from the first ideas through design, implementation, testing, and release. I&#8217;ll walk you through all of the design decisions and trade-offs, the problems I run into along the way, and the development methodologies I use.</p>
<p>I would really appreciate your feedback, ideas, suggestions, and criticisms. This is going to be fun!</p>
<a href="http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.parkscomputing.com%2F2009%2F10%2Fa-new-article-series-ripsaw%2F&amp;t=A%20New%20Article%20Series%3A%20Ripsaw" id="facebook_share_button_30" style="font-size:11px; line-height:13px; font-family:'lucida grande',tahoma,verdana,arial,sans-serif; text-decoration:none; display: -moz-inline-block; display:inline-block; padding:1px 20px 0 5px; margin: 5px 0; height:15px; border:1px solid #d8dfea; color: #3B5998; background: #fff url(http://b.static.ak.fbcdn.net/images/share/facebook_share_icon.gif) no-repeat top right;">Share</a>
	<script type="text/javascript">
	<!--
	var button = document.getElementById('facebook_share_link_30') || document.getElementById('facebook_share_icon_30') || document.getElementById('facebook_share_both_30') || document.getElementById('facebook_share_button_30');
	if (button) {
		button.onclick = function(e) {
			var url = this.href.replace(/share\.php/, 'sharer.php');
			window.open(url,'sharer','toolbar=0,status=0,width=626,height=436');
			return false;
		}
	
		if (button.id === 'facebook_share_button_30') {
			button.onmouseover = function(){
				this.style.color='#fff';
				this.style.borderColor = '#295582';
				this.style.backgroundColor = '#3b5998';
			}
			button.onmouseout = function(){
				this.style.color = '#3b5998';
				this.style.borderColor = '#d8dfea';
				this.style.backgroundColor = '#fff';
			}
		}
	}
	-->
	</script>
	]]></content:encoded>
			<wfw:commentRss>http://www.parkscomputing.com/2009/10/a-new-article-series-ripsaw/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>An API is Forever</title>
		<link>http://www.parkscomputing.com/2009/05/an-api-is-forever/</link>
		<comments>http://www.parkscomputing.com/2009/05/an-api-is-forever/#comments</comments>
		<pubDate>Fri, 08 May 2009 18:36:00 +0000</pubDate>
		<dc:creator>Paul Parks</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://nightowl/?p=25</guid>
		<description><![CDATA[An API is an interface. Those of you that have worked with COM already know that once an interface is published, it can never, ever change. Ever. Not until the end of time. The reason is that some bit of code somewhere is going to be using that interface, and if you change it you&#8217;ve [...]]]></description>
			<content:encoded><![CDATA[<p>An <a href="http://en.wikipedia.org/wiki/API">API</a> is an <a href="http://en.wikipedia.org/wiki/Interface_(computer_science)">interface</a>. Those of you that have worked with <a href="http://en.wikipedia.org/wiki/Component_Object_Model">COM</a> already know that <a href="http://blogs.msdn.com/oldnewthing/archive/2005/11/01/487658.aspx">once an interface is published, it can never, ever change</a>. Ever. Not until the end of time. The reason is that some bit of code somewhere is going to be using that interface, and if you change it you&#8217;ve just broken that code. Of course, not changing an interface also means not deleting a portion of it.</p>
<p><span id="more-25"></span>(I apologize for the corrupted formatting of the code. I&#8217;m in the middle of a conversion from Blogger to WordPress.)</p>
<p>At my job I have worked on, and currently maintain, a few APIs implemented in Windows <a href="http://en.wikipedia.org/wiki/Dynamic-link_library">DLLs</a>, some of which have been around for a long time. I had to rewrite significant portions of the internal implementation of one particular DLL in order to add some new features, fix several bugs, and improve the overall performance of the DLL. The old API exposed from the DLL wasn&#8217;t able to take advantage of the new features, and it wasn&#8217;t designed all that well to begin with. Since nearly all of the use of that API was through a C++ template wrapper implemented a header, I just added a new set of API functions and changed the wrapper to use the new API.</p>
<p>I did some digging around in the code base (it&#8217;s a huge code base) to see what else was using the class wrapper around the DLL, and I found out that the component was in far more widespread use than I had anticipated. There were components in all corners of the code base using it now.</p>
<p>The component was still desperately in need of a new API, so what I did was write a new one and forward the old API to the new API. I changed the header file that declared the API functions to look like this:</p>
<div class="example">
<pre>FICTIONAL_API void NaDoStuff(   HANDLE hFict,   DWORD flags,    LPCSTR name,   LPCVOID bytes,    DWORD byteCount,   LPCSTR desc);

// The rest of the new API was declared here...// ...// ...

/************************************************************************Old, deprecated API. This API is still supported, but calls to all of these functions are now forwarded to the new API described above. Please use only the new API in new code.************************************************************************/

/* DEPRECATED: Use NaDoStuff instead. */FICTIONAL_API BOOL OaDoStuff(   HANDLE hFict,   DWORD flags,    LPCSTR desc,   LPCVOID bytes,    DWORD byteCount);

// The rest of the old API was declared here...// ...// ...</pre>
</div>
<p>I hoped that the comments would make clear that the use of the old API is discouraged, and that any clients should move to the new API. Likewise, in the implementation, I forwarded the old API functions to the new API functions:</p>
<div class="example">
<pre>FICTIONAL_API void NaDoStuff(   HANDLE hFict,   DWORD flags,    LPCSTR name,   LPCVOID bytes,    DWORD byteCount,   LPCSTR desc){   // Go do stuff}

// Elsewhere in the code..

FICTIONAL_API BOOL OaDoStuff(   HANDLE hFict,   DWORD flags,    LPCSTR desc,   LPCVOID bytes,    DWORD byteCount){   NaDoStuff(hFict, flags, "", bytes, byteCount, desc);   return TRUE;}</pre>
</div>
<p>In some cases, forwarding the old API to the new API meant that I had to make the new API implement the semantics of the old API whenever it was being called through the old API functions. For example, the old API had a nasty habit of writing sub-keys all over the company&#8217;s registry key under HKLM\SOFTWARE. I made the new API put these settings into a tidy sub-key that belonged to the API, like HKLM\SOFTWARE\ComanyName\Fictional. It would even hunt down the all of the old keys created by the old API and move them into the new sub-key. In a later story I&#8217;ll explain why I had to preserve that behavior in the old API, but for now just remember that I did.</p>
<p>Recently, a co-worker changed a customer-specific branch of the archive so that it would point to the newest implementation of this component. He was writing an application using some libraries that called this component&#8217;s API. He asked me to help with at a problem he was having, and when I went to look in the registry at some of the settings the API had written, I was dismayed to find that the settings were in the old location, all over the root of the company&#8217;s HKLM\SOFTWARE key. At first, I thought that he was still somehow using the old DLL, but when I checked the version information on the DLL it was, indeed, the new one. How could this be?</p>
<p>As I mentioned above, most clients use this DLL through a C++ wrapper, since most of the archive is now C++. Only a handful of older C modules call this API directly. The wrapper is a C++ template class, which means it is implemented in a header file. This customer archive was still pointing at the old version the header that called the old API. As I mentioned above, the new API preserves the semantics of the old API <span style="font-style: italic;">when it is called through the old API</span>, and that&#8217;s what we were seeing here.</p>
<p>My first suggestion, without really thinking about it, was to change the archive to point at the newer header. My co-worker pointed out that this would mean rebuilding <span style="font-weight: bold;">all</span> of the components in the archive that used the header, not just the one he was working on.</p>
<p>We left it alone, and everything is working as it should be. At some point in the future we&#8217;ll move all of the other components up to the newer version of the wrapper, and they&#8217;ll start seeing the behavior associated with the new API. In the meantime, the customer still benefit from a less buggy and more efficient component.</p>
<a href="http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.parkscomputing.com%2F2009%2F05%2Fan-api-is-forever%2F&amp;t=An%20API%20is%20Forever" id="facebook_share_button_25" style="font-size:11px; line-height:13px; font-family:'lucida grande',tahoma,verdana,arial,sans-serif; text-decoration:none; display: -moz-inline-block; display:inline-block; padding:1px 20px 0 5px; margin: 5px 0; height:15px; border:1px solid #d8dfea; color: #3B5998; background: #fff url(http://b.static.ak.fbcdn.net/images/share/facebook_share_icon.gif) no-repeat top right;">Share</a>
	<script type="text/javascript">
	<!--
	var button = document.getElementById('facebook_share_link_25') || document.getElementById('facebook_share_icon_25') || document.getElementById('facebook_share_both_25') || document.getElementById('facebook_share_button_25');
	if (button) {
		button.onclick = function(e) {
			var url = this.href.replace(/share\.php/, 'sharer.php');
			window.open(url,'sharer','toolbar=0,status=0,width=626,height=436');
			return false;
		}
	
		if (button.id === 'facebook_share_button_25') {
			button.onmouseover = function(){
				this.style.color='#fff';
				this.style.borderColor = '#295582';
				this.style.backgroundColor = '#3b5998';
			}
			button.onmouseout = function(){
				this.style.color = '#3b5998';
				this.style.borderColor = '#d8dfea';
				this.style.backgroundColor = '#fff';
			}
		}
	}
	-->
	</script>
	]]></content:encoded>
			<wfw:commentRss>http://www.parkscomputing.com/2009/05/an-api-is-forever/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Pre-emptive Snarkiness</title>
		<link>http://www.parkscomputing.com/2009/04/pre-emptive-snarkiness/</link>
		<comments>http://www.parkscomputing.com/2009/04/pre-emptive-snarkiness/#comments</comments>
		<pubDate>Wed, 15 Apr 2009 20:52:00 +0000</pubDate>
		<dc:creator>Paul Parks</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://nightowl/?p=19</guid>
		<description><![CDATA[It&#8217;s all about the sense of humor, people. First of all, read the &#8220;pre-emptive snarky comment&#8221; that I wrote in the earlier entry about the dragsens utility. It&#8217;s pretty clear that, first of all, I&#8217;m tipping my hat to Raymond Chen by even adding a pre-emptive snarky comment. Second, it should also be clear that [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s all about the sense of humor, people. First of all, read the &#8220;pre-emptive snarky comment&#8221; that I wrote in the <a href="/2009/04/windows-drag-sensitivity-utility.html">earlier entry</a> about the <em>dragsens</em> utility. It&#8217;s pretty clear that, first of all, I&#8217;m tipping my hat to Raymond Chen by even adding a pre-emptive snarky comment. Second, it should also be clear that I&#8217;m mentioning the size only because I&#8217;m trying to head off any snarky comments about it. Alas, that just doesn&#8217;t stop some people.</p>
<p>In my <a href="http://blogs.msdn.com/oldnewthing/archive/2009/04/10/9541813.aspx#9543899">first comment to Raymond&#8217;s article</a> I mentioned that it took me only eleven minutes to write the utility. That was the entire point of the exercise, really. If the utility happens to be useful as well, that&#8217;s fantastic. In fact, the reason that I bothered to take an extra 30 seconds and link in the C runtime was to make it easier to use. Just copy it to your favorite USB drive, and off you go. If you don&#8217;t have 84KB free on your drive for the <a href="dragsens.zip">ZIP file</a>, then that&#8217;s still okay. You can download the <a href="/code/dragsens_src.zip">source and VS project</a> and build it any way you like. Not a problem.</p>
<p>So, despite the fact that I <strong>clearly stated</strong> that I was aware that I could make the utility very tiny if I wanted to take the time to do so (when I said, &#8220;Of course you could. So could I.&#8221;), someone still didn&#8217;t get it. I guess <a href="http://blogs.msdn.com/oldnewthing/archive/2009/04/10/9541813.aspx#9547397">quoting me out of context</a>, or perhaps even <a href="http://blogs.msdn.com/oldnewthing/archive/2009/04/10/9541813.aspx#9550342">putting words in my mouth</a>, is more fun.</p>
<p>If I wanted to make it smaller, perhaps I could dispense with the CRT altogether. Perhaps I could write it in assembly language. Who knows. <em>It doesn&#8217;t matter.</em> I just wasn&#8217;t inclined to take any more time gold-plating what I regarded as a very simple exercise. The utility does what it is supposed to do, with a very tiny investment in programming time. That&#8217;s all I was out to prove. I made the source freely available, with no strings, in case anyone wanted to tweak it to handle some situation that I didn&#8217;t think about, or perhaps wanted a different implementation (like setting the width and height separately).</p>
<p>As Raymond might say, I can&#8217;t believe I had to write that.</p>
<a href="http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.parkscomputing.com%2F2009%2F04%2Fpre-emptive-snarkiness%2F&amp;t=Pre-emptive%20Snarkiness" id="facebook_share_button_19" style="font-size:11px; line-height:13px; font-family:'lucida grande',tahoma,verdana,arial,sans-serif; text-decoration:none; display: -moz-inline-block; display:inline-block; padding:1px 20px 0 5px; margin: 5px 0; height:15px; border:1px solid #d8dfea; color: #3B5998; background: #fff url(http://b.static.ak.fbcdn.net/images/share/facebook_share_icon.gif) no-repeat top right;">Share</a>
	<script type="text/javascript">
	<!--
	var button = document.getElementById('facebook_share_link_19') || document.getElementById('facebook_share_icon_19') || document.getElementById('facebook_share_both_19') || document.getElementById('facebook_share_button_19');
	if (button) {
		button.onclick = function(e) {
			var url = this.href.replace(/share\.php/, 'sharer.php');
			window.open(url,'sharer','toolbar=0,status=0,width=626,height=436');
			return false;
		}
	
		if (button.id === 'facebook_share_button_19') {
			button.onmouseover = function(){
				this.style.color='#fff';
				this.style.borderColor = '#295582';
				this.style.backgroundColor = '#3b5998';
			}
			button.onmouseout = function(){
				this.style.color = '#3b5998';
				this.style.borderColor = '#d8dfea';
				this.style.backgroundColor = '#fff';
			}
		}
	}
	-->
	</script>
	]]></content:encoded>
			<wfw:commentRss>http://www.parkscomputing.com/2009/04/pre-emptive-snarkiness/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows Drag Sensitivity Utility</title>
		<link>http://www.parkscomputing.com/2009/04/windows-drag-sensitivity-utility/</link>
		<comments>http://www.parkscomputing.com/2009/04/windows-drag-sensitivity-utility/#comments</comments>
		<pubDate>Fri, 10 Apr 2009 19:10:00 +0000</pubDate>
		<dc:creator>Paul Parks</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[utilities]]></category>

		<guid isPermaLink="false">http://nightowl/?p=18</guid>
		<description><![CDATA[Inspired by an article by Raymond Chen about how to correctly change the Windows mouse drag sensitivity, I wrote a quick utility called dragsens. It&#8217;s a small command-line utility that will allow you to change the number of pixels the mouse has to travel before a drag operation is initiated. Just download and unzip the [...]]]></description>
			<content:encoded><![CDATA[<p>Inspired by an article by Raymond Chen about  <a href="http://blogs.msdn.com/oldnewthing/archive/2009/04/10/9541813.aspx">how to correctly change the Windows mouse drag sensitivity</a>, I wrote a quick <a href="http://www.parkscomputing.com/dragsens.zip">utility called <em>dragsens</em></a>. It&#8217;s a small command-line utility that will allow you to change the number of pixels the mouse has to travel before a drag operation is initiated. Just download and unzip the utility, then run it at the command line, supplying a single parameter that is the number of pixels for the mouse to travel.</p>
<p>If you&#8217;d like modify the utility, or examine its source, you may <a href="http://www.parkscomputing.com/code/dragsens_src.zip">download the Visual Studio 2008 project</a>. If you just want the utility itself, you may <a href="http://www.parkscomputing.com/dragsens.zip">download a ZIP of the executable</a>.<br />
<span id="more-18"></span></p>
<h3 id="about">About the Utility</h3>
<p>The utility is actually very simple. It accepts a single parameter, which is the number of pixels the mouse must travel with a button depressed before the motion registers as a drag action. Rather than separate out the width and height, I just set both to the same number since this is generally all that&#8217;s necessary.</p>
<div class="example">
<pre>BOOL success = FALSE;

success = SystemParametersInfo(SPI_SETDRAGWIDTH, numPixels, NULL, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);

if (!success)
{
  DWORD error = GetLastError();
  std::wcout < < L"Error " << std::hex << error << std::dec << " while setting drag width." << std::endl;
  return 1;
}

success = SystemParametersInfo(SPI_SETDRAGHEIGHT, numPixels, NULL, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);

if (!success)
{
  DWORD error = GetLastError();
  std::wcout << L"Error " << std::hex << error << std::dec << " while setting drag height." << std::endl;
  return 1;
}</pre>
</pre>
</div>
<p>It would be fairly simple to modify the application to set the width and height independently, if you so desired.</p>
<h3 id="update">Update</h3>
<p>I&#8217;m already at version 1.1. I decided to add a version resource and support for a &#8220;/?&#8221; parameter.</p>
<a href="http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.parkscomputing.com%2F2009%2F04%2Fwindows-drag-sensitivity-utility%2F&amp;t=Windows%20Drag%20Sensitivity%20Utility" id="facebook_share_button_18" style="font-size:11px; line-height:13px; font-family:'lucida grande',tahoma,verdana,arial,sans-serif; text-decoration:none; display: -moz-inline-block; display:inline-block; padding:1px 20px 0 5px; margin: 5px 0; height:15px; border:1px solid #d8dfea; color: #3B5998; background: #fff url(http://b.static.ak.fbcdn.net/images/share/facebook_share_icon.gif) no-repeat top right;">Share</a>
	<script type="text/javascript">
	<!--
	var button = document.getElementById('facebook_share_link_18') || document.getElementById('facebook_share_icon_18') || document.getElementById('facebook_share_both_18') || document.getElementById('facebook_share_button_18');
	if (button) {
		button.onclick = function(e) {
			var url = this.href.replace(/share\.php/, 'sharer.php');
			window.open(url,'sharer','toolbar=0,status=0,width=626,height=436');
			return false;
		}
	
		if (button.id === 'facebook_share_button_18') {
			button.onmouseover = function(){
				this.style.color='#fff';
				this.style.borderColor = '#295582';
				this.style.backgroundColor = '#3b5998';
			}
			button.onmouseout = function(){
				this.style.color = '#3b5998';
				this.style.borderColor = '#d8dfea';
				this.style.backgroundColor = '#fff';
			}
		}
	}
	-->
	</script>
	]]></content:encoded>
			<wfw:commentRss>http://www.parkscomputing.com/2009/04/windows-drag-sensitivity-utility/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>

