<?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; visual studio</title>
	<atom:link href="http://www.parkscomputing.com/labels/visual-studio/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>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>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>
	</channel>
</rss>

