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

<channel>
	<title>Software Expressions</title>
	<atom:link href="http://dalldorf.com/home/index.php?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://dalldorf.com/home</link>
	<description>.Net / Software / Visual Studio / TFS / other ramblings</description>
	<pubDate>Thu, 05 Feb 2009 01:10:19 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.3</generator>
	<language>en</language>
			<item>
		<title>Convert Class Libary to Test Project</title>
		<link>http://dalldorf.com/home/?p=263</link>
		<comments>http://dalldorf.com/home/?p=263#comments</comments>
		<pubDate>Wed, 04 Feb 2009 15:53:27 +0000</pubDate>
		<dc:creator>Troy</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://dalldorf.com/home/?p=263</guid>
		<description><![CDATA[Converting a class library in Visual Studio 2008 to a Test Project is as easy as opening up: the .vbproj or .csproj in NotePad and adding a ProjectTypeGuids element under the PropertyGroup element.  This should be around the AssemblyName element.

&#60;ProjectTypeGuids&#62;{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{F184B08F-C81C-45F6-A57F-5ABD9991F28F}&#60;/ProjectTypeGuids&#62;

There is one more catch.  If you convert multiple Class Libraries, the second guid [...]]]></description>
			<content:encoded><![CDATA[<p>Converting a class library in Visual Studio 2008 to a Test Project is as easy as opening up: the .vbproj or .csproj in NotePad and adding a <strong>ProjectTypeGuids</strong> element under the <strong>PropertyGroup</strong> element.  This should be around the <strong>AssemblyName</strong> element.</p>
<p><code><br />
&lt;ProjectTypeGuids&gt;{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{F184B08F-C81C-45F6-A57F-5ABD9991F28F}&lt;/ProjectTypeGuids&gt;<br />
</code></p>
<p>There is one more catch.  If you convert multiple Class Libraries, the second guid must be unique.  Otherwise you will receive the &#8220;A project with the same name is already opened in the solution&#8221; error when adding the second Test Project or when you open the solution.</p>
]]></content:encoded>
			<wfw:commentRss>http://dalldorf.com/home/?feed=rss2&amp;p=263</wfw:commentRss>
		</item>
		<item>
		<title>Mounting virtual hard disks at the command line</title>
		<link>http://dalldorf.com/home/?p=260</link>
		<comments>http://dalldorf.com/home/?p=260#comments</comments>
		<pubDate>Wed, 03 Dec 2008 14:26:23 +0000</pubDate>
		<dc:creator>Troy</dc:creator>
		
		<category><![CDATA[Other Stuff]]></category>

		<guid isPermaLink="false">http://dalldorf.com/home/?p=260</guid>
		<description><![CDATA[Backing up the data on my virtual PC has always been a little painful.  I use a NAS Server (NASLite) with SecondCopy to perform the backups in the early hours of the morning.  However, it&#8217;s very likely that my VirtualPC is shutdown, and so SecondCopy running in the VirtualPC only gets to perform [...]]]></description>
			<content:encoded><![CDATA[<p>Backing up the data on my virtual PC has always been a little painful.  I use a NAS Server (NASLite) with SecondCopy to perform the backups in the early hours of the morning.  However, it&#8217;s very likely that my VirtualPC is shutdown, and so SecondCopy running in the VirtualPC only gets to perform the backup every few weeks - and that&#8217;s not guaranteed.  With this command line utility it&#8217;s possible to include a batch file in SecondCopy which mounts the VHD and then performs the backup.  It&#8217;s perfect.  <a href="http://technet.microsoft.com/en-us/library/cc708295.aspx">http://technet.microsoft.com/en-us/library/cc708295.aspx</a><br />
&#8230;and then there&#8217;s also this article which describes compacting your VHD outside of VirtualPC using the VHD mount utility: <a href="http://vscommunity.com/blogs/virtualzone/archive/2007/01/17/three-steps-to-vhd-compaction-with-virtual-server-2005-r2-sp1.aspx">http://vscommunity.com/blogs/virtualzone/archive/2007/01/17/three-steps-to-vhd-compaction-with-virtual-server-2005-r2-sp1.aspx</a></p>
]]></content:encoded>
			<wfw:commentRss>http://dalldorf.com/home/?feed=rss2&amp;p=260</wfw:commentRss>
		</item>
		<item>
		<title></title>
		<link>http://dalldorf.com/home/?p=259</link>
		<comments>http://dalldorf.com/home/?p=259#comments</comments>
		<pubDate>Tue, 18 Nov 2008 17:33:03 +0000</pubDate>
		<dc:creator>Troy</dc:creator>
		
		<category><![CDATA[CustomerComments]]></category>

		<guid isPermaLink="false">http://dalldorf.com/home/?p=259</guid>
		<description><![CDATA[I am always dazzled with your consistency and your practical approach to issues. You surely must be brilliant for being able to create the architecture we have - QA Lead
]]></description>
			<content:encoded><![CDATA[<p>I am always dazzled with your consistency and your practical approach to issues. You surely must be brilliant for being able to create the architecture we have - QA Lead</p>
]]></content:encoded>
			<wfw:commentRss>http://dalldorf.com/home/?feed=rss2&amp;p=259</wfw:commentRss>
		</item>
		<item>
		<title>Button theory</title>
		<link>http://dalldorf.com/home/?p=258</link>
		<comments>http://dalldorf.com/home/?p=258#comments</comments>
		<pubDate>Fri, 14 Nov 2008 22:04:30 +0000</pubDate>
		<dc:creator>Troy</dc:creator>
		
		<category><![CDATA[User Experience]]></category>

		<guid isPermaLink="false">http://dalldorf.com/home/?p=258</guid>
		<description><![CDATA[Buttons on Windows applications have been around since the first version of Windows.  One would think that the patterns for using buttons would have been firmly established by now.  In particular rules for disabling and enabling buttons.
Concerning visibility: 
Buttons should never be made invisible based on some transient state.  i.e. Don&#8217;t hide [...]]]></description>
			<content:encoded><![CDATA[<p>Buttons on Windows applications have been around since the first version of Windows.  One would think that the patterns for using buttons would have been firmly established by now.  In particular rules for disabling and enabling buttons.<br />
Concerning visibility: </p>
<li>Buttons should never be made invisible based on some transient state.  i.e. Don&#8217;t hide the button when the user is disconnected from the internet, or hide the button when the order has already been placed.</li>
<li>Users should expect to see buttons in the same order and same location for a given context.</li>
<li>Hiding buttons is good for things like user permissions.  If you don&#8217;t have the permission to delete the customer information, there&#8217;s no need to see the button ever.</li>
<p>Concerning enable and disable:</p>
<li>If a button is no longer available due to a transient state, or state of the underlying object, disable it.  This keeps the screens and button layout consistent.</li>
<li>Don&#8217;t disable the button without giving the user a reason.  This may seem strange, but you <em>can</em> display a tooltip on a disabled button.  Let the user know why they&#8217;re not able to perform the action.  Don&#8217;t leave them guessing.</li>
<li>I suppose there could be exceptions to this.  In some cases it may really be obvious.</li>
<li>If it&#8217;s not really obvious and you can&#8217;t display a tooltip on a disabled button, leave the button enabled and display a pop-up message indicating why.</li>
<li>The more rules there are that control whether or not the button is available, the more reasons there are to clearly communicate this to the user.</li>
]]></content:encoded>
			<wfw:commentRss>http://dalldorf.com/home/?feed=rss2&amp;p=258</wfw:commentRss>
		</item>
		<item>
		<title>Serializing images</title>
		<link>http://dalldorf.com/home/?p=257</link>
		<comments>http://dalldorf.com/home/?p=257#comments</comments>
		<pubDate>Fri, 14 Nov 2008 21:50:26 +0000</pubDate>
		<dc:creator>Troy</dc:creator>
		
		<category><![CDATA[CSLA]]></category>

		<category><![CDATA[Code Sample]]></category>

		<guid isPermaLink="false">http://dalldorf.com/home/?p=257</guid>
		<description><![CDATA[The System.Drawing.Image class is not serializable by default.  This class can be used to serialize images as well as load the image from the IDataRecord.


   1:  Imports System.Drawing
   2:  Imports System.Runtime.Serialization
   3:  Imports System.Drawing.Imaging
   4:  Imports System.IO
   5:  &#160;
 [...]]]></description>
			<content:encoded><![CDATA[<p>The System.Drawing.Image class is not serializable by default.  This class can be used to serialize images as well as load the image from the IDataRecord.<br />
<!-- code formatted by http://manoli.net/csharpformat/ --></p>
<div class="csharpcode">
<pre><span class="lnum">   1:  </span><span class="kwrd">Imports</span> System.Drawing</pre>
<pre><span class="lnum">   2:  </span><span class="kwrd">Imports</span> System.Runtime.Serialization</pre>
<pre><span class="lnum">   3:  </span><span class="kwrd">Imports</span> System.Drawing.Imaging</pre>
<pre><span class="lnum">   4:  </span><span class="kwrd">Imports</span> System.IO</pre>
<pre><span class="lnum">   5:  </span>&nbsp;</pre>
<pre><span class="lnum">   6:  </span>&lt;Serializable()&gt; _</pre>
<pre><span class="lnum">   7:  </span><span class="kwrd">Public</span> <span class="kwrd">Class</span> SerializableImage</pre>
<pre><span class="lnum">   8:  </span>    <span class="kwrd">Implements</span> ISerializable</pre>
<pre><span class="lnum">   9:  </span> </pre>
<pre><span class="lnum">  10:  </span>    <span class="kwrd">Private</span> _master <span class="kwrd">As</span> MasterEnum = MasterEnum.Image</pre>
<pre><span class="lnum">  11:  </span>    <span class="kwrd">Private</span> _imageBuffer <span class="kwrd">As</span> <span class="kwrd">Byte</span>()</pre>
<pre><span class="lnum">  12:  </span>    <span class="kwrd">Private</span> _image <span class="kwrd">As</span> Image</pre>
<pre><span class="lnum">  13:  </span>    <span class="kwrd">Private</span> _serializationFormat <span class="kwrd">As</span> ImageFormat = ImageFormat.Png</pre>
<pre><span class="lnum">  14:  </span>&nbsp;</pre>
<pre><span class="lnum">  15:  </span>    <span class="kwrd">Public</span> <span class="kwrd">Property</span> Image() <span class="kwrd">As</span> Image</pre>
<pre><span class="lnum">  16:  </span>        <span class="kwrd">Get</span></pre>
<pre><span class="lnum">  17:  </span>            <span class="kwrd">If</span> _master &lt;&gt; MasterEnum.Image <span class="kwrd">Then</span></pre>
<pre><span class="lnum">  18:  </span>                CreateImageFromBuffer()</pre>
<pre><span class="lnum">  19:  </span>            <span class="kwrd">End</span> <span class="kwrd">If</span></pre>
<pre><span class="lnum">  20:  </span>            <span class="kwrd">Return</span> _image</pre>
<pre><span class="lnum">  21:  </span>        <span class="kwrd">End</span> <span class="kwrd">Get</span></pre>
<pre><span class="lnum">  22:  </span>        <span class="kwrd">Set</span>(<span class="kwrd">ByVal</span> value <span class="kwrd">As</span> Image)</pre>
<pre><span class="lnum">  23:  </span>            <span class="kwrd">If</span> (value <span class="kwrd">Is</span> _image) <span class="kwrd">Then</span> <span class="kwrd">Return</span></pre>
<pre><span class="lnum">  24:  </span>            _image = value</pre>
<pre><span class="lnum">  25:  </span>            ‘The image becomes the master once the setter <span class="kwrd">is</span> used</pre>
<pre><span class="lnum">  26:  </span>            _master = MasterEnum.Image</pre>
<pre><span class="lnum">  27:  </span>            _imageBuffer = <span class="kwrd">Nothing</span></pre>
<pre><span class="lnum">  28:  </span>        <span class="kwrd">End</span> <span class="kwrd">Set</span></pre>
<pre><span class="lnum">  29:  </span>    <span class="kwrd">End</span> <span class="kwrd">Property</span></pre>
<pre><span class="lnum">  30:  </span>&nbsp;</pre>
<pre><span class="lnum">  31:  </span>    <span class="kwrd">Private</span> <span class="kwrd">Sub</span> CreateImageFromBuffer()</pre>
<pre><span class="lnum">  32:  </span>        ‘Once this method <span class="kwrd">is</span> called, the image becomes the master</pre>
<pre><span class="lnum">  33:  </span>        _master = MasterEnum.Image</pre>
<pre><span class="lnum">  34:  </span>        ‘Check <span class="kwrd">if</span> there <span class="kwrd">is</span> a buffer</pre>
<pre><span class="lnum">  35:  </span>        <span class="kwrd">If</span> _imageBuffer <span class="kwrd">Is</span> <span class="kwrd">Nothing</span> <span class="kwrd">OrElse</span> _imageBuffer.Length = 0 <span class="kwrd">Then</span></pre>
<pre><span class="lnum">  36:  </span>            Image = <span class="kwrd">Nothing</span></pre>
<pre><span class="lnum">  37:  </span>        <span class="kwrd">Else</span></pre>
<pre><span class="lnum">  38:  </span>            ‘http://support.microsoft.com/?id=814675</pre>
<pre><span class="lnum">  39:  </span>            Using s <span class="kwrd">As</span> <span class="kwrd">New</span> MemoryStream(_imageBuffer)</pre>
<pre><span class="lnum">  40:  </span>                <span class="kwrd">If</span> <span class="kwrd">Not</span> s <span class="kwrd">Is</span> System.IO.Stream.Null <span class="kwrd">Then</span></pre>
<pre><span class="lnum">  41:  </span>                    <span class="kwrd">Dim</span> tempImage <span class="kwrd">As</span> Image = _</pre>
<pre><span class="lnum">  42:  </span>                        <span class="kwrd">DirectCast</span>(Bitmap.FromStream(s), Bitmap)</pre>
<pre><span class="lnum">  43:  </span>                    Image = <span class="kwrd">New</span> Bitmap(tempImage)</pre>
<pre><span class="lnum">  44:  </span>                    <span class="kwrd">Dim</span> g <span class="kwrd">As</span> Graphics = Graphics.FromImage(tempImage)</pre>
<pre><span class="lnum">  45:  </span>                    g.DrawImage(Image, <span class="kwrd">New</span> PointF(0, 0))</pre>
<pre><span class="lnum">  46:  </span>                    g.Dispose()</pre>
<pre><span class="lnum">  47:  </span>                    tempImage.Dispose()</pre>
<pre><span class="lnum">  48:  </span>                <span class="kwrd">End</span> <span class="kwrd">If</span></pre>
<pre><span class="lnum">  49:  </span>                s.Close()</pre>
<pre><span class="lnum">  50:  </span>            <span class="kwrd">End</span> Using</pre>
<pre><span class="lnum">  51:  </span>        <span class="kwrd">End</span> <span class="kwrd">If</span></pre>
<pre><span class="lnum">  52:  </span>    <span class="kwrd">End</span> <span class="kwrd">Sub</span></pre>
<pre><span class="lnum">  53:  </span>&nbsp;</pre>
<pre><span class="lnum">  54:  </span>    <span class="kwrd">Private</span> <span class="kwrd">Property</span> ImageBuffer() <span class="kwrd">As</span> <span class="kwrd">Byte</span>()</pre>
<pre><span class="lnum">  55:  </span>        <span class="kwrd">Get</span></pre>
<pre><span class="lnum">  56:  </span>            <span class="kwrd">Select</span> <span class="kwrd">Case</span> _master</pre>
<pre><span class="lnum">  57:  </span>                <span class="kwrd">Case</span> MasterEnum.Image</pre>
<pre><span class="lnum">  58:  </span>                    ‘Used <span class="kwrd">for</span> serialization</pre>
<pre><span class="lnum">  59:  </span>                    <span class="kwrd">Return</span> CreateBufferFromImage()</pre>
<pre><span class="lnum">  60:  </span>                <span class="kwrd">Case</span> MasterEnum.Buffer</pre>
<pre><span class="lnum">  61:  </span>                    <span class="kwrd">Return</span> _imageBuffer</pre>
<pre><span class="lnum">  62:  </span>            <span class="kwrd">End</span> <span class="kwrd">Select</span></pre>
<pre><span class="lnum">  63:  </span>            <span class="kwrd">Return</span> _imageBuffer</pre>
<pre><span class="lnum">  64:  </span>        <span class="kwrd">End</span> <span class="kwrd">Get</span></pre>
<pre><span class="lnum">  65:  </span>        <span class="kwrd">Set</span>(<span class="kwrd">ByVal</span> value <span class="kwrd">As</span> <span class="kwrd">Byte</span>())</pre>
<pre><span class="lnum">  66:  </span>            <span class="kwrd">If</span> (value <span class="kwrd">Is</span> _imageBuffer) <span class="kwrd">Then</span> <span class="kwrd">Return</span></pre>
<pre><span class="lnum">  67:  </span>            _imageBuffer = value</pre>
<pre><span class="lnum">  68:  </span>            ‘The Buffer becomes the master</pre>
<pre><span class="lnum">  69:  </span>            _master = MasterEnum.Buffer</pre>
<pre><span class="lnum">  70:  </span>            _image = <span class="kwrd">Nothing</span></pre>
<pre><span class="lnum">  71:  </span>        <span class="kwrd">End</span> <span class="kwrd">Set</span></pre>
<pre><span class="lnum">  72:  </span>    <span class="kwrd">End</span> <span class="kwrd">Property</span></pre>
<pre><span class="lnum">  73:  </span>&nbsp;</pre>
<pre><span class="lnum">  74:  </span>    <span class="kwrd">Private</span> <span class="kwrd">Function</span> CreateBufferFromImage() <span class="kwrd">As</span> <span class="kwrd">Byte</span>()</pre>
<pre><span class="lnum">  75:  </span>        <span class="kwrd">If</span> _image <span class="kwrd">Is</span> <span class="kwrd">Nothing</span> <span class="kwrd">Then</span> <span class="kwrd">Return</span> <span class="kwrd">Nothing</span></pre>
<pre><span class="lnum">  76:  </span>        ‘Convert the image <span class="kwrd">to</span> a <span class="kwrd">byte</span> array using the serialization format</pre>
<pre><span class="lnum">  77:  </span>        Using stream <span class="kwrd">As</span> <span class="kwrd">New</span> MemoryStream</pre>
<pre><span class="lnum">  78:  </span>            _image.Save(stream, SerializationFormat)</pre>
<pre><span class="lnum">  79:  </span>            <span class="kwrd">Dim</span> result <span class="kwrd">As</span> <span class="kwrd">Byte</span>() = stream.ToArray()</pre>
<pre><span class="lnum">  80:  </span>            stream.Close()</pre>
<pre><span class="lnum">  81:  </span>            <span class="kwrd">Return</span> result</pre>
<pre><span class="lnum">  82:  </span>        <span class="kwrd">End</span> Using</pre>
<pre><span class="lnum">  83:  </span>    <span class="kwrd">End</span> <span class="kwrd">Function</span></pre>
<pre><span class="lnum">  84:  </span>&nbsp;</pre>
<pre><span class="lnum">  85:  </span>    <span class="kwrd">Public</span> <span class="kwrd">Property</span> SerializationFormat() <span class="kwrd">As</span> ImageFormat</pre>
<pre><span class="lnum">  86:  </span>        <span class="kwrd">Get</span></pre>
<pre><span class="lnum">  87:  </span>            <span class="kwrd">Return</span> _serializationFormat</pre>
<pre><span class="lnum">  88:  </span>        <span class="kwrd">End</span> <span class="kwrd">Get</span></pre>
<pre><span class="lnum">  89:  </span>        <span class="kwrd">Set</span>(<span class="kwrd">ByVal</span> value <span class="kwrd">As</span> ImageFormat)</pre>
<pre><span class="lnum">  90:  </span>            _serializationFormat = value</pre>
<pre><span class="lnum">  91:  </span>        <span class="kwrd">End</span> <span class="kwrd">Set</span></pre>
<pre><span class="lnum">  92:  </span>    <span class="kwrd">End</span> <span class="kwrd">Property</span></pre>
<pre><span class="lnum">  93:  </span>&nbsp;</pre>
<pre><span class="lnum">  94:  </span>    <span class="kwrd">Public</span> <span class="kwrd">Sub</span> <span class="kwrd">New</span>()</pre>
<pre><span class="lnum">  95:  </span>&nbsp;</pre>
<pre><span class="lnum">  96:  </span>    <span class="kwrd">End</span> <span class="kwrd">Sub</span></pre>
<pre><span class="lnum">  97:  </span>&nbsp;</pre>
<pre><span class="lnum">  98:  </span>    <span class="kwrd">Public</span> <span class="kwrd">Sub</span> <span class="kwrd">New</span>(<span class="kwrd">ByVal</span> image <span class="kwrd">As</span> Image)</pre>
<pre><span class="lnum">  99:  </span>        <span class="kwrd">Me</span>.Image = image</pre>
<pre><span class="lnum"> 100:  </span>    <span class="kwrd">End</span> <span class="kwrd">Sub</span></pre>
<pre><span class="lnum"> 101:  </span>&nbsp;</pre>
<pre><span class="lnum"> 102:  </span>    <span class="kwrd">Public</span> <span class="kwrd">Sub</span> <span class="kwrd">New</span>(<span class="kwrd">ByVal</span> record <span class="kwrd">As</span> IDataRecord, <span class="kwrd">ByVal</span> fieldIndex <span class="kwrd">As</span> <span class="kwrd">Integer</span>)</pre>
<pre><span class="lnum"> 103:  </span>        Load(record, fieldIndex)</pre>
<pre><span class="lnum"> 104:  </span>    <span class="kwrd">End</span> <span class="kwrd">Sub</span></pre>
<pre><span class="lnum"> 105:  </span>&nbsp;</pre>
<pre><span class="lnum"> 106:  </span>    <span class="kwrd">Public</span> <span class="kwrd">Sub</span> <span class="kwrd">New</span>(<span class="kwrd">ByVal</span> record <span class="kwrd">As</span> IDataRecord, <span class="kwrd">ByVal</span> fieldName <span class="kwrd">As</span> <span class="kwrd">String</span>)</pre>
<pre><span class="lnum"> 107:  </span>        Load(record, fieldName)</pre>
<pre><span class="lnum"> 108:  </span>    <span class="kwrd">End</span> <span class="kwrd">Sub</span></pre>
<pre><span class="lnum"> 109:  </span>&nbsp;</pre>
<pre><span class="lnum"> 110:  </span>    <span class="kwrd">Private</span> <span class="kwrd">Sub</span> Load(<span class="kwrd">ByVal</span> record <span class="kwrd">As</span> IDataRecord, <span class="kwrd">ByVal</span> fieldName <span class="kwrd">As</span> <span class="kwrd">String</span>)</pre>
<pre><span class="lnum"> 111:  </span>        <span class="kwrd">If</span> record <span class="kwrd">Is</span> <span class="kwrd">Nothing</span> <span class="kwrd">Then</span> <span class="kwrd">Throw</span> <span class="kwrd">New</span> ArgumentNullException(“record”)</pre>
<pre><span class="lnum"> 112:  </span>        Load(record, record.GetOrdinal(fieldName))</pre>
<pre><span class="lnum"> 113:  </span>    <span class="kwrd">End</span> <span class="kwrd">Sub</span></pre>
<pre><span class="lnum"> 114:  </span>&nbsp;</pre>
<pre><span class="lnum"> 115:  </span>    <span class="kwrd">Private</span> <span class="kwrd">Sub</span> Load(<span class="kwrd">ByVal</span> record <span class="kwrd">As</span> IDataRecord, <span class="kwrd">ByVal</span> fieldIndex <span class="kwrd">As</span> <span class="kwrd">Integer</span>)</pre>
<pre><span class="lnum"> 116:  </span>        <span class="kwrd">If</span> record <span class="kwrd">Is</span> <span class="kwrd">Nothing</span> <span class="kwrd">Then</span> <span class="kwrd">Throw</span> <span class="kwrd">New</span> ArgumentNullException(“record”)</pre>
<pre><span class="lnum"> 117:  </span>        <span class="kwrd">If</span> record.IsDBNull(fieldIndex) <span class="kwrd">Then</span> <span class="kwrd">Return</span></pre>
<pre><span class="lnum"> 118:  </span>        ImageBuffer = <span class="kwrd">DirectCast</span>(record.GetValue(fieldIndex), <span class="kwrd">Byte</span>())</pre>
<pre><span class="lnum"> 119:  </span>    <span class="kwrd">End</span> <span class="kwrd">Sub</span></pre>
<pre><span class="lnum"> 120:  </span>&nbsp;</pre>
<pre><span class="lnum"> 121:  </span>    <span class="kwrd">Public</span> <span class="kwrd">Sub</span> <span class="kwrd">New</span>(<span class="kwrd">ByVal</span> info <span class="kwrd">As</span> SerializationInfo, _</pre>
<pre><span class="lnum"> 122:  </span>        <span class="kwrd">ByVal</span> context <span class="kwrd">As</span> StreamingContext)</pre>
<pre><span class="lnum"> 123:  </span>        ‘Image</pre>
<pre><span class="lnum"> 124:  </span>        <span class="kwrd">Dim</span> data <span class="kwrd">As</span> <span class="kwrd">Byte</span>() = _</pre>
<pre><span class="lnum"> 125:  </span>            <span class="kwrd">DirectCast</span>(info.GetValue(“image”, <span class="kwrd">GetType</span>(<span class="kwrd">Byte</span>())), <span class="kwrd">Byte</span>())</pre>
<pre><span class="lnum"> 126:  </span>        <span class="kwrd">If</span> data IsNot <span class="kwrd">Nothing</span> <span class="kwrd">AndAlso</span> data.Length &gt; 0 <span class="kwrd">Then</span></pre>
<pre><span class="lnum"> 127:  </span>            ‘http://support.microsoft.com/?id=814675</pre>
<pre><span class="lnum"> 128:  </span>            Using s <span class="kwrd">As</span> <span class="kwrd">New</span> MemoryStream(data)</pre>
<pre><span class="lnum"> 129:  </span>                <span class="kwrd">If</span> <span class="kwrd">Not</span> s <span class="kwrd">Is</span> System.IO.Stream.Null <span class="kwrd">Then</span></pre>
<pre><span class="lnum"> 130:  </span>                    <span class="kwrd">Dim</span> tempImage <span class="kwrd">As</span> Image = _</pre>
<pre><span class="lnum"> 131:  </span>                        <span class="kwrd">DirectCast</span>(Bitmap.FromStream(s), Bitmap)</pre>
<pre><span class="lnum"> 132:  </span>                    Image = <span class="kwrd">New</span> Bitmap(tempImage)</pre>
<pre><span class="lnum"> 133:  </span>                    <span class="kwrd">Dim</span> g <span class="kwrd">As</span> Graphics = Graphics.FromImage(tempImage)</pre>
<pre><span class="lnum"> 134:  </span>                    g.DrawImage(Image, <span class="kwrd">New</span> PointF(0, 0))</pre>
<pre><span class="lnum"> 135:  </span>                    g.Dispose()</pre>
<pre><span class="lnum"> 136:  </span>                    tempImage.Dispose()</pre>
<pre><span class="lnum"> 137:  </span>                <span class="kwrd">End</span> <span class="kwrd">If</span></pre>
<pre><span class="lnum"> 138:  </span>                s.Close()</pre>
<pre><span class="lnum"> 139:  </span>            <span class="kwrd">End</span> Using</pre>
<pre><span class="lnum"> 140:  </span>        <span class="kwrd">End</span> <span class="kwrd">If</span></pre>
<pre><span class="lnum"> 141:  </span>    <span class="kwrd">End</span> <span class="kwrd">Sub</span></pre>
<pre><span class="lnum"> 142:  </span>&nbsp;</pre>
<pre><span class="lnum"> 143:  </span>    <span class="kwrd">Public</span> <span class="kwrd">Sub</span> GetObjectData(<span class="kwrd">ByVal</span> info <span class="kwrd">As</span> SerializationInfo, +</pre>
<pre><span class="lnum"> 144:  </span>        <span class="kwrd">ByVal</span> context <span class="kwrd">As</span> StreamingContext) <span class="kwrd">Implements</span> ISerializable.GetObjectData</pre>
<pre><span class="lnum"> 145:  </span>        info.AddValue(“image”, ImageBuffer, <span class="kwrd">GetType</span>(<span class="kwrd">Byte</span>()))</pre>
<pre><span class="lnum"> 146:  </span>    <span class="kwrd">End</span> <span class="kwrd">Sub</span></pre>
<pre><span class="lnum"> 147:  </span>&nbsp;</pre>
<pre><span class="lnum"> 148:  </span>    <span class="kwrd">Private</span> <span class="kwrd">Enum</span> MasterEnum</pre>
<pre><span class="lnum"> 149:  </span>        Buffer</pre>
<pre><span class="lnum"> 150:  </span>        Image</pre>
<pre><span class="lnum"> 151:  </span>    <span class="kwrd">End</span> <span class="kwrd">Enum</span></pre>
<pre><span class="lnum"> 152:  </span>&nbsp;</pre>
<pre><span class="lnum"> 153:  </span><span class="kwrd">End</span> Class</pre>
</div>
]]></content:encoded>
			<wfw:commentRss>http://dalldorf.com/home/?feed=rss2&amp;p=257</wfw:commentRss>
		</item>
		<item>
		<title>How to make a bootable thumb drive virus scanner for NTFS</title>
		<link>http://dalldorf.com/home/?p=256</link>
		<comments>http://dalldorf.com/home/?p=256#comments</comments>
		<pubDate>Fri, 14 Nov 2008 14:11:48 +0000</pubDate>
		<dc:creator>Troy</dc:creator>
		
		<category><![CDATA[Other Stuff]]></category>

		<guid isPermaLink="false">http://dalldorf.com/home/?p=256</guid>
		<description><![CDATA[Some friends were experiencing problems with a virus (run32dll - possibly WhisperB-worm), while searching for the best approach to resolve this issue I came across this really simple and impressive article.  I guess I&#8217;m rather old-school when it comes to viruses and haven&#8217;t dealt much with them for many years.  Back in the [...]]]></description>
			<content:encoded><![CDATA[<p>Some friends were experiencing problems with a virus (run32dll - possibly WhisperB-worm), while searching for the best approach to resolve this issue I came across this really simple and impressive article.  I guess I&#8217;m rather old-school when it comes to viruses and haven&#8217;t dealt much with them for many years.  Back in the DOS days you would create a boot disk with your virus software.  You would boot up on the clean boot disk, and run the scan on C:.  There was nothing else to it.  It seems to be rather more complicated these days - and I&#8217;m not sure it needs to be.  For one thing, how can you download virus scanning software and run it on a machine with a virus?  How can you run a Windows virus scanning software on a machine where when Windows starts up it already has the virus loaded.  This was evidently the problem in this case because the virus scanners that were downloaded picked up no viruses.  Indeed the virus software had cleverly intercepted the scanner.  It was obvious because during the scan the machine would reboot.  The scanning software couldn&#8217;t even download all it&#8217;s updated virus signatures&#8230;<br />
<a href="http://askthegeek.kennyhart.com/2005/12/how-to-make-bootable-thumb-drive-virus.html">http://askthegeek.kennyhart.com/2005/12/how-to-make-bootable-thumb-drive-virus.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://dalldorf.com/home/?feed=rss2&amp;p=256</wfw:commentRss>
		</item>
		<item>
		<title>Sync Services Headaches</title>
		<link>http://dalldorf.com/home/?p=250</link>
		<comments>http://dalldorf.com/home/?p=250#comments</comments>
		<pubDate>Sat, 11 Oct 2008 02:50:47 +0000</pubDate>
		<dc:creator>Troy</dc:creator>
		
		<category><![CDATA[Oracle]]></category>

		<category><![CDATA[Other Stuff]]></category>

		<guid isPermaLink="false">http://dalldorf.com/home/?p=250</guid>
		<description><![CDATA[On my current project we decided to leverage Microsoft Sync Services (since we were already using SQL CE for our local database in a smart-client solution with an Oracle back end, it seemed to be the logical choice). After a few months of tweaking and jumping through a few hoops to get SQL CE and Oracle to play together, we had a solution that appeared to work just fine... on the surface anyway. We decided to assess the solution we had and see how far down the road it would take us. This article describes our findings which are some inherent problems, some problems integrating with Oracle, some performance related, and some just because one size does not fit all.]]></description>
			<content:encoded><![CDATA[<p>On my current project we decided to leverage Microsoft Sync Services (since we were already using SQL CE for our local database in a smart-client solution with an Oracle back end, it seemed to be the logical choice). After a few months of tweaking and jumping through a few hoops to get SQL CE and Oracle to play together, we had a solution that appeared to work just fine&#8230; on the surface anyway. We decided to assess the solution we had and see how far down the road it would take us. This article describes our findings which are some inherent problems, some problems integrating with Oracle, some performance related, and some just because one size does not fit all.</p>
<p>
<strong>Note: </strong>I will not assume that any or all of these hurdles cannot be overcome with some level of effort.  On our project the effort to implement our own synchronization service far outweighed the cost of trying to work around these issues and in the end we still weren’t sure it would work.
</p>
<p>
<strong>System overview</strong><br />
<strong>Database Server:</strong> Oracle 10g<br />
<strong>App Server</strong>: Sync Web Services hosted in IIS<br />
<strong>Local Database:</strong> SQL CE<br />
<a href='http://dalldorf.com/home/wp-content/uploads/2008/10/architecture.png'><img src="http://dalldorf.com/home/wp-content/uploads/2008/10/architecture.png" alt="System Architecture" title="architecture" width="500" height="354" class="aligncenter size-full wp-image-252" /></a>
</p>
<p><strong>Synchronization characteristics </strong><br />
The database contains around 40-50 tables, some tables are download-only and others are unidirectional. The business rules ensure that only one user can edit a record at one time and the user must explicitly give up ownership before another user can edit the record. The data is what I would call document based, in that the user owns and works with a parent record and many detailed child records. Each parent record and it&#8217;s child records are self-contained. Because users cannot edit a record at the same time there is no need for merges (at least in theory).  Data is only logically deleted which simplifies the sync process in that there is no need to the tombstone table.</p>
<p><strong>How Sync Services works</strong><br />
<strong>Client-side change tracking</strong>: SQL CE has a hidden feature to track changes on rows; this feature is leveraged by Sync Services as long as the tables are created via Sync Services.  Each time a row is modified a flag is set on a hidden field for that row.</p>
<p><strong>Server-side change tracking: </strong>If you’re using SQL Server 2008, change tracking is integrated.  SQL Server 2008 change tracking resolves some of the issues that be identified in this article.  It’s change tracking is built into the SQL Server core engine and outperforms similar implementations using triggers.  Change tracking also occurs per transaction which is harder to accomplish with triggers.  If you’re unfortunate to be working without SQL Server 2008 (or Oracle in our case) you will need to create a couple columns for each table and implement a trigger for each table to be change tracked.  The trigger simply updates a client id and timestamp when the record is modified.</p>
<p>Synchronization occurs via the Client and Server Providers.  Each of these provide a set of methods which are used to perform sync operations.  No transport mechanism is provided out of the box, however it’s a trivial task to publish the server provider methods in a web service.</p>
<p>A sync operation consists of looping through each table on the client, checking for changes, packing up the changes and sending them to the ServerProvider which applies the changes.  This occurs for each table.</p>
<p>Tables can be synchronized at different frequencies by creating a separate service.  For example lookup tables may only require synchronization once per day.</p>
<p>Tables can be grouped.  All grouping does is ensure that a dependency tables are updated after their dependency.  Customer would need to be updated before Address (for example).</p>
<p><strong>The anchor: </strong>Each time a client requests data from the server, the server provides a timestamp which the client stores.  On subsequent download requests the client sends its anchor to the server.  The server queries the table in question to determine if there are any records with a timestamp greater than the supplied timestamp.</p>
<p><strong>Transaction isolation: </strong>On the server, serializable or snapshot isolation is required for both upload and download operations to ensure that data does not change during the sync.</p>
<p><strong>The first problem: no-change-sync takes 30 seconds</strong><br />
Sync Services must perform a separate check on each client and server table to check for changes.  Each table check is a separate call to the web service.  In our case it took 30 seconds to perform a no-change-sync.  Ideally a no-change-sync should be sub-second.  The client should “know” if it has any changes (just maintaining a single flag would suffice).  For server changes, the client should ask “Are there any changes for me?” with a simple yes/no response from the server.  Further on I will discuss why background sync is not feasible, but basically a 30 second no-change-sync means that the user is locked out of the system for 30 seconds when there aren’t even any changes.<br />
The sub-second goal is particularly important on our project because of background sync.  In most cases there will be no data changes and the number of hits on the server will be pretty high.  6000 users pinging the server every 30 seconds equates to 720,000 requests per hour (200 requests per second) on the server.  It has to be fast.</p>
<p><strong>No granularity on transactional units</strong><br />
A sync operation is an all-or-nothing deal.  Because Sync services has no knowledge of the relationships on your data (other than order which is determined by sync groups), the longer the client waits to sync, the more data there is to sync in a single operation.  The transactional unit in Sync Services is the entire mass of data that needs to be uploaded or downloaded.  There is no way to break the data up into smaller chunks without knowing how the data is related.  Of course you can sync your lookup tables separately and batch those into smaller chunks.  But when the data is all related there are no other options.  This inherent flaw is the cause of the next three problems.</p>
<p><strong>Long running transactions</strong><br />
Each time an upload operation starts a transaction is started on the server and the transaction is closed when the last table is checked and uploaded.  The longer you wait to sync, the more data you have to sync and the longer the transaction.  Long running transactions can cause serious problems.  The length of these transactions is also dependent on the user’s bandwidth and other conditions which leads to the next problem…</p>
<p><strong>Client controlled transactions</strong><br />
Just off the bat this seems like a bad idea.  What I mean by this is that it is the client that initiates the start of the Oracle (server) transaction and the client that determines the end of the transaction.  The length of the transaction can be determined by: their bandwidth, how much data they have that’s not synchronized, or if they just decide to suspend their laptop in the middle of a sync operation.  If user’s behave nicely and sync often, make sure they have adequate bandwidth and be sure to not terminate the application or suspend the laptop while a sync is in progress things may work just fine… but we all know this isn’t going to happen.</p>
<p><strong>Sync operations are non-recoverable</strong><br />
By non-recoverable, I mean that if an upload or download fails part-way through, the sync operation must completely restart (again for tables without relationships it’s easy to continue where you left off).  For data that has relationships to other data, ALL the data must be synchronized in a single operation and if there are any failures the sync operation must start from the beginning.  If the user has an unreliable connection (low QoS), this problem could compound.  Poor QoS means that the connection could be lost resulting in a hanging long running Oracle transaction.  The user will possibly continue to add more data, and by the time they try to sync again, they have even more data to synchronize which means even less chance of getting all their data through, possibly leaving a few more hanging transactions before a successful attempt is made.  These scenarios increase the network traffic and load on the servers and database.</p>
<p><strong>Data integrity issues under load conditions</strong><br />
The recommended solution for Database Servers (outside of SQL Server 2008) is using triggers with timestamps.  This solution is flawed right off the bat.  The best way to describe this is with the help of the help of the following example.  (Be sure to read the definition of anchor above before continuing). Assuming a parent table, “Project” and child table “Line Item.”  Client A is performing an upload which will last for 15 seconds.  Prior to upload a transaction is started.  After 7 seconds of uploading all the project records are uploaded and just then Client B performs a download sync.  Because the projects have not yet been committed the server returns no results (however, Client B’s anchor is updated to the 7 second mark).  At 15 seconds client A has completed its upload and Client B performs another download – the only data that’s downloaded are the line items.  Because Client B’s anchor was at 7 seconds only changes after the 7 second mark are retrieved.  Of course this will result in FK Violations on the client because the Projects that the Line Item references don’t exist.<br />
<a href='http://dalldorf.com/home/wp-content/uploads/2008/10/integrity.png'><img src="http://dalldorf.com/home/wp-content/uploads/2008/10/integrity.png" alt="Data Integrity" title="integrity" width="500" height="179" class="aligncenter size-full wp-image-253" /></a><br />
SQL Server 2008 solves this problem by (a) not using timestamps; and (b) by setting the version of the rows all to the same version which is based on the transaction.<br />
Impossible to support background sync<br />
Because the sync operations must scan ALL data and SQL CE does not support snapshot or serializable transaction isolation, it’s a lost cause even trying to attempt background sync.  Once a sync operations starts the user cannot modify the data.  If snapshot isolation were available, the sync operation could start a transaction and the data within the transaction wouldn’t change.</p>
]]></content:encoded>
			<wfw:commentRss>http://dalldorf.com/home/?feed=rss2&amp;p=250</wfw:commentRss>
		</item>
		<item>
		<title></title>
		<link>http://dalldorf.com/home/?p=249</link>
		<comments>http://dalldorf.com/home/?p=249#comments</comments>
		<pubDate>Fri, 25 Jul 2008 17:40:23 +0000</pubDate>
		<dc:creator>Troy</dc:creator>
		
		<category><![CDATA[CustomerComments]]></category>

		<guid isPermaLink="false">http://dalldorf.com/home/?p=249</guid>
		<description><![CDATA[Please allow me to tell you again what a tremendous asset you are to this project.  I told Jay again this morning that you are fabulous.  This document is great. &#8212; Project Manager, Magenic
]]></description>
			<content:encoded><![CDATA[<p>Please allow me to tell you again what a tremendous asset you are to this project.  I told Jay again this morning that you are fabulous.  This document is great. &#8212; Project Manager, Magenic</p>
]]></content:encoded>
			<wfw:commentRss>http://dalldorf.com/home/?feed=rss2&amp;p=249</wfw:commentRss>
		</item>
		<item>
		<title></title>
		<link>http://dalldorf.com/home/?p=246</link>
		<comments>http://dalldorf.com/home/?p=246#comments</comments>
		<pubDate>Thu, 24 Apr 2008 10:23:30 +0000</pubDate>
		<dc:creator>Troy</dc:creator>
		
		<category><![CDATA[CustomerComments]]></category>

		<guid isPermaLink="false">http://dalldorf.com/home/?p=246</guid>
		<description><![CDATA[Troy is the solution architect and mentor for the Marvin Windows and Doors OMS product.  OMS allows customers to configure, quote and purchase virtually any Marvin product.  His major accomplishment has been the implementation of a business rule engine that has allowed Marvin to encode a decade of product knowledge.  He also [...]]]></description>
			<content:encoded><![CDATA[<p>Troy is the solution architect and mentor for the Marvin Windows and Doors OMS product.  OMS allows customers to configure, quote and purchase virtually any Marvin product.  His major accomplishment has been the implementation of a business rule engine that has allowed Marvin to encode a decade of product knowledge.  He also implemented a presentation framework, extended CSLA, and provided extensive mentoring to a development team scattered across three locations.</p>
<p>However, technical skills are only a single part of a successful engagement.  The soft skills presented by Troy are extraordinary.  This is best demonstrated in an email from Lisa Carlston, e-business manager of the Marvin marketing department.</p>
<p>In the course of my career I have worked for and on-behalf of many organizations, and have had the opportunity to partner with several IT firms and internal departments. Too often, my experience has been a comedy of disconnected conversations with the business (aka me and people like me) struggling to communicate and ask good questions, and the developers delivering short, binary-like answers that rarely answer the “real” question or completely inform me of the choices or impact of my decisions. </p>
<p>And, then there is Troy.</p>
<p>Troy is a good listener and an active questioner who engages completely in the conversation. He really works to understand the strategy and the detailed business processes that drive his development work. He always seeks to understand the “why!”  Troy kindly bridges knowledge gaps, politely educates, and sheds light on what lays in the shadows of the decisions I make on the OMS project. I rely heavily on his insights and humble, guru-like guidance. So, not only is Troy’s contribution to the OMS project very great, but having Troy on our team empowers me (and others) to contribute at a higher level. </p>
<p>I appreciate the planning, technical and development work and long hours Troy has contributed to the progress of the OMS, as well as his can-do attitude and ability to persevere when the task looms so very large. Whatever recognition or reward may come as a result of this nomination, I hope Magenic will reward Troy with two scoops, because Troy is awesome.<br />
- Consultant of the Quarter, Q1 2008</p>
]]></content:encoded>
			<wfw:commentRss>http://dalldorf.com/home/?feed=rss2&amp;p=246</wfw:commentRss>
		</item>
		<item>
		<title></title>
		<link>http://dalldorf.com/home/?p=245</link>
		<comments>http://dalldorf.com/home/?p=245#comments</comments>
		<pubDate>Thu, 24 Apr 2008 10:22:07 +0000</pubDate>
		<dc:creator>Troy</dc:creator>
		
		<category><![CDATA[CustomerComments]]></category>

		<guid isPermaLink="false">http://dalldorf.com/home/?p=245</guid>
		<description><![CDATA[In the course of my career I have worked for and on-behalf of many organizations, and have had the opportunity to partner with several IT firms and internal departments. Too often, my experience has been a comedy of disconnected conversations with the business (aka me and people like me) struggling to communicate and ask good [...]]]></description>
			<content:encoded><![CDATA[<p>In the course of my career I have worked for and on-behalf of many organizations, and have had the opportunity to partner with several IT firms and internal departments. Too often, my experience has been a comedy of disconnected conversations with the business (aka me and people like me) struggling to communicate and ask good questions, and the developers delivering short, binary-like answers that rarely answer the “real” question or completely inform me of the choices or impact of my decisions. </p>
<p>And, then there is Troy.</p>
<p>Troy is a good listener and an active questioner who engages completely in the conversation. He really works to understand the strategy and the detailed business processes that drive his development work. He always seeks to understand the “why!”  Troy kindly bridges knowledge gaps, politely educates, and sheds light on what lays in the shadows of the decisions I make on the OMS project. I rely heavily on his insights and humble, guru-like guidance. So, not only is Troy’s contribution to the OMS project very great, but having Troy on our team empowers me (and others) to contribute at a higher level. </p>
<p>I appreciate the planning, technical and development work and long hours Troy has contributed to the progress of the OMS, as well as his can-do attitude and ability to persevere when the task looms so very large. Whatever recognition or reward may come as a result of this nomination, I hope Magenic will reward Troy with two scoops, because Troy is awesome.<br />
- E-Business Manager, Marvin Windows and Doors</p>
]]></content:encoded>
			<wfw:commentRss>http://dalldorf.com/home/?feed=rss2&amp;p=245</wfw:commentRss>
		</item>
	</channel>
</rss>
