
<rss version="2.0">
  <channel>
    <title>Dblock.org | Code</title>
    <description>technology website</description>
    <link>http://code.dblock.org/</link>
    <language>en-us</language>
    <image>
      <url>http://code.dblock.org/images/blog/blog.gif</url>
      <title>Dblock.org | Code</title>
      <link>http://code.dblock.org/</link>
      <width>72</width>
      <height>49</height>
    </image>
    
      <item>
       <title>VMWare Tasks Library</title>
       <pubDate>Sat, 03 Jan 2009 14:15:00 GMT</pubDate>
       <description>
         <![CDATA[
          <link rel="stylesheet" href='http://code.dblock.org/Style.css' />
          <html><div><stripped><P><IMG style="MARGIN-RIGHT: 20px" height="63" alt="VMWare" src="http://www.codeproject.com/KB/library/VMWareTasks/VMWareLogo.jpg" width="160" align="right" /></P>
<P>The <STRONG>VMWare Tasks Library </STRONG>is a managed C# wrapper on top of VMWare COM ViX API that makes it really easy to use.</P>
<UL>
<LI><A href="http://code.dblock.org/source/VMWareTasks/Vestris.VMWareTasks.zip">Download Latest Build</A> <FONT color="#ff0000"><STRONG>(1.0.1604.0, updated Jan 03, 2009)</STRONG></FONT> 
</LI><LI><A href="http://www.codeproject.com/KB/library/VMWareTasks.aspx">CodeProject Article</A> 
</LI><LI><A href="http://svn.vestris.com/listing.php?repname=Vestris+SVN&path=%2Fcodeproject%2FVMWareTasks%2FSource%2FVMWareLib%2F#_codeproject_VMWareTasks_Source_VMWareLib_">Live source code in SVN</A> </LI></UL>
<P><FONT size="1">Features:</FONT></P>
<UL>
<LI><FONT size="1">a much more natural and easy programming model</FONT>
</LI><LI><FONT size="1">supports virtual machine VI (ESX) and Workstation </FONT>
</LI><LI><FONT size="1">enumerate and power Virtual Machines </FONT>
</LI><LI><FONT size="1">enumerate, revert and power snapshots </FONT>
</LI><LI><FONT size="1">execute commands in guest OS </FONT>
</LI><LI><FONT size="1">list and delete files and directories with subdirectories in guest OS </FONT>
</LI><LI><FONT size="1">manage shared folders </FONT>
</LI><LI><FONT size="1">read and write guest and environment variables</FONT></LI></UL></stripped></div><div><a href="http://code.dblock.org/ShowPost.aspx?id=29">Read</a> | Updated 1/3/2009</div></html>
         ]]>
       </description>
       <category>vmware</category>
       <link>http://code.dblock.org/ShowPost.aspx?Id=29</link>
       <guid isPermaLink="false">http://code.dblock.org/Post/29</guid>
      </item>
     
      <item>
       <title>Abstracting a cumbersome construct in VIX API: GetNumProperties + GetNthProperty</title>
       <pubDate>Sat, 27 Dec 2008 22:15:00 GMT</pubDate>
       <description>
         <![CDATA[
          <link rel="stylesheet" href='http://code.dblock.org/Style.css' />
          <html><div><stripped><P>Did I tell you how much I love <STRONG><A href="http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx">yield return</A></STRONG>?</P>
<P>One of the peculiar VIX COM API constructs is the combination that returns arrays of properties. This is done with two functions: <CODE>GetNumProperties</CODE> and <CODE>GetNthProperties</CODE>. The first returns the number of property arrays returned by the job and the second fetches a property array at a given index. The first obvious step is to wrap the functions within the job class. </P><div class="code"><pre><PRE><BLOCKQUOTE style="MARGIN-RIGHT: 0px"><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"><P>public</P></FONT></FONT><FONT size="2"> T GetNthProperties&lt;T&gt;(</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">int</FONT></FONT><FONT size="2"> index, </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">object</FONT></FONT><FONT size="2">[] properties)<P>{</P><P></P></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">   object</FONT></FONT><FONT size="2"> result = </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">null</FONT></FONT><FONT size="2">;<P>   VMWareInterop.Check(_handle.GetNthProperties(</P><P>      index, properties, <FONT color="#0000ff">ref</FONT><FONT size="2"> </FONT><FONT color="#000000" size="2">result</FONT></P></FONT><FONT size="2">));<P></P></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">   return</FONT></FONT><FONT size="2"> (T) result;<P>}</P><P> </P></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"><P>public</P></FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">int</FONT></FONT><FONT size="2"> GetNumProperties(</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">int</FONT></FONT><FONT size="2"> property)<P>{</P><P></P></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">   return</FONT></FONT><FONT size="2"> _handle.GetNumProperties(property);<P>}</P></FONT>  </BLOCKQUOTE></PRE></pre></div> 
<P>We can now write such properties as <CODE>RunningVirtualMachines</CODE>. </P><div class="code"><pre><PRE><BLOCKQUOTE style="MARGIN-RIGHT: 0px"><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"><P>public</P></FONT></FONT><FONT size="2"> IEnumerable&lt;VMWareVirtualMachine&gt; RunningVirtualMachines<P>{</P><P></P></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">   get</FONT></FONT><FONT size="2"><P>   {</P><P>      VMWareJob job = </P></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">new</FONT></FONT><FONT size="2"> VMWareJob(_handle.FindItems(</FONT><P><FONT size="2">         Constants.VIX_FIND_RUNNING_VMS, </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">null</FONT></FONT><FONT size="2">, -1, </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">null</FONT></FONT><FONT size="2">));</FONT></P><P>      job.Wait(VMWareInterop.Timeouts.FindItemsTimeout);</P><P><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">      object</FONT></FONT><FONT size="2">[] properties = { Constants.VIX_PROPERTY_FOUND_ITEM_LOCATION };</FONT></P><P><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">      for</FONT></FONT><FONT size="2"> (</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">int</FONT></FONT><FONT size="2"> i = 0; i &lt; job.GetNumProperties((</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">int</FONT></FONT><FONT size="2">) properties[0]); i++)</FONT></P><P>      {</P><P><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">         yield</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">return</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">this</FONT></FONT><FONT size="2">.Open(</FONT></P><P>            (<FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2">) job.GetNthProperties&lt;</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">object</FONT></FONT><FONT size="2">[]&gt;(</FONT></P><P><FONT size="2">               i, properties)[0]);</FONT></P><P>      }</P><P>   }</P><P>}  </P></BLOCKQUOTE></PRE></pre></div> 
<P>This is still not good enough. Let's combine the number of results and the results themselves in a <CODE>YieldWait</CODE> method. </P><div class="code"><pre><PRE><BLOCKQUOTE style="MARGIN-RIGHT: 0px"><FONT size="2"><P></P></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">public</FONT></FONT><FONT size="2"> </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">IEnumerable</FONT></FONT><FONT size="2">&lt;</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">object</FONT></FONT><FONT size="2">[]&gt; YieldWait(</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">object</FONT></FONT><FONT size="2">[] properties, </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">int</FONT></FONT><FONT size="2"> timeoutInSeconds)<P>{</P><P>   Wait(timeoutInSeconds);</P><P></P></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">   for</FONT></FONT><FONT size="2"> (</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">int</FONT></FONT><FONT size="2"> i = 0; i &lt; GetNumProperties((</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">int</FONT></FONT><FONT size="2">)properties[0]); i++)<P>   {</P><P></P></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">      yield</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">return</FONT></FONT><FONT size="2"> GetNthProperties&lt;</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">object</FONT></FONT><FONT size="2">[]&gt;(i, properties);<P>   }</P><P>}</P></FONT> </BLOCKQUOTE></PRE></pre></div> 
<P>This results in a nice improvement over the previous implementation: we're interating over a resultset rather than calling methods for how many results are available and to fetch each result.</P><div class="code"><pre><PRE><BLOCKQUOTE style="MARGIN-RIGHT: 0px"><FONT size="2"><P></P></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">public</FONT></FONT><FONT size="2"> </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">IEnumerable</FONT></FONT><FONT size="2">&lt;</FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">VMWareVirtualMachine</FONT></FONT><FONT size="2">&gt; RunningVirtualMachines<P>{</P><P></P></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">   get</FONT></FONT><FONT size="2"><P>   {</P><P></P></FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">      VMWareJob</FONT></FONT><FONT size="2"> job = </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">new</FONT></FONT><FONT size="2"> </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">VMWareJob</FONT></FONT><FONT size="2">(_handle.FindItems(</FONT><P><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">         Constants</FONT></FONT><FONT size="2">.VIX_FIND_RUNNING_VMS, </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">null</FONT></FONT><FONT size="2">, -1, </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">null</FONT></FONT><FONT size="2">));</FONT></P><P><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">      object</FONT></FONT><FONT size="2">[] properties = { </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">Constants</FONT></FONT><FONT size="2">.VIX_PROPERTY_FOUND_ITEM_LOCATION };</FONT></P><P><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">      foreach</FONT></FONT><FONT size="2"> (</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">object</FONT></FONT><FONT size="2">[] runningVirtualMachine </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">in</FONT></FONT><FONT size="2"> job.YieldWait(</FONT></P><P><FONT size="2">         properties, </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">VMWareInterop</FONT></FONT><FONT size="2">.Timeouts.FindItemsTimeout))</FONT></P><P>      {</P><P><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">         yield</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">return</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">this</FONT></FONT><FONT size="2">.Open((</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2">) runningVirtualMachine[0]);</FONT></P><P>      }</P><P>   }</P><P>}  </P></BLOCKQUOTE></PRE></pre></div> 
<P>
</P><P></P></stripped></div><div><a href="http://code.dblock.org/ShowPost.aspx?id=28">Read</a> | Updated 12/27/2008</div></html>
         ]]>
       </description>
       <category>vmware</category>
       <link>http://code.dblock.org/ShowPost.aspx?Id=28</link>
       <guid isPermaLink="false">http://code.dblock.org/Post/28</guid>
      </item>
     
      <item>
       <title>Getting the display name of a VMWare snapshot</title>
       <pubDate>Fri, 26 Dec 2008 14:00:00 GMT</pubDate>
       <description>
         <![CDATA[
          <link rel="stylesheet" href='http://code.dblock.org/Style.css' />
          <html><div><stripped><P style="MARGIN-RIGHT: 0px">Looking at the source code of <A href="http://www.codeplex.com/VixCOMWrapper">another VMWare C# wrapper on CodePlex</A>, turns out that most VMWare interfaces represent VMWare handles. This is a good decision from the design point of view, but the implementation in VMWare VIX API is wrong: it should be returning objects that implement multiple interfaces, instead it returns one of the interfaces that you can happily cast to another.</P>
<P>This does answer the question of how to get the display name of a VMWare snapshot.</P>
<P>Let's add a wrapper for a VIX handle.</P>
<BLOCKQUOTE style="MARGIN-RIGHT: 0px">
<P></P><div class="code"><pre><BR /><FONT color="#808080" size="2"><FONT color="#808080" size="2">///</FONT></FONT><FONT color="#008000" size="2"><FONT color="#008000" size="2"> </FONT></FONT><FONT color="#808080" size="2"><FONT color="#808080" size="2">&lt;summary&gt;<BR /></FONT></FONT><FONT color="#808080" size="2"><FONT color="#808080" size="2">///</FONT></FONT><FONT color="#008000" size="2"><FONT color="#008000" size="2"> A wrapper for a VIX handle. Most VIX objects returned also implement IVixHandle.<BR /></FONT></FONT><FONT color="#808080" size="2"><FONT color="#808080" size="2">///</FONT></FONT><FONT color="#008000" size="2"><FONT color="#008000" size="2"> </FONT></FONT><FONT color="#808080" size="2"><FONT color="#808080" size="2">&lt;/summary&gt;<BR /></FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">public</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">class</FONT></FONT><FONT size="2"> </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">VMWareVixHandle<BR /></FONT></FONT><FONT size="2">{<BR /> </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">IVixHandle</FONT></FONT><FONT size="2"> _handle = </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">null</FONT></FONT><FONT size="2">;<BR /> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">public</FONT></FONT><FONT size="2"> VMWareVixHandle(</FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">IVixHandle</FONT></FONT><FONT size="2"> handle)<BR /> {<BR />  _handle = handle;<BR /> }<BR /><BR /> </FONT><FONT color="#808080" size="2"><FONT color="#808080" size="2">///</FONT></FONT><FONT color="#008000" size="2"><FONT color="#008000" size="2"> </FONT></FONT><FONT color="#808080" size="2"><FONT color="#808080" size="2">&lt;summary&gt;<BR /> </FONT></FONT><FONT color="#808080" size="2"><FONT color="#808080" size="2">///</FONT></FONT><FONT color="#008000" size="2"><FONT color="#008000" size="2"> Get an array of properties.<BR /> </FONT></FONT><FONT color="#808080" size="2"><FONT color="#808080" size="2">///</FONT></FONT><FONT color="#008000" size="2"><FONT color="#008000" size="2"> </FONT></FONT><FONT color="#808080" size="2"><FONT color="#808080" size="2">&lt;/summary&gt;<BR /> </FONT></FONT><FONT color="#808080" size="2"><FONT color="#808080" size="2">///</FONT></FONT><FONT color="#008000" size="2"><FONT color="#008000" size="2"> </FONT></FONT><FONT color="#808080" size="2"><FONT color="#808080" size="2">&lt;param name="properties"&gt;</FONT></FONT><FONT color="#008000" size="2"><FONT color="#008000" size="2">properties to fetch</FONT></FONT><FONT color="#808080" size="2"><FONT color="#808080" size="2">&lt;/param&gt;<BR /> </FONT></FONT><FONT color="#808080" size="2"><FONT color="#808080" size="2">///</FONT></FONT><FONT color="#008000" size="2"><FONT color="#008000" size="2"> </FONT></FONT><FONT color="#808080" size="2"><FONT color="#808080" size="2">&lt;returns&gt;</FONT></FONT><FONT color="#008000" size="2"><FONT color="#008000" size="2">an array of property values</FONT></FONT><FONT color="#808080" size="2"><FONT color="#808080" size="2">&lt;/returns&gt;<BR /> </FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">public</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">object</FONT></FONT><FONT size="2">[] GetProperties(</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">object</FONT></FONT><FONT size="2">[] properties)<BR /> {<BR />  </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">object</FONT></FONT><FONT size="2"> result = </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">null</FONT></FONT><FONT size="2">;<BR />  </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">VMWareInterop</FONT></FONT><FONT size="2">.Check(_handle.GetProperties(properties, </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">ref</FONT></FONT><FONT size="2"> result));<BR />  </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">return</FONT></FONT><FONT size="2"> (</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">object</FONT></FONT><FONT size="2">[]) result;<BR /> }<BR />}<BR /></FONT></pre></div></BLOCKQUOTE>
<P>Then the snapshot's name is a cast to a IVixHandle which implements GetProperties.</P>
<BLOCKQUOTE style="MARGIN-RIGHT: 0px">
<P></P><div class="code"><pre><BR /><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">public</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2"> DisplayName<BR />{<BR /> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">get<BR /> </FONT></FONT><FONT size="2">{<BR />  </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">object</FONT></FONT><FONT size="2">[] properties = { </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">Constants</FONT></FONT><FONT size="2">.VIX_PROPERTY_SNAPSHOT_DISPLAYNAME };<BR />  </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">return</FONT></FONT><FONT size="2"> (</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2">)</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">new</FONT></FONT><FONT size="2"> </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">VMWareVixHandle</FONT></FONT><FONT size="2">((</FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">IVixHandle</FONT></FONT><FONT size="2">) _snapshot).GetProperties(properties)[0];<BR /> }<BR />}<BR /></FONT></pre></div></BLOCKQUOTE></stripped></div><div><a href="http://code.dblock.org/ShowPost.aspx?id=27">Read</a> | Updated 12/26/2008</div></html>
         ]]>
       </description>
       <category>vmware</category>
       <link>http://code.dblock.org/ShowPost.aspx?Id=27</link>
       <guid isPermaLink="false">http://code.dblock.org/Post/27</guid>
      </item>
     
      <item>
       <title>Copying files to/from VMWare guest OS is slow: an alternate approach</title>
       <pubDate>Wed, 24 Dec 2008 05:45:00 GMT</pubDate>
       <description>
         <![CDATA[
          <link rel="stylesheet" href='http://code.dblock.org/Style.css' />
          <html><div><stripped><P>I really like VMWare VIX API's <EM>CopyFileFromGuestToHost</EM> and <EM>CopyFileFromHostToGuest. </EM>These automatically copy a single file or an entire directory tree. Easy. Unfortunately I am copying large (150-300 Mb) files to/from a VMWare guest OS and it's taking an hour to copy a hundred megs. I bet VMWare API was developed by Russian developers, so it's probably sending UTF-8 encoded bytes in Russian via SOAP. You might remember that I am writing a tool that lets one test a cross-product of installers and virtual machine snapshots: three MSIs multipled by twenty snapshots equals days of file copying! It's not going to work.</P>
<P>I posted a <A href="http://communities.vmware.com/thread/184489?tstart=0">question about this in VMWare Communities</A> and got a satisfactory response: <EM>I don't think there is a workaround. We are aware of the issue (we run in to it internally) and hope to fix it in a future release. </EM></P>
<P>In the meantime, I need a short term solution.</P>
<P>I decided to try and map the remote drive and use a simple <EM>File.Copy</EM>. The first challenge is to find out the remote server's IP address. VMWare exposes guest OS variables, including the ip, so I've extended <A href="http://code.dblock.org/ShowPost.aspx?id=25">VMWare Tasks</A> to support those.</P>
<BLOCKQUOTE style="MARGIN-RIGHT: 0px">
<P></P><div class="code"><pre><BR /><FONT color="#808080" size="2"><FONT color="#808080" size="2">///</FONT></FONT><FONT color="#008000" size="2"><FONT color="#008000" size="2"> </FONT></FONT><FONT color="#808080" size="2"><FONT color="#808080" size="2">&lt;summary&gt;<BR /></FONT></FONT><FONT color="#808080" size="2"><FONT color="#808080" size="2">///</FONT></FONT><FONT color="#008000" size="2"><FONT color="#008000" size="2"> Environment, guest and runtime variables<BR /></FONT></FONT><FONT color="#808080" size="2"><FONT color="#808080" size="2">///</FONT></FONT><FONT color="#008000" size="2"><FONT color="#008000" size="2"> </FONT></FONT><FONT color="#808080" size="2"><FONT color="#808080" size="2">&lt;/summary&gt;<BR /></FONT></FONT><FONT color="#808080" size="2"><FONT color="#808080" size="2">///</FONT></FONT><FONT color="#008000" size="2"><FONT color="#008000" size="2"> </FONT></FONT><FONT color="#808080" size="2"><FONT color="#808080" size="2">&lt;param name="name"&gt;</FONT></FONT><FONT color="#008000" size="2"><FONT color="#008000" size="2">name of the variable</FONT></FONT><FONT color="#808080" size="2"><FONT color="#808080" size="2">&lt;/param&gt;<BR /></FONT></FONT><FONT size="2">[</FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">IndexerName</FONT></FONT><FONT size="2">(</FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"Variables"</FONT></FONT><FONT size="2">)]<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">public</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">this</FONT></FONT><FONT size="2">[</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2"> name]<BR />{<BR /> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">get<BR /> </FONT></FONT><FONT size="2">{<BR />  </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">VMWareJob</FONT></FONT><FONT size="2"> job = </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">new</FONT></FONT><FONT size="2"> </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">VMWareJob</FONT></FONT><FONT size="2">(_vm.ReadVariable(_variableType, name, 0, </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">null</FONT></FONT><FONT size="2">));<BR />  </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">object</FONT></FONT><FONT size="2">[] properties = { </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">Constants</FONT></FONT><FONT size="2">.VIX_PROPERTY_JOB_RESULT_VM_VARIABLE_STRING };<BR />  </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">return</FONT></FONT><FONT size="2"> job.Wait&lt;</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2">&gt;(properties, 0, </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">VMWareInterop</FONT></FONT><FONT size="2">.Timeouts.ReadVariableTimeout);<BR /> }<BR /> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">set<BR /> </FONT></FONT><FONT size="2">{<BR />   </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">VMWareJob</FONT></FONT><FONT size="2"> job = </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">new</FONT></FONT><FONT size="2"> </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">VMWareJob</FONT></FONT><FONT size="2">(_vm.WriteVariable(_variableType, name, </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">value</FONT></FONT><FONT size="2">, 0, </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">null</FONT></FONT><FONT size="2">));<BR />   job.Wait(</FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">VMWareInterop</FONT></FONT><FONT size="2">.Timeouts.WriteVariableTimeout);<BR />  }<BR />}<BR /></FONT></pre></div></BLOCKQUOTE>
<P>Here's the IP address of a powered-on VM.</P>
<BLOCKQUOTE style="MARGIN-RIGHT: 0px">
<P></P><div class="code"><pre><BR /><FONT size="2">virtualMachine.GuestVariables[</FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"ip"</FONT></FONT><FONT size="2">];<BR /></FONT></pre></div></BLOCKQUOTE>
<P>We can make up a network path out of a local one.</P>
<BLOCKQUOTE style="MARGIN-RIGHT: 0px">
<P></P><div class="code"><pre><BR /><FONT size="2"><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">public</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2"> PathToNetworkPath(<FONT color="#0000ff">string </FONT><FONT color="#000000">ip, </FONT></FONT><FONT size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2"> value)<BR />{<BR /> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">return</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2">.Format(</FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">@"\\{0}\{1}"</FONT></FONT><FONT size="2">, ip, value.Replace(</FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">":"</FONT></FONT><FONT size="2">, </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"$"</FONT></FONT><FONT size="2">));<BR />}<BR /></FONT></FONT></pre></div></BLOCKQUOTE>
<P>Mapping a network drive is implemented in mpr.dll with <A href="http://msdn.microsoft.com/en-us/library/aa385413(VS.85).aspx">WNetAddConnection2</A>. A wrapper class will do the job.</P>
<BLOCKQUOTE style="MARGIN-RIGHT: 0px">
<P></P><div class="code"><pre><BR /><FONT size="2"><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">public</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">class</FONT></FONT><FONT size="2"> </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">NetworkDrive<BR /></FONT></FONT><FONT size="2">{<BR /> [</FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">DllImport</FONT></FONT><FONT size="2">(</FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"mpr.dll"</FONT></FONT><FONT size="2">)]<BR /> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">public</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">static</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">extern</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">int</FONT></FONT><FONT size="2"> WNetAddConnection2(<BR />   </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">ref</FONT></FONT><FONT size="2"> </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">NETRESOURCE</FONT></FONT><FONT size="2"> lpNetResource, </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2"> lpPassword, </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2"> UserName, </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">int</FONT></FONT><FONT size="2"> dwFlags);</FONT></FONT>
<P><FONT size="2"><FONT size="2"> [</FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">StructLayout</FONT></FONT><FONT size="2">(</FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">LayoutKind</FONT></FONT><FONT size="2">.Sequential)]<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> public</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">struct</FONT></FONT><FONT size="2"> </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">NETRESOURCE<BR /></FONT></FONT><FONT size="2"> {<BR />  </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">public</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">int</FONT></FONT><FONT size="2"> dwScope;<BR />  </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">public</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">int</FONT></FONT><FONT size="2"> dwType;<BR />  </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">public</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">int</FONT></FONT><FONT size="2"> dwDisplayType;<BR />  </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">public</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">int</FONT></FONT><FONT size="2"> dwUsage;<BR />  </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">public</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2"> lpLocalName;<BR />  </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">public</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2"> lpRemoteName;<BR />  </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">public</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2"> lpComment;<BR />  </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">public</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2"> lpProvider;<BR /> }</FONT></FONT></P>
<P><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> private</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">const</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">int</FONT></FONT><FONT size="2"> RESOURCETYPE_DISK = 0x1;</FONT></P>
<P><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> private</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2"> _localName;<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> private</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2"> _remoteName;</FONT></P>
<P><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> public</FONT></FONT><FONT size="2"> NetworkDrive(</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2"> remoteName)<BR /> {<BR />  _remoteName = remoteName;<BR /> }</FONT></P>
<P><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> public</FONT></FONT><FONT size="2"> NetworkDrive(</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2"> remoteName, </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2"> localName)<BR /> {<BR />  _remoteName = remoteName;<BR />  _localName = localName;<BR /> }</FONT></P>
<P><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">  public</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2"> LocalName<BR />  {<BR />   </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">get</FONT></FONT><FONT size="2"> { </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">return</FONT></FONT><FONT size="2"> _localName; }<BR />   </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">set</FONT></FONT><FONT size="2"> { _localName = </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">value</FONT></FONT><FONT size="2">; }<BR />  }</FONT></P>
<P><FONT size="2">  <FONT color="#0000ff"><FONT color="#0000ff">public</FONT></FONT> <FONT color="#0000ff"><FONT color="#0000ff">string</FONT></FONT> RemoteName<BR />  </FONT><FONT size="2">{<BR />   </FONT><FONT size="2"><FONT color="#0000ff"><FONT color="#0000ff">get</FONT></FONT> { <FONT color="#0000ff"><FONT color="#0000ff">return</FONT></FONT> _remoteName; }<BR />   </FONT><FONT size="2"><FONT color="#0000ff"><FONT color="#0000ff">set</FONT></FONT> { _remoteName = <FONT color="#0000ff"><FONT color="#0000ff">value</FONT></FONT>; }<BR />  </FONT><FONT size="2">}</FONT></P>
<P><FONT size="2"><FONT color="#0000ff"><FONT color="#0000ff"> public</FONT></FONT> <FONT color="#0000ff"><FONT color="#0000ff">void</FONT></FONT> MapNetworkDrive(<FONT color="#0000ff"><FONT color="#0000ff">string</FONT></FONT> username, <FONT color="#0000ff"><FONT color="#0000ff">string</FONT></FONT> password)<BR /> </FONT><FONT size="2">{<BR />   </FONT><FONT size="2"><FONT color="#2b91af"><FONT color="#2b91af">NETRESOURCE</FONT></FONT> netResource = <FONT color="#0000ff"><FONT color="#0000ff">new</FONT></FONT> <FONT color="#2b91af"><FONT color="#2b91af">NETRESOURCE</FONT></FONT>();<BR />   </FONT><FONT size="2">netResource.dwScope = 2;<BR />   </FONT><FONT size="2">netResource.dwType = RESOURCETYPE_DISK;<BR />   </FONT><FONT size="2">netResource.dwDisplayType = 3;<BR />   </FONT><FONT size="2">netResource.dwUsage = 1;<BR />   </FONT><FONT size="2">netResource.lpRemoteName = _remoteName;<BR />   </FONT><FONT size="2">netResource.lpLocalName = _localName;<BR />   </FONT><FONT size="2"><FONT color="#0000ff"><FONT color="#0000ff">int</FONT></FONT> rc = WNetAddConnection2(<FONT color="#0000ff"><FONT color="#0000ff">ref</FONT></FONT> netResource, password, username, 0);<BR />   </FONT><FONT size="2"><FONT color="#0000ff"><FONT color="#0000ff">if</FONT></FONT> (rc != 0)<BR />   </FONT><FONT size="2">{<BR />    </FONT><FONT size="2"><FONT color="#0000ff"><FONT color="#0000ff">throw</FONT></FONT> <FONT color="#0000ff"><FONT color="#0000ff">new</FONT></FONT> <FONT color="#2b91af"><FONT color="#2b91af">Win32Exception</FONT></FONT>(rc);<BR />   </FONT><FONT size="2">}<BR /> </FONT><FONT size="2">}<BR /></FONT><FONT size="2">}<BR /></FONT></P></pre></div></BLOCKQUOTE>
<P>Let's put it all together.</P>
<BLOCKQUOTE style="MARGIN-RIGHT: 0px">
<P></P><div class="code"><pre><BR /><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">public</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">void</FONT></FONT><FONT size="2"> CopyFileFromGuestToHost(</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2"> guestPath, </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2"> hostPath<FONT color="#000000">)<BR />{<BR />  </FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2"> guestNetworkPath = PathToNetworkPath(_ip, guestPath);<BR />  </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">NetworkDrive</FONT></FONT><FONT size="2"> guestNetworkDrive = </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">new</FONT></FONT><FONT size="2"> </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">NetworkDrive</FONT></FONT><FONT size="2">(</FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">Path</FONT></FONT><FONT size="2">.GetPathRoot(guestNetworkPath));<BR />  </FONT><FONT size="2">guestNetworkDrive.MapNetworkDrive(_username, _password);<BR />  </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">File</FONT></FONT><FONT size="2">.Copy(guestNetworkPath, hostPath, </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">true</FONT></FONT><FONT size="2">);<BR /></FONT><FONT size="2">}<BR /></FONT></pre></div></BLOCKQUOTE>
<P>The last thing that remains to be done to make the new copy compatible is to also copy directories and subdirectories. That's left as an exercise to the reader.</P></stripped></div><div><a href="http://code.dblock.org/ShowPost.aspx?id=26">Read</a> | Updated 12/26/2008</div></html>
         ]]>
       </description>
       <category>vmware</category>
       <link>http://code.dblock.org/ShowPost.aspx?Id=26</link>
       <guid isPermaLink="false">http://code.dblock.org/Post/26</guid>
      </item>
     
      <item>
       <title>Announcing the VMWare Tasks Library</title>
       <pubDate>Sat, 20 Dec 2008 05:30:00 GMT</pubDate>
       <description>
         <![CDATA[
          <link rel="stylesheet" href='http://code.dblock.org/Style.css' />
          <html><div><stripped><P><IMG height="63" alt="VMWare" src="http://www.codeproject.com/KB/library/VMWareTasks/VMWareLogo.jpg" width="160" /></P>
<P>Now that I wrote various tools that interop with VMWare, I started working on a <STRONG>VMWare Tasks Library</STRONG>, a managed C# wrapper on top of VMWare COM ViX API that makes it really easy to use.</P>
<UL>
<LI><A href="http://www.codeproject.com/KB/library/VMWareTasks.aspx">CodeProject Article</A></LI>
<LI><A href="http://svn.vestris.com/listing.php?repname=Vestris+SVN&path=%2Fcodeproject%2FVMWareTasks%2FSource%2FVMWareLib%2F#_codeproject_VMWareTasks_Source_VMWareLib_">Live source code in SVN</A></LI></UL>
<P>I checked in basic functionality of connecting to a virtual machine host, restoring snapshots, powering them up, executing commands, getting lists of files in a directory and subdirectories, etc.</P>
<P>At my day job we developed a tool that uses VMWare to test installers (executes a cross-product of virtual machine snapshots and installers). I plan to take an alternate approach here and write an MSBuild Task to control VMWare, which could enable more flexible automation scenarios.</P></stripped></div><div><a href="http://code.dblock.org/ShowPost.aspx?id=25">Read</a> | Updated 12/22/2008</div></html>
         ]]>
       </description>
       <category>vmware</category>
       <link>http://code.dblock.org/ShowPost.aspx?Id=25</link>
       <guid isPermaLink="false">http://code.dblock.org/Post/25</guid>
      </item>
     
      <item>
       <title>HowTo: remote control, copy and run programs on a VMware Workstation or VI server using VIX APIs</title>
       <pubDate>Wed, 10 Dec 2008 20:15:00 GMT</pubDate>
       <description>
         <![CDATA[
          <link rel="stylesheet" href='http://code.dblock.org/Style.css' />
          <html><div><stripped><P>I've been playing with <A href="http://www.vmware.com/">VMware</A> lately, both Workstation and VMware Infrastructure (VI). The company has really stepped up with the new SDKs and the level of programmable interfaces, making some excellent implementation decisions that enable us to drive virtual machines for primarily unit-testing purposes. The doc is a little light today, so this should help. </P>
<P><STRONG>What do we use this for?</STRONG></P>
<P>We (at my <A href="http://www.appsecinc.com/aboutus/index.shtml">day job</A>) developed a tool (in C#) that runs MSI installers to make sure the product installs on various knownly good or bad environments, sort of unit testing installers. We also have an ESX environment that we share.</P>
<P><STRONG>VMWare Programming APIs</STRONG></P>
<P>There're two types of APIs.</P>
<UL>
<LI><STRONG>VMWare Virtual Infrastructure SDK</STRONG>: a set of tools and APIs to manage a VMWare Infrastructure environment. A toolkit has also been released that contains managed wrappers on top of the SOAP interface provided by a VMWare deployment. It's focused on VMWare ESX or VirtualCenter management and is beyond the scope of this post.<BR />
</LI><LI><STRONG>VMWare VIX API</STRONG>. The VIX API allows you to write programs and scripts that automate virtual machine operations, as well as the guests within virtual machines. It runs on both Windows and Linux and supports management of VMware Server, Workstation, and Virtual Infrastructure (both ESX and vCenter). Bindings are provided for C, Perl, and COM (Visual Basic, VBscript, C#). In this post I'll focus on the C# implementation.</LI></UL>
<P><STRONG>What do you need?</STRONG></P>
<UL>
<LI>Either VMWare <A href="http://www.vmware.com/download/ws/">Workstation 6.5</A>, a VI environment (I use ESX), or both. 
</LI><LI>VMWare ViX. This is the SDK, obtained from <A href="http://www.vmware.com/download/sdk/vmauto.html"><U><FONT color="#810081">http://www.vmware.com/download/sdk/vmauto.html</FONT></U></A>. The new 1.6.2 version is required for VI support.</LI></UL>
<P><STRONG>Connecting to a VMWare Workstation or ESX Server</STRONG><BR /><BR />Connecting to a local VMWare Workstation or an ESX server is virtually identical. The ESX server requires an URL to the SOAP SDK (eg. <A href="https://esxserver/sdk">https://esxserver/sdk</A>) and a username and password.</P>
<BLOCKQUOTE style="MARGIN-RIGHT: 0px">
<P></P><div class="code"><pre><BR /><FONT size="2"><FONT color="#0000ff">private</FONT> <FONT color="#0000ff">void</FONT> ConnectToVMWareWorkstation()<BR />{<BR /> Connect(<FONT color="#2b91af">Constants</FONT>.VIX_SERVICEPROVIDER_VMWARE_WORKSTATION, <FONT color="#0000ff">string</FONT>.Empty, 0, <FONT color="#0000ff">string</FONT>.Empty, <FONT color="#0000ff">string</FONT>.Empty);<BR />}</FONT>
<P><FONT size="2"><FONT color="#0000ff">private</FONT> <FONT color="#0000ff">void</FONT> ConnectToVMWareVIServer(<FONT color="#0000ff">string</FONT> hostName, <FONT color="#0000ff">int</FONT> hostPort, <FONT color="#0000ff">string</FONT> username, <FONT color="#0000ff">string</FONT> password)<BR />{<BR /> Connect(<FONT color="#2b91af">Constants</FONT>.VIX_SERVICEPROVIDER_VMWARE_VI_SERVER,  hostName, hostPort, username, password);<BR />}</FONT></P>
<P><FONT size="2"></FONT></P>
<P><FONT size="2"><FONT color="#0000ff">private</FONT> <FONT color="#0000ff">void</FONT> Connect(<FONT color="#0000ff">int</FONT> hostType, <FONT color="#0000ff">string</FONT> hostName, <FONT color="#0000ff">int</FONT> hostPort, <FONT color="#0000ff">string</FONT> username, <FONT color="#0000ff">string</FONT> password)<BR />{<BR /></FONT><FONT size="2"><FONT color="#008000"> // Connect to a VMware Workstation<BR /></FONT><FONT color="#2b91af"> IJob</FONT> vmJob = <FONT color="#2b91af">VmwareVixInterop</FONT>.vixLib.Connect(<BR />  <FONT color="#2b91af">Constants</FONT>.VIX_API_VERSION, hostType, hostName, hostPort, username, password, 0, <FONT color="#0000ff">null</FONT>, <FONT color="#0000ff">null</FONT>);<BR /></FONT><FONT size="2"><FONT color="#008000"> // You need to get the IHost object that represents the host where your VM is located.<BR />// Since COM allocates the pointer you need to use this funky mechanism to extract the IHosts array.<BR /></FONT><FONT color="#0000ff"> object</FONT>[] VIX_PROPERTY_JOB_RESULT_HANDLE =<FONT color="#0000ff">  new</FONT> <FONT color="#0000ff">object</FONT>[1];<BR /> VIX_PROPERTY_JOB_RESULT_HANDLE[0] = <FONT color="#2b91af">Constants</FONT>.VIX_PROPERTY_JOB_RESULT_HANDLE;<BR /></FONT><FONT size="2"><FONT color="#008000"> // Wait for the operation to complete<BR /> </FONT><FONT color="#0000ff">object</FONT> hosts = <FONT color="#2b91af">VmwareVixInterop</FONT>.Wait(vmJob, VIX_PROPERTY_JOB_RESULT_HANDLE);<BR /> </FONT><FONT size="2"><FONT color="#008000">// Cast and retrieve the IHost object.<BR /> </FONT><FONT color="#0000ff">object</FONT>[] hostArray = hosts <FONT color="#0000ff">as</FONT> <FONT color="#0000ff">object</FONT>[];<BR /> _host = (<FONT color="#2b91af">IHost</FONT>) hostArray[0];<BR />}<BR /></FONT></P></pre></div></BLOCKQUOTE>
<P><STRONG>Locating a Virtual Machine</STRONG></P>
<P style="MARGIN-RIGHT: 0px">A virtual machine on a VMWare Workstation is a file with a standard path (eg. <EM>C:\Virtual Machines\myvirtualmachine.vmx</EM>). Unsurprisingly it is the same thing on an ESX server, but with a relative storage path. The latter can be found in the VMWare Infrastructure Client: right click on a virtual machine, choose <EM>Edit Settings</EM>, click the <EM>Options</EM> tab and note the <EM>Virtual Machine Configuration File</EM> (eg. <EM>[storage] virtualmachine/virtualmachine.vmx</EM>).</P>
<BLOCKQUOTE style="MARGIN-RIGHT: 0px">
<P style="MARGIN-RIGHT: 0px"></P><div class="code"><pre><BR /><FONT size="2"><FONT color="#0000ff">public</FONT> <FONT color="#0000ff">void</FONT> OpenFile(<FONT color="#0000ff">string</FONT> fileName)<BR />{<BR /> </FONT><FONT size="2"><FONT color="#008000">// Open the VM from the path specified<BR /> </FONT><FONT color="#2b91af">IJob</FONT> vmJob = _host.OpenVM(fileName, <FONT color="#0000ff">null</FONT>);<BR /> <FONT color="#0000ff">object</FONT>[] resultHandles = <FONT color="#0000ff">new</FONT> <FONT color="#0000ff">object</FONT>[1];<BR /> resultHandles[0] = <FONT color="#2b91af">Constants</FONT>.VIX_PROPERTY_JOB_RESULT_HANDLE;<BR /> </FONT><FONT size="2"><FONT color="#008000">// Wait for the operation to complete<BR /> </FONT><FONT color="#0000ff">object</FONT> vms = <FONT color="#2b91af">VmwareVixInterop</FONT>.Wait(vmJob, resultHandles);<BR /> </FONT><FONT size="2"><FONT color="#008000">// Get the VM object returned<BR /> </FONT><FONT color="#2b91af">Object</FONT>[] vmArray = vms <FONT color="#0000ff">as</FONT> <FONT color="#2b91af">Object</FONT>[];<BR /> _vm = (<FONT color="#2b91af">IVM</FONT>) vmArray[0];<BR />}<BR /></FONT></pre></div></BLOCKQUOTE>
<P style="MARGIN-RIGHT: 0px"><STRONG>Power-on, power-off, copy and execute</STRONG></P>
<P style="MARGIN-RIGHT: 0px">These are straightforward operations supported by the SDK via the IVM interface returned set by the above-mentioned OpenFile method. Here're some examples.</P>
<P style="MARGIN-RIGHT: 0px">
</P><UL>
<LI>
<P><FONT size="2"><FONT color="#2b91af">IJob </FONT>PowerOn(<FONT color="#0000ff">int</FONT> powerOnOptions, <FONT color="#2b91af">IVixHandle</FONT> propertyList, <FONT color="#2b91af">ICallback</FONT> jobDoneCallback);</FONT></P>
</LI><LI>
<P><FONT size="2"><FONT color="#2b91af">IJob </FONT>RevertToSnapshot(<FONT color="#2b91af">ISnapshot</FONT> snapshot, <FONT color="#0000ff">int</FONT> options, <FONT color="#2b91af">IVixHandle</FONT> propertyList, <FONT color="#2b91af">ICallback</FONT> jobDoneCallback);</FONT></P>
</LI><LI>
<P><FONT size="2"><FONT color="#2b91af">IJob </FONT>CopyFileFromHostToGuest(<FONT color="#0000ff">string</FONT> hostPathName, <FONT color="#0000ff">string</FONT> guestPathName, <FONT color="#0000ff">int</FONT> options, <FONT color="#2b91af">IVixHandle</FONT> propertyList, <FONT color="#2b91af">ICallback</FONT> jobDoneCallback);</FONT></P></LI></UL>
<P></P>
<P>It is now possible to execute commands synchronously and asynchronously, without having to involve WMI or another similar method.</P>
<BLOCKQUOTE style="MARGIN-RIGHT: 0px">
<P></P><div class="code"><pre><BR /><FONT size="2"><FONT color="#0000ff">public</FONT> <FONT color="#0000ff">int</FONT> Execute(<FONT color="#0000ff">string</FONT> path, <FONT color="#0000ff">string</FONT> parameters)<BR />{<BR /> <FONT color="#2b91af">IJob</FONT> vmJob = _vm.RunProgramInGuest(path, parameters, VixCOM.<FONT color="#2b91af">Constants</FONT>.VIX_RUNPROGRAM_ACTIVATE_WINDOW, <FONT color="#0000ff">null</FONT>, <FONT color="#0000ff">null</FONT>);<BR /><FONT color="#0000ff"><FONT color="#000000"> </FONT>object</FONT>[] propertyIDs = <FONT color="#0000ff">new</FONT> <FONT color="#2b91af">Object</FONT>[] { <FONT color="#2b91af">Constants</FONT>.VIX_PROPERTY_JOB_RESULT_GUEST_PROGRAM_EXIT_CODE };<BR /> <FONT color="#0000ff">object</FONT> results = <FONT color="#2b91af">VmwareVixInterop</FONT>.Wait(vmJob, propertyIDs);<BR /> <FONT color="#0000ff">return</FONT> <FONT color="#2b91af">Convert</FONT>.ToInt32(((<FONT color="#0000ff">object</FONT>[])results)[0]);<BR />}<BR /></FONT></pre></div></BLOCKQUOTE>
<P>I think the whole job-based API could use a nice .NET wrapper :)</P></stripped></div><div><a href="http://code.dblock.org/ShowPost.aspx?id=24">Read</a> | Updated 12/26/2008</div></html>
         ]]>
       </description>
       <category>vmware</category>
       <link>http://code.dblock.org/ShowPost.aspx?Id=24</link>
       <guid isPermaLink="false">http://code.dblock.org/Post/24</guid>
      </item>
     
      <item>
       <title>WMI: Executing a remote process and waiting for its completion</title>
       <pubDate>Wed, 03 Dec 2008 21:45:00 GMT</pubDate>
       <description>
         <![CDATA[
          <link rel="stylesheet" href='http://code.dblock.org/Style.css' />
          <html><div><stripped><P>This drove me crazy for an hour. I needed to execute a remote process via WMI and wait for it to finish. Lots of online resources are suggesting to use __InstanceCreationEvent, but that always threw access denied errors back at me. This is a workable straightforward solution, waiting for process to finish by quering the running processes.</P>
<P><FONT color="#2b91af" size="2">ConnectionOptions</FONT><FONT size="2"> connOptions = </FONT><FONT color="#0000ff" size="2">new</FONT><FONT size="2"> </FONT><FONT color="#2b91af" size="2">ConnectionOptions</FONT><FONT size="2">();<BR />connOptions.Impersonation = </FONT><FONT color="#2b91af" size="2">ImpersonationLevel</FONT><FONT size="2">.Impersonate;<BR />connOptions.Authentication = </FONT><FONT color="#2b91af" size="2">AuthenticationLevel</FONT><FONT size="2">.Default;<BR /></FONT><FONT size="2">connOptions.Username = ...;<BR />connOptions.Password = ...;<BR /></FONT><FONT size="2">connOptions.EnablePrivileges = </FONT><FONT color="#0000ff" size="2">true</FONT><FONT size="2">;<BR /><FONT color="#2b91af">ManagementScope </FONT>scope = </FONT><FONT color="#0000ff" size="2">new</FONT><FONT size="2"> </FONT><FONT color="#2b91af" size="2">ManagementScope</FONT><FONT size="2">(</FONT><FONT color="#a31515" size="2">@"\\"</FONT><FONT size="2"> + machinename + </FONT><FONT color="#a31515" size="2">@"\root\cimv2"</FONT><FONT size="2">, connOptions);<BR />scope.Connect();</FONT></P><FONT size="2"><FONT size="2">
<P></P></FONT><FONT color="#2b91af" size="2">ManagementPath</FONT><FONT size="2"> mgmtPath = </FONT><FONT color="#0000ff" size="2">new</FONT><FONT size="2"> </FONT><FONT color="#2b91af" size="2">ManagementPath</FONT><FONT size="2">(</FONT><FONT color="#a31515" size="2">"Win32_Process"</FONT><FONT size="2">);<BR /></FONT><FONT color="#2b91af" size="2">ManagementClass</FONT><FONT size="2"> mgmtClass = </FONT><FONT color="#0000ff" size="2">new</FONT><FONT size="2"> </FONT><FONT color="#2b91af" size="2">ManagementClass</FONT><FONT size="2">(_scope, mgmtPath, </FONT><FONT color="#0000ff" size="2">null</FONT><FONT size="2">);<BR /></FONT><FONT color="#2b91af" size="2">ManagementBaseObject</FONT><FONT size="2"> mgmtBaseObject = mgmtClass.GetMethodParameters(</FONT><FONT color="#a31515" size="2">"Create"</FONT><FONT size="2">);<BR />mgmtBaseObject[</FONT><FONT color="#a31515" size="2">"CommandLine"</FONT><FONT size="2">] = commandLine;<BR /></FONT><FONT color="#2b91af" size="2">ManagementBaseObject</FONT><FONT size="2"> outputParams = mgmtClass.InvokeMethod(</FONT><FONT color="#a31515" size="2">"Create"</FONT><FONT size="2">, mgmtBaseObject, </FONT><FONT color="#0000ff" size="2">null</FONT><FONT size="2">);<BR /></FONT><FONT color="#0000ff" size="2">uint</FONT><FONT size="2"> pid = (</FONT><FONT color="#0000ff" size="2">uint</FONT><FONT size="2">) outputParams[</FONT><FONT color="#a31515" size="2">"processId"</FONT><FONT size="2">];<BR /></FONT><FONT color="#2b91af" size="2">Console</FONT><FONT size="2">.Write(</FONT><FONT color="#a31515" size="2">"Pid: {0} "</FONT><FONT size="2">, pid);<BR /></FONT><FONT color="#0000ff" size="2">while</FONT><FONT size="2"> (Select(</FONT><FONT color="#a31515" size="2">"Win32_Process"</FONT><FONT size="2">, </FONT><FONT color="#0000ff" size="2">string</FONT><FONT size="2">.Format(</FONT><FONT color="#a31515" size="2">"processId = {0}"</FONT><FONT size="2">, pid)).Count &gt; 0)<BR />{<BR /> </FONT><FONT color="#2b91af" size="2">Console</FONT><FONT size="2">.Write(</FONT><FONT color="#a31515" size="2">"."</FONT><FONT size="2">);<BR /> </FONT><FONT color="#2b91af" size="2">Thread</FONT><FONT size="2">.Sleep(1000);<BR />}<BR /></FONT><FONT color="#2b91af" size="2">Console</FONT><FONT size="2">.WriteLine(</FONT><FONT color="#a31515" size="2">" done."</FONT><FONT size="2">);</FONT></FONT></stripped></div><div><a href="http://code.dblock.org/ShowPost.aspx?id=23">Read</a> | Updated 12/3/2008</div></html>
         ]]>
       </description>
       <category>wmi</category>
       <link>http://code.dblock.org/ShowPost.aspx?Id=23</link>
       <guid isPermaLink="false">http://code.dblock.org/Post/23</guid>
      </item>
     
      <item>
       <title>Count projections in NHibernate 1.2</title>
       <pubDate>Wed, 03 Dec 2008 14:45:00 GMT</pubDate>
       <description>
         <![CDATA[
          <link rel="stylesheet" href='http://code.dblock.org/Style.css' />
          <html><div><stripped><P>For someone who got stuck with NHibernate 1.1 it was actually surprisingly hard to find much about projections. Before you had to do different queries for a COUNT or a SELECT and you couldn't use ICriteria.</P><div class="code"><pre><FONT size="2"> 
<P><FONT color="#0000ff">int </FONT>count = (<FONT color="#0000ff">int</FONT>) session.CreateQuery(</P></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">string</FONT></FONT><FONT size="2">.Format(<BR /> </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"SELECT COUNT(instance) FROM Login instance WHERE Role='{0}'"</FONT></FONT><FONT size="2">, <BR /> </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">TransitLoginRole</FONT></FONT><FONT size="2">.Administrator.ToString()))<BR /> .UniqueResult();</FONT></pre></div> 
<P>This is resolved with a projection.</P>
<P></P><div class="code"><pre>
<P><FONT size="2"><FONT color="#0000ff">int </FONT>count = session.CreateCriteria(</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">typeof</FONT></FONT><FONT size="2">(</FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">Login</FONT></FONT><FONT size="2">))<BR /> .Add(</FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">Expression</FONT></FONT><FONT size="2">.Eq(</FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"Role"</FONT></FONT><FONT size="2">, </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">TransitLoginRole</FONT></FONT><FONT size="2">.Administrator.ToString()))<BR /> .SetProjection(</FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">Projections</FONT></FONT><FONT size="2">.Count(</FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"Id"</FONT></FONT><FONT size="2">))<BR /> .UniqueResult&lt;</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">int</FONT></FONT><FONT size="2">&gt;();</FONT></P><FONT size="2">
<P>IList&lt;</P></FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">Login</FONT></FONT><FONT size="2">&gt; logins = session.CreateCriteria(</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">typeof</FONT></FONT><FONT size="2">(</FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">Login</FONT></FONT><FONT size="2">))<BR /> .Add(</FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">Expression</FONT></FONT><FONT size="2">.Eq(</FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"Role"</FONT></FONT><FONT size="2">, </FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">TransitLoginRole</FONT></FONT><FONT size="2">.Administrator.ToString()))<BR /> .List&lt;</FONT><FONT color="#2b91af" size="2"><FONT color="#2b91af" size="2">Login</FONT></FONT><FONT size="2">&gt;();</FONT>
<P></P></pre></div>
<P>Nice and easy.</P></stripped></div><div><a href="http://code.dblock.org/ShowPost.aspx?id=22">Read</a> | Updated 12/3/2008</div></html>
         ]]>
       </description>
       <category>hibernate</category>
       <link>http://code.dblock.org/ShowPost.aspx?Id=22</link>
       <guid isPermaLink="false">http://code.dblock.org/Post/22</guid>
      </item>
     
      <item>
       <title>Resetting a Canon MP460</title>
       <pubDate>Wed, 03 Dec 2008 04:25:03 GMT</pubDate>
       <description>
         <![CDATA[
          <link rel="stylesheet" href='http://code.dblock.org/Style.css' />
          <html><div><stripped><P>This is going to be my first hardware post. We'll start simple - I do have a copy of <A href="http://www.amazon.com/Art-Electronics-Paul-Horowitz/dp/0521370957">The Art of Electronics</A> and a welder, so there's a chance I might post something meaningful one day.</P>
<P>I was about to throw my MP460 Canon printer (80$) out of the window (8th floor, 10$ a flight of stairs). I was trying to setup a wireless print server and finally got that working, when the printer came back with an obscure 5100 error. I tried everything, including shaking it violently. What worked was a reset, and <A href="http://tricks-collections.com/2008/04/reset-printer-canon-mp140-mp160-mp180-mp210-mp220-mp460-mp470-mp500-mp510-mp530-mp600-mp610-mp800-mp820-mp810-mp830-mp960-mp970/">this page</A> explains how.</P>
<OL>
<LI>Turn off the printer 
</LI><LI>Hold the Resume Button (red circle in the triangle), add a printer (click “Power”) an indicator light green. 
</LI><LI>Hold the Power Button, release the Resume Button. 
</LI><LI>Not releasing the Power Button, double click “Resume” and release Both Buttons. 
</LI><LI>Click “Resume” for Four times 
</LI><LI>Once you click “Power”, to confirm the selected action (reset counter absorber). To disable the printer “Power” button to click again. </LI></OL>
<P>On the wireless front, I got a Linksys <A href="http://www.linksys.com/servlet/Satellite?c=L_Product_C2&childpagename=US%2FLayout&cid=1114037289494&pagename=Linksys%2FCommon%2FVisitorWrapper">WPS54G</A>. None of the wizards worked, go figure. I ended up being able to connect to the printer's HTTP configuration interface, but couldn't configure it on Vista. It wasn't too hard to configure manually with <A href="http://forums.linksys.com/linksys/board/message?board.id=Wireless_Print_Servers&thread.id=1476">some help</A>.</P>
<OL>
<LI>Add the appropriate printer from <EM>Control Panel</EM>, <EM>Printers</EM>, <EM>Add Printer</EM></LI>
<LI>Select <EM>Local Printer</EM> and select <EM>Create New Port</EM>, <EM>Standard TCP/IP Port</EM></LI>
<LI><EM>Device Type</EM>, <EM>TCP/IP Device.</EM> </LI>
<LI><EM>HostName</EM> or <EM>IPAddress</EM> should be the IP Address of the Print Server Device. I configured it with a static IP.</LI>
<LI>After nothing is detected choose <EM>Custom</EM>, <EM>Settings</EM></LI>
<LI>Select <EM>LPR</EM>, set <EM>Queue Name</EM> to <EM>L2</EM> for USB printer.</LI>
<LI>Turn on <EM>LPR Byte Counting Enabled</EM>.  </LI>
<LI>Select the printer, install the driver.</LI></OL>
<P>Easy? Ahem.</P></stripped></div><div><a href="http://code.dblock.org/ShowPost.aspx?id=21">Read</a></div></html>
         ]]>
       </description>
       <category>hardware</category>
       <link>http://code.dblock.org/ShowPost.aspx?Id=21</link>
       <guid isPermaLink="false">http://code.dblock.org/Post/21</guid>
      </item>
     
      <item>
       <title>DNI: setup (msi) bootstrapper 1.5 released</title>
       <pubDate>Sun, 26 Oct 2008 22:59:40 GMT</pubDate>
       <description>
         <![CDATA[
          <link rel="stylesheet" href='http://code.dblock.org/Style.css' />
          <html><div><stripped>DNI 1.5 has been released <A href="http://www.devage.com/Wiki/ViewArticle.aspx?name=dotnetinstaller&version=0">&gt; Read/Download</A>. I've been contributing to this open-source project for a while. You can <A href="http://code.dblock.org/ShowPost.aspx?id=9">read about that here</A>.</stripped></div><div><a href="http://code.dblock.org/ShowPost.aspx?id=20">Read</a></div></html>
         ]]>
       </description>
       <category>msi</category>
       <link>http://code.dblock.org/ShowPost.aspx?Id=20</link>
       <guid isPermaLink="false">http://code.dblock.org/Post/20</guid>
      </item>
     
      <item>
       <title>Product/Build Versioning with MSBuild, ANT and CruiseControl</title>
       <pubDate>Sun, 26 Oct 2008 13:30:00 GMT</pubDate>
       <description>
         <![CDATA[
          <link rel="stylesheet" href='http://code.dblock.org/Style.css' />
          <html><div><stripped><P><IMG src="http://code.dblock.org/ShowPicture.aspx?id=6" align="right" /></P>
<P><EM>Versioning</EM> is probably the hottest area of reinventing a better wheel. </P>
<H3>Single Versioning Scheme</H3>
<P>Do we really need a single versioning scheme? My answer is simple. Every company should strive towards unified processes. It makes people more interchangeable, avoids duplicate work and creates systems. Ultimately systems win, not individuals. A system can be derived from healthy competition of ideas and implementations, but once things are stable and everybody is entrenched in their ways, it is good to stir the pot, get people talking and standardize on one single method. </P>
<P>We have roughly 4 development teams, about ten subprojects with 7 versioning schemes. Trying to get everyone on a single one is a challenge and needs to be approached with care. I created a presentation entitled <EM><STRONG>"Product Versioning: or how management tells you to change something for no reason" </STRONG></EM>and spent a lot of time convincing people not that my versioning scheme is the best, but that we need a single one. I've used the following arguments.</P>
<OL>
<LI>Sitting at any computer, including a customer site, we have hard time tracing back to the source code that has produced a build. 
</LI><LI>We have two builds with the same build number, which becomes very confusing when it comes to figuring out whether a customer has installed a patch. 
</LI><LI>There's only one test team, which has to context switch from product to product for their bug reporting processes.  
</LI><LI>There's only one development team, giving a developer the opportunity to work on another team represents a culture shock, which promotes people working on the same thing for too many years. 
</LI><LI>When creating a new project we waste a lot of time debating about versioning.</LI></OL>
<P>Finally, 7 versioning schemes across 4 development teams is best qualified in Russian as: "кто в лес, кто по дрова". Ceci explique cela.</P>
<H3>Requirements</H3>
<P>It starts with conflicting <EM>requirements </EM>between various parts of the organization. </P>
<P>Engineering usually has conflicting requirements from product management and marketing. For example, on Windows the first three digits of the version matter for Windows installer and all the three parts must be numbers. But marketing likes versions like <EM>2008.1</EM> or <EM>Gold Edition</EM>. Hence, <EM><STRONG>offer marketing the opportunity to set any version they like</STRONG></EM>, one that has nothing to do with the engineering version. It's often as easy as adding text in the right places and managing it centrally.</P>
<P>Different engineers from various schools of thought usually have conflicting requirements. One of the managers who works for me believes that a build should be promoted to the test team and so a digit in the version must represent an auto-incremented number of builds promoted. Another manager thinks that the build number should be date-based, derived from the current year, month and day. The third manager agrees, but wants to use the Jewish calendar which creates more boundary problems. There's only one conclusion possible: <EM><STRONG>a single person must make this decision</STRONG></EM> and that person will not be liked. That's my job!</P>
<H3>Ingredients</H3>
<P>Before setting a versioning scheme I must outline several ingredients of successful versioning.</P>
<OL>
<LI>Versioning must be completely hands-off on a daily basis. That is nobody should have to do anything manually or semi-automatically for versioning every day. 
</LI><LI>It should be quick and easy to implement. 
</LI><LI>Developer builds, qa builds, official builds, blue and yellow biulds should be versioned in the same manner. 
</LI><LI>Versioning should uniformly target the platforms you ship your product on. 
</LI><LI>It should be possible to quickly trace back from a version number to the source code that produced the build. 
</LI><LI>Versioning should apply to every kind of artifact that is produced: binaries, web pages, documents, etc. 
</LI><LI>There must be unambiguous interpretation of the version number. Two people looking at the same number must understand what it means.</LI></OL>
<H3>Versioning Scheme</H3>
<P>Out of all conversations and options I've picked the following 4-digit scheme.</P>
<BLOCKQUOTE style="MARGIN-RIGHT: 0px">
<P><STRONG>Major.Minor.SVN Revision.Zero</STRONG></P></BLOCKQUOTE>
<UL>
<LI><STRONG>Major</STRONG>: the major version of the product, changed manually with every product release with a large new feature set. 
</LI><LI><STRONG>Minor</STRONG>: the minor version of the product, changed manually with every minor product release containing some features. 
</LI><LI><STRONG>SVN Revision</STRONG>: the latest source-control revision of the codebase used for this build. 
</LI><LI><STRONG>Zero</STRONG>: the last number is 0. If there're more than one builds at the same revision, it is an auto-incremented number.</LI></UL>
<P>For example, 1.5.4567.0 means that this is product version 1.5 at SVN revision 4567.</P>
<H3>Implementation with MSBuild</H3>
<P>We use <a target="_blank" href="http://msbuildtasks.tigris.org/"><img src="http://code.dblock.org/images/links/link.gif" border="0" align="absmiddle" width="16" height="16" /> MSBuild Community Tasks</a> to generate the version number.</P>
<P></P><div class="code"><pre><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">PropertyGroup<FONT color="#0000ff">&gt;<BR /> </FONT></FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">ProductName</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;</FONT></FONT><FONT size="2">ACME Product</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">ProductName</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR /> &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">CompanyName</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;</FONT></FONT><FONT size="2">ACME Inc.</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">CompanyName</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR /> &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">Copyright</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;</FONT></FONT><FONT size="2">Copyright (c) ACME 2008</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">Copyright</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR /> &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">Trademark</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;</FONT></FONT><FONT size="2">All Rights Reserved</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">Trademark</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR />&lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">PropertyGroup</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;</FONT></FONT></pre></div>
<P></P><div class="code"><pre><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">Target</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">Name</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">version</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR /> &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">Version</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">Major</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">1</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">Minor</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">0</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">VersionFile</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">version.txt</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">RevisionType</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Increment</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR />  &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">Output</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">TaskParameter</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Major</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">PropertyName</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Major</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> /&gt;<BR />  &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">Output</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">TaskParameter</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Minor</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">PropertyName</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Minor</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> /&gt;<BR />  &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">Output</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">TaskParameter</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Revision</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">PropertyName</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Revision</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> /&gt;<BR /> &lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">Version</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR /> &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">SvnVersion</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">LocalPath</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">.</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR />  &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">Output</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">TaskParameter</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Revision</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">PropertyName</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Build</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> /&gt;<BR /> &lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">SvnVersion</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR /> &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">Message</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">Text</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Version: $(Major).$(Minor).$(Build).$(Revision)</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">/&gt;<BR /> <FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">CreateItem</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">Include</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Major</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">AdditionalMetadata</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">ReplacementValue=$(Major)</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR />  &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">Output</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">TaskParameter</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Include</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">ItemName</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">AssemblyInfoTokens</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">/&gt;<BR /> &lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">CreateItem</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR /> &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">CreateItem</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">Include</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Minor</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">AdditionalMetadata</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">ReplacementValue=$(Minor)</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR />  &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">Output</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">TaskParameter</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Include</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">ItemName</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">AssemblyInfoTokens</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">/&gt;<BR /> &lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">CreateItem</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR /> &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">CreateItem</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">Include</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Build</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">AdditionalMetadata</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">ReplacementValue=$(Build)</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR />  &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">Output</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">TaskParameter</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Include</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">ItemName</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">AssemblyInfoTokens</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">/&gt;<BR /> &lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">CreateItem</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR /> &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">CreateItem</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">Include</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Revision</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">AdditionalMetadata</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">ReplacementValue=$(Revision)</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR />  &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">Output</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">TaskParameter</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Include</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">ItemName</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">AssemblyInfoTokens</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">/&gt;<BR /> &lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">CreateItem</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR /> &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">CreateItem</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">Include</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Configuration</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">AdditionalMetadata</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">ReplacementValue=$(Configuration)</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR />  &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">Output</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">TaskParameter</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Include</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">ItemName</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">AssemblyInfoTokens</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">/&gt;<BR /> &lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">CreateItem</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR /> &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">CreateItem</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">Include</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">ProductName</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">AdditionalMetadata</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">ReplacementValue=$(ProductName)</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR />  &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">Output</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">TaskParameter</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Include</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">ItemName</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">AssemblyInfoTokens</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">/&gt;<BR /> &lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">CreateItem</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR /> &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">CreateItem</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">Include</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">CompanyName</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">AdditionalMetadata</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">ReplacementValue=$(CompanyName)</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR />  &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">Output</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">TaskParameter</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Include</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">ItemName</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">AssemblyInfoTokens</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">/&gt;<BR /> &lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">CreateItem</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR /> &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">CreateItem</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">Include</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Copyright</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">AdditionalMetadata</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">ReplacementValue=$(Copyright)</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR />  &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">Output</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">TaskParameter</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Include</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">ItemName</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">AssemblyInfoTokens</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">/&gt;<BR /> &lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">CreateItem</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR /> &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">CreateItem</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">Include</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Trademark</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">AdditionalMetadata</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">ReplacementValue=$(Trademark)</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR />  &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">Output</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">TaskParameter</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Include</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">ItemName</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">AssemblyInfoTokens</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">/&gt;<BR /> &lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">CreateItem</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR /> &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">CreateItem</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">Include</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">ProductId</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">AdditionalMetadata</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">ReplacementValue=$(ProductId)</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR />  &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">Output</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">TaskParameter</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Include</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">ItemName</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">AssemblyInfoTokens</FONT></FONT><FONT color="#000000" size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">/&gt;<BR /> &lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">CreateItem</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR /></FONT></FONT>&lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">Target</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;</FONT></FONT></pre></div>
<P><B>Versioning C# Assemblies</B></P>
<OL>
<LI>Generate a GlobalAssemblyInfo.cs version file. 
</LI><LI>Edit AssemblyInfo.cs in each project and reduce it down to AssemblyTitle, AssemblyDescription and AssemblyGUID. 
</LI><LI>Add the generated GlobalAssemblyInfo.cs as a link to each project. When adding a file in Visual Studio, the Add button drops down to add a file as a link.</LI></OL>
<P>The following MSBuild script generates the version file.</P>
<P></P><div class="code"><pre><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">AssemblyInfo</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> <BR /> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">CodeLanguage</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">CS</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> <BR /> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">OutputFile</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">src\Version\GlobalAssemblyInfo.cs</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> <BR /> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">AssemblyCompany</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">$(CompanyName)</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> <BR /> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">AssemblyProduct</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">$(ProductName)</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> <BR /> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">AssemblyCopyright</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">$(Copyright)</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> <BR /> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">AssemblyTrademark</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">$(Trademark)</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> <BR /> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">CLSCompliant</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">true</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> <BR /> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">AssemblyDelaySign</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">false</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> <BR /> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">AssemblyKeyName</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">""</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> <BR /> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">AssemblyCulture</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">""</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> <BR /> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">AssemblyVersion</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">$(Major).$(Minor).$(Build).$(Revision)</FONT></FONT><FONT size="2">"<BR /> </FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">AssemblyFileVersion</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">$(Major).$(Minor).$(Build).$(Revision)</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> /&gt;</FONT></FONT></pre></div>
<P><B>Versioning C++ Code</B></P>
<OL>
<LI>Use a template version header file (version.h.template). 
</LI><LI>Generate replacement fields for the template file using an MSBuild script. 
</LI><LI>Replace the fields in the template to produce version.h. 
</LI><LI>Use a generic version.rc file that includes version.h. 
</LI><LI>Include version.rc in all resources files instead of a hardcoded OSVERSIONINFO resource.</LI></OL>
<P>A Version.h.template file looks like this.</P>
<P></P><div class="code"><pre><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#pragma</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">once<BR /><BR />#define </FONT></FONT><FONT size="2">VERSION_MAJOR ${Major}<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#define</FONT></FONT><FONT size="2"> VERSION_MINOR ${Minor}<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#define</FONT></FONT><FONT size="2"> VERSION_BUILD ${Build}<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#define</FONT></FONT><FONT size="2"> VERSION_REVISION ${Revision}<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"><BR />#define</FONT></FONT><FONT size="2"> VERSION_PRODUCTNAME_VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"${ProductName}"<BR /></FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#define</FONT></FONT><FONT size="2"> VERSION_COMPANYNAME_VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"${CompanyName}"<BR /></FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#define</FONT></FONT><FONT size="2"> VERSION_LEGALCOPYRIGHT_VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"${Copyright}"<BR /></FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#define</FONT></FONT><FONT size="2"> VERSION_LEGALTRADEMARK_VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"${Trademark}"<BR /></FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#define</FONT></FONT><FONT size="2"> VERSION_VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"${Major}.${Minor}.${Build}.${Revision}"<BR /></FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"><BR />#define</FONT></FONT><FONT size="2"> BINARY_VERSION ${Major},${Minor},${Build},${Revision}<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"><BR />#define</FONT></FONT><FONT size="2"> VERSION_FILEVERSION BINARY_VERSION<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#define</FONT></FONT><FONT size="2"> VERSION_PRODUCTVERSION BINARY_VERSION<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#define</FONT></FONT><FONT size="2"> VERSION_FILEVERSION_VALUE VERSION_VALUE<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#define</FONT></FONT><FONT size="2"> VERSION_PRODUCTVERSION_VALUE VERSION_VALUE</FONT></pre></div>
<P>The template replacement, task from <a target="_blank" href="http://msbuildtasks.tigris.org/"><img src="http://code.dblock.org/images/links/link.gif" border="0" align="absmiddle" width="16" height="16" /> MSBuild Community Tasks</a>.</P>
<P></P><div class="code"><pre><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">TemplateFile</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> <BR /> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">Template</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">src\Version\Version.h.template</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> <BR /> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">OutputFilename</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Version.h</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> <BR /> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">Tokens</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">@(AssemblyInfoTokens)</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">/&gt;</FONT></FONT></pre></div>
<P>And the version.rc file to include in every other .rc file.</P>
<P></P><div class="code"><pre><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#pragma</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">once<BR />#include</FONT></FONT><FONT size="2"> </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">&lt;Version/Version.h&gt;<BR /></FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#ifndef</FONT></FONT><FONT size="2"> _MAC<BR /></FONT><FONT color="#008000" size="2"><FONT color="#008000" size="2">/////////////////////////////////////////////////////////////////////////////<BR />//<BR />// Version<BR />//</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">
<P>#ifndef</P></FONT></FONT><FONT size="2"> VERSION_PROJECT_COMMENTS_VALUE<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#define</FONT></FONT><FONT size="2"> VERSION_PROJECT_COMMENTS_VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">""<BR /></FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#endif</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">
<P>#ifndef</P></FONT></FONT><FONT size="2"> VERSION_PROJECT_FILE_DESCRIPTION_VALUE<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#define</FONT></FONT><FONT size="2"> VERSION_PROJECT_FILE_DESCRIPTION_VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">""<BR /></FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#endif</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">
<P>#ifndef</P></FONT></FONT><FONT size="2"> VERSION_PROJECT_INTERNAL_NAME_VALUE<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#define</FONT></FONT><FONT size="2"> VERSION_PROJECT_INTERNAL_NAME_VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">""<BR /></FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#endif</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">
<P>#ifndef</P></FONT></FONT><FONT size="2"> VERSION_PROJECT_ORIGINAL_FILENAME_VALUE<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#define</FONT></FONT><FONT size="2"> VERSION_PROJECT_ORIGINAL_FILENAME_VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">""<BR /></FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#endif</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">
<P>#ifndef</P></FONT></FONT><FONT size="2"> VERSION_PROJECT_OLE_SELF_REGISTER_VALUE<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#define</FONT></FONT><FONT size="2"> VERSION_PROJECT_OLE_SELF_REGISTER_VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">""<BR /></FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#endif</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">
<P>#ifndef</P></FONT></FONT><FONT size="2"> VERSION_PROJECT_PRIVATE_BUILD_VALUE<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#define</FONT></FONT><FONT size="2"> VERSION_PROJECT_PRIVATE_BUILD_VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">""<BR /></FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#endif</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">
<P>#ifndef</P></FONT></FONT><FONT size="2"> VERSION_PROJECT_SPECIAL_BUILD_VALUE<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#define</FONT></FONT><FONT size="2"> VERSION_PROJECT_SPECIAL_BUILD_VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">""<BR /></FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#endif</FONT></FONT><FONT size="2"> </FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">
<P>#ifndef</P></FONT></FONT><FONT size="2"> VERSION_PROJECT_STRINGFILEINFO_BLOCK_VALUE<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#define</FONT></FONT><FONT size="2"> VERSION_PROJECT_STRINGFILEINFO_BLOCK_VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"040904B0"<BR /></FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#endif
<P>#ifndef</P></FONT></FONT><FONT size="2"> VERSION_PROJECT_VARFILEINFO_TRANSLATION_HEX_VALUE<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#define</FONT></FONT><FONT size="2"> VERSION_PROJECT_VARFILEINFO_TRANSLATION_HEX_VALUE 0x409<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#endif
<P>#ifndef</P></FONT></FONT><FONT size="2"> VERSION_PROJECT_VARFILEINFO_TRANSLATION_DEC_VALUE<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#define</FONT></FONT><FONT size="2"> VERSION_PROJECT_VARFILEINFO_TRANSLATION_DEC_VALUE 1200<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#endif</FONT></FONT><FONT size="2">
<P>VS_VERSION_INFO VERSIONINFO<BR />FILEVERSION VERSION_FILEVERSION<BR />PRODUCTVERSION VERSION_PRODUCTVERSION<BR />FILEFLAGSMASK 0x3fL<BR /></P></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#ifdef</FONT></FONT><FONT size="2"> _DEBUG<BR />FILEFLAGS 0x1L<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#else<BR /></FONT></FONT><FONT size="2">FILEFLAGS 0x0L<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#endif<BR /></FONT></FONT><FONT size="2">FILEOS 0x4L<BR />FILETYPE 0x2L<BR />FILESUBTYPE 0x0L<BR />BEGIN<BR />BLOCK </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"StringFileInfo"<BR /></FONT></FONT><FONT size="2">BEGIN<BR />BLOCK VERSION_PROJECT_STRINGFILEINFO_BLOCK_VALUE<BR />BEGIN<BR />VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"Comments"</FONT></FONT><FONT size="2">, VERSION_PROJECT_COMMENTS_VALUE<BR /></FONT><FONT size="2">VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"CompanyName"</FONT></FONT><FONT size="2">, VERSION_COMPANYNAME_VALUE<BR />VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"FileDescription"</FONT></FONT><FONT size="2">, VERSION_PROJECT_FILE_DESCRIPTION_VALUE<BR />VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"FileVersion"</FONT></FONT><FONT size="2">, VERSION_FILEVERSION_VALUE<BR />VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"InternalName"</FONT></FONT><FONT size="2">, VERSION_PROJECT_INTERNAL_NAME_VALUE<BR />VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"LegalCopyright"</FONT></FONT><FONT size="2">, VERSION_LEGALCOPYRIGHT_VALUE<BR />VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"LegalTrademarks"</FONT></FONT><FONT size="2">, VERSION_LEGALTRADEMARK_VALUE<BR />VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"OLESelfRegister"</FONT></FONT><FONT size="2">, VERSION_PROJECT_OLE_SELF_REGISTER_VALUE<BR />VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"OriginalFilename"</FONT></FONT><FONT size="2">, VERSION_PROJECT_ORIGINAL_FILENAME_VALUE<BR />VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"PrivateBuild"</FONT></FONT><FONT size="2">, VERSION_PROJECT_PRIVATE_BUILD_VALUE<BR />VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"ProductName"</FONT></FONT><FONT size="2">, VERSION_PRODUCTNAME_VALUE<BR />VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"ProductVersion"</FONT></FONT><FONT size="2">, VERSION_PRODUCTVERSION_VALUE<BR />VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"SpecialBuild"</FONT></FONT><FONT size="2">, VERSION_PROJECT_SPECIAL_BUILD_VALUE<BR />END<BR />END<BR />BLOCK </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"VarFileInfo"<BR /></FONT></FONT><FONT size="2">BEGIN<BR />VALUE </FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">"Translation"</FONT></FONT><FONT size="2">, VERSION_PROJECT_VARFILEINFO_TRANSLATION_HEX_VALUE, VERSION_PROJECT_VARFILEINFO_TRANSLATION_DEC_VALUE<BR />END<BR />END<BR /></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">#endif</FONT></FONT><FONT size="2"> </FONT><FONT color="#008000" size="2"><FONT color="#008000" size="2">// !_MAC<BR /></FONT></FONT></pre></div>
<P></P>
<P><B>Versioning Other Targets</B></P>
<P>The same template idea applies to all kinds of targets. For example, the doxygen documentation.</P>
<P></P><div class="code"><pre><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">TemplateFile</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> <BR /> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">Template</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">doc\Doxyfile.template</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> <BR /> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">OutputFilename</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">Doxyfile</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> <BR /> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">Tokens</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">@(AssemblyInfoTokens)</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">/&gt;</FONT></FONT></pre></div>
<H3>Implementation with Ant</H3>
<P>The major and minor version (property version.majorminor) are stored in the version.properties file. The file is included in the ant build script. </P>
<P></P><div class="code"><pre><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">property</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">file</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">version.properties</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">/&gt;</FONT></FONT></pre></div>
<P>The following code fragment gets the svn revision of the current directory. </P>
<P></P><div class="code"><pre><BR /><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">target</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">name</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">get-svn-revision</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR /> &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">tempfile</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">property</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">temp.file.for.get-svn-revision</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">/&gt;<BR /> &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">exec</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">dir</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">.</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">executable</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">svn</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">failonerror</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">true</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">output</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">${temp.file.for.get-svn-revision}</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR />  &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">arg</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">line</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">info . --non-interactive</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">/&gt;<BR /> &lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">exec</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR /> &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">loadproperties</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">srcFile</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">${temp.file.for.get-svn-revision}</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR />  &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">filterchain</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR />   &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">linecontainsregexp</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR />    &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">regexp</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">pattern</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">^Revision: </FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">/&gt;<BR />   &lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">linecontainsregexp</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR /></FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">   &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">tokenfilter</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR />    &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">containsregex</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">pattern</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">^Revision: ([0-9]+)</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">replace</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">svn.revision=\1</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">/&gt;<BR />   &lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">tokenfilter</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR />  &lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">filterchain</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR /> &lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">loadproperties</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;<BR /> &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">delete</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">quiet</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">true</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">file</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">${temp.file.for.get-svn-revision}</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">/&gt;<BR /> &lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">echo</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">message</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">svn.revision=${svn.revision}</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">/&gt;<BR />&lt;/</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">target</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&gt;</FONT></FONT> <BR /></pre></div>
<P>Finally, the auto-incremented build number is generated with the following tag (which should be run once per build, somewhere in initialization).</P>
<P></P><div class="code"><pre><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">buildnumber</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> /&gt;</FONT></FONT></pre></div>
<P>This sets the build.number property. The build files may then use the version.full property, created in the following way.</P>
<P></P><div class="code"><pre><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">&lt;</FONT></FONT><FONT color="#a31515" size="2"><FONT color="#a31515" size="2">property</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">name</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">version.full</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> </FONT></FONT><FONT color="#ff0000" size="2"><FONT color="#ff0000" size="2">value</FONT></FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">=</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2">${version.majorminor}.${svn.revision}.${build.number}</FONT></FONT><FONT size="2">"</FONT><FONT color="#0000ff" size="2"><FONT color="#0000ff" size="2"> /&gt;</FONT></FONT></pre></div>
<H3>Implementation in CruiseControl</H3>
<P>CruiseControl supports the concept of build publishe