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

<channel>
	<title>Nathan Jones</title>
	<atom:link href="http://www.nathanpjones.com/wp/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.nathanpjones.com/wp</link>
	<description>Programming, tips, reviews, etc.</description>
	<lastBuildDate>Wed, 10 Aug 2011 05:17:42 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Detect InputBox Cancel</title>
		<link>http://www.nathanpjones.com/wp/2011/08/detect-cancel-on-inputbox/</link>
		<comments>http://www.nathanpjones.com/wp/2011/08/detect-cancel-on-inputbox/#comments</comments>
		<pubDate>Wed, 10 Aug 2011 00:26:32 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Coding]]></category>

		<guid isPermaLink="false">http://www.nathanpjones.com/wp/?p=355</guid>
		<description><![CDATA[So we&#8217;ve all had the situation where we&#8217;d like to get an input from the user and we&#8217;re not too keen on creating a form, adding controls, and writing all the other underlying functionality. Many times, it&#8217;s just a lot easier to use an InputBox and validate the data afterward. Usually everything will go smoothly, [...]]]></description>
			<content:encoded><![CDATA[<p>So we&#8217;ve all had the situation where we&#8217;d like to get an input from the user and we&#8217;re not too keen on creating a form, adding controls, and writing all the other underlying functionality. Many times, it&#8217;s just a lot easier to use an InputBox and validate the data afterward.</p>
<p>Usually everything will go smoothly, that is until you want to accept an empty string as input. The InputBox returns an empty string when the user hits the Cancel button, so how can you tell the difference between Cancel and OK with a blank string?</p>
<p>Well here&#8217;s a neat trick. I tested this to work in VB.NET 2005, but I&#8217;m sure it&#8217;ll work in other versions.</p>
<pre class="brush: vb; collapse: false; title: ; wrap-lines: false; notranslate">
Dim ret As String
Dim dlgRes as DialogResult

ret = InputBox(&quot;Input a value:&quot;, &quot;Input&quot;)
If ret Is String.Empty Then
    dlgRes = DialogResult.Cancel
Else
    dlgRes = DialogResult.OK
End If
</pre>
<p>This works because Strings aren&#8217;t values, but are instead a reference to a character array in memory. As long as the string is unchanged, only the reference is passed around. InputBox will return String.Empty when you click the Cancel button, and you can check if the return value references the same object by using the <strong><em>Is</em></strong> keyword. If it matches, then Cancel was clicked.</p>
<p>Whenever you click OK, the InputBox returns an empty string, but never <em>the</em> empty string, String.Empty. Even if you try passing it String.Empty as the initial value, the return value is still a reference to a new, different empty string.</p>
<p>That&#8217;s it. Easy as pie!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.nathanpjones.com/wp/2011/08/detect-cancel-on-inputbox/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bulk Insert Using SqlClient.SqlBulkCopy</title>
		<link>http://www.nathanpjones.com/wp/2011/05/bulk-insert-using-sqlclient-sqlbulkcopy/</link>
		<comments>http://www.nathanpjones.com/wp/2011/05/bulk-insert-using-sqlclient-sqlbulkcopy/#comments</comments>
		<pubDate>Sat, 21 May 2011 15:58:52 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.nathanpjones.com/wp/?p=317</guid>
		<description><![CDATA[Inspired by: Steve Novoselac&#8217;s Post on SqlBulkCopy I had a lot of data that I wanted to dump from a wide range of flat text file databases. I already had classes that stored the schema for the tables and some of the formats were weird (i.e. custom date stored as a single), and rather than [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Inspired by:</strong> <a href="http://blog.stevienova.com/2008/01/16/net-fastest-way-to-load-text-file-to-sql-sqlbulkcopy/">Steve Novoselac&#8217;s Post on SqlBulkCopy</a></p>
<p>I had a lot of data that I wanted to dump from a wide range of flat text file databases. I already had classes that stored the schema for the tables and some of the formats were weird (i.e. custom date stored as a single), and rather than setting up a bulk insert in SQL Server, I decided I&#8217;d just import directly using my classes. They&#8217;re optimized to load, cache, and interpret the data but I just needed a way to get it quickly over to the SQL table.</p>
<p>If you have a similar situation or your program is generating a lot of data (over a couple thousand rows) that needs to be dumped into a table, <a href="http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy(v=VS.80).aspx">SqlClient.SqlBulkCopy</a> is the way to go.</p>
<h2>Slower Methods</h2>
<p>Before I used bulk insert, I was using a SqlCommand with parameters (e.g. &#8220;<code>INSERT INTO MyTable VALUES (@KeyValue, @Value1, @Value2)</code>&#8220;). From what I understand, SQL Server compiles these and so long as the command text doesn&#8217;t change (not even character casing), it doesn&#8217;t have to compile it again between calls.</p>
<p>While this method was definitely faster than composing an INSERT for each row, I was averaging only a couple or few hundred records a second and I had hundreds of thousands of records.</p>
<p>I got a little performance boost when I waited until the end to add my primary key index, but of course that takes some time depending on the number of rows you have.</p>
<p>With using SqlBulkCopy, my performance jumped tenfold to a couple or few thousand a second. At first I tried caching all the data in a DataTable (about 630,000 records), and the bulk insert at the end took about 25 to 35 seconds. However, the DataTable just ate through memory, taking over a GB when everything was loaded. It would also pause frequently near the end when allocating more memory and causing use of the swap file.</p>
<p>Here&#8217;s the code for after the DataTable (<code>dt</code>) has been filled. Also, <code>c</code> represents an open connection, but you can also use a connection string.</p>
<pre class="brush: vb; collapse: false; title: ; wrap-lines: false; notranslate">
Dim bc As SqlBulkCopy
bc = New SqlBulkCopy(c, SqlBulkCopyOptions.TableLock, Nothing)
bc.DestinationTableName = String.Format(&quot;[{0}].[dbo].[{1}]&quot;, database, tableName)
bc.BatchSize = 1000
bc.BulkCopyTimeout = 300
bc.WriteToServer(dt)
bc.Close()
</pre>
<ul>
<li><strong>BatchSize </strong>- Can be the full number of rows, but it seems like performance is a little better when you give the server a chance to process the records as they come in.</li>
<li><strong>BulkCopyTimeout </strong>- The default is 30 seconds. If you have a lot of records you&#8217;ll blow past this so make sure to set it higher.</li>
<li><strong><code>dt.Dispose(): GC.Collect()</code></strong> &#8211; You should consider calling this once you&#8217;re done to free up some memory from your DataTable.</li>
</ul>
<h2>Fastest</h2>
<p>My final, fastest solution was to create a class that implemented the <strong><a href="http://msdn.microsoft.com/en-us/library/system.data.idatareader(v=VS.80).aspx">IDataReader</a></strong> interface and that consumed my data. It would load my data from disk as requested by SqlBulkCopy which was then sent to the server. Memory usage was minimal, maybe from 50 to 70MB according to Task Manager and performance was even better since there was no memory allocation hiccups.</p>
<pre class="brush: vb; collapse: false; title: ; wrap-lines: false; notranslate">
Dim bc As SqlBulkCopy
bc = New SqlBulkCopy(c, SqlBulkCopyOptions.TableLock, Nothing)
bc.DestinationTableName = String.Format(&quot;[{0}].[dbo].[{1}]&quot;, database, tableName)
bc.BatchSize = 1000
bc.BulkCopyTimeout = 3000
bc.WriteToServer(New RecBaseDataReader(rec, recsToExport))
bc.Close()
</pre>
<ul>
<li><strong>RecBaseDataReader</strong> is my custom class. I pass it <code>rec</code> which is used to load data and <code>recsToExport</code> which is a list of records that it can iterate through.</li>
<li><strong>BulkCopyTimeout </strong>- Note that it&#8217;s much higher than when we pass in a DataTable because of the extra time that we take loading the data in the IDataReader.</li>
</ul>
<p>You can set up your IDataReader class any way that works best for you. The following routines are used by SqlBulkCopy and must be implemented. You can just put a <code>Stop</code> in the rest of the routines just in case anyone tries to use them.</p>
<ul>
<li><strong>System.Data.IDataRecord.FieldCount</strong> &#8211; Should return the number of fields in your record.</li>
<li><strong>System.Data.IDataRecord.GetOrdinal</strong> &#8211; Should return the ordinal for the given field.</li>
<li><strong>System.Data.IDataReader.Read</strong> &#8211; Should advance the read cursor to the next record and load it. Make sure it&#8217;s set up so the first call of Read will return the first record.</li>
<li><strong>System.Data.IDataRecord.GetValue</strong> &#8211; Should return the value of the column specified by the given ordinal.</li>
</ul>
<p>Here&#8217;s a skeleton implementation: <a href='http://www.nathanpjones.com/wp/wp-content/uploads/2011/07/MyCustomDataReader.zip'>MyCustomDataReader.zip</a></p>
<h2>Notes</h2>
<ul>
<li>Destination table name is kind of finicky. When I used just the table name, it threw an error so I just went ahead and used the full table name.</li>
<li>If you have computed columns on your source or destination, you&#8217;ll need to set up <a href="http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopycolumnmapping(v=VS.80).aspx">column mappings</a> to specify which columns should actually be inserted. A straightforward <code>.ColumnMappings.Add(col.ColumnName, col.ColumnName)</code> worked for me. Others have suggested that you can use an <a href="http://stackoverflow.com/questions/438587/sqlbulkcopy-not-working/438606#438606">intermediate table</a> which provides a little protection if the bulk insert fails for some reason.</li>
<li>For the method where I loaded all the data into a DataTable, I set up columns and column types, but didn&#8217;t set up MaxLength for varchar columns. This caused an error so make sure these are set up correctly. If you&#8217;re using a strongly-typed DataTable generated from the destination table you shouldn&#8217;t have to worry about this.</li>
<li>Check out <a href="http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopyoptions(v=VS.80).aspx">SqlBulkCopyOptions</a> (specified in the constructor) for more settings on things like how identity columns are handled, how null values are copied to the new table, etc.</li>
<li>Apparently <a href="http://www.adathedev.co.uk/2010/04/sqlbulkcopy-columnmappings-mismatch.html">column names are case-sensitive</a> in SqlBulkCopy. I didn&#8217;t encounter any issues with this because I was creating the table at the same time I was setting up column mappings so the casing matched anyways.</li>
<li>Some are saying there&#8217;s a bug in .NET 2.0 where a quote character in the column name will prevent you from using SqlBulkCopy so heads up.</li>
</ul>
<p><strong>2011-07-27 Edit:</strong> Uploaded skeleton class as a zip file to avoid 404 error because of &#8220;.vb&#8221; extension.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.nathanpjones.com/wp/2011/05/bulk-insert-using-sqlclient-sqlbulkcopy/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Descriptions for Enum</title>
		<link>http://www.nathanpjones.com/wp/2011/04/descriptions-for-enum/</link>
		<comments>http://www.nathanpjones.com/wp/2011/04/descriptions-for-enum/#comments</comments>
		<pubDate>Thu, 28 Apr 2011 15:30:32 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.nathanpjones.com/wp/?p=315</guid>
		<description><![CDATA[Awhile ago I created a method to simulate a Enum but based on a string value rather than integral numeric (published here on CodeProject). It also allows for adding and extracting a description. However, if you&#8217;re just looking for a lightweight way to add a description to your enums, this blog post posits a simple, [...]]]></description>
			<content:encoded><![CDATA[<p>Awhile ago I created a method to simulate a Enum but based on a string value rather than integral numeric (published <a href="http://www.codeproject.com/KB/vb/StringEnum.aspx">here</a> on <a href="http://www.codeproject.com/">CodeProject</a>). It also allows for adding and extracting a description.</p>
<p>However, if you&#8217;re just looking for a lightweight way to add a description to your enums, <a href="http://msmvps.com/blogs/deborahk/archive/2009/07/10/enum-binding-to-the-description-attribute.aspx">this blog post</a> posits a simple, elegant way to add and use a description. It requires .NET 3.5 or higher since it uses extension methods.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.nathanpjones.com/wp/2011/04/descriptions-for-enum/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Preventing ClickOnce from Publishing a Debug Configuration</title>
		<link>http://www.nathanpjones.com/wp/2010/05/preventing-clickonce-publishing-a-debug-configuration/</link>
		<comments>http://www.nathanpjones.com/wp/2010/05/preventing-clickonce-publishing-a-debug-configuration/#comments</comments>
		<pubDate>Sat, 29 May 2010 16:45:02 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[.net]]></category>
		<category><![CDATA[ClickOnce]]></category>
		<category><![CDATA[publish]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://www.nathanpjones.com/wp/?p=274</guid>
		<description><![CDATA[You&#8217;ve all had it happen. You just put the finishing touches on your project and you hit the Publish button. The files are automatically copied to the file server and users start get the updates right away. You double-check the publish and then you realize that you published the DEBUG version with all your program [...]]]></description>
			<content:encoded><![CDATA[<p>You&#8217;ve all had it happen. You just put the finishing touches on your project and you hit the Publish button. The files are automatically copied to the file server and users start get the updates right away. You double-check the publish and then you realize that you published the DEBUG version with all your program stops, disabled error checking, and wide open access to all program features!</p>
<p>Custom MSBuild targets to the rescue! Just add the following to your project file and it will prevent a publish when the DEBUG constant is defined. Place it at the bottom of your project file right before the <code>&lt;/Project&gt;</code> tag. (For an example of editing your project file, see my post on <a title="Obfuscating a ClickOnce Publish" href="http://www.nathanpjones.com/wp/?p=172" target="_blank">Obfuscating  a ClickOnce Publish</a>.)</p>
<pre class="brush: xml; gutter: false; title: ; notranslate">
  &lt;!-- The following makes sure we don't try to publish a configuration that defines the DEBUG constant --&gt;
  &lt;Target Name=&quot;BeforePublish&quot;&gt;
    &lt;Error Condition=&quot;'$(DefineDebug)'=='true'&quot;
           Text=&quot;You attempted to publish a configuration that defines the DEBUG constant!&quot; /&gt;
  &lt;/Target&gt;
</pre>
<p>By the way, the DEBUG constant is the constant that you use in your code as a compiler constant, for example <code>#If DEBUG Then</code>. It can be found in the &#8216;Compile&#8217; tab under &#8216;My Project&#8217; by clicking &#8216;Advanced Compile Options&#8230;&#8217;:</p>
<div id="attachment_282" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.nathanpjones.com/wp/wp-content/uploads/2010/05/DefineDEBUGConstant.png"><img class="size-medium wp-image-282 " title="Define DEBUG Constant" src="http://www.nathanpjones.com/wp/wp-content/uploads/2010/05/DefineDEBUGConstant-300x232.png" alt="" width="300" height="232" /></a><p class="wp-caption-text">Define DEBUG Constant</p></div>
<p><strong>Edit:</strong> It looks like some people have had issues with the way I got things working. I was using a VB.Net forms application in VS2005 (and I think I tested in 2008 as well). The key is to find which constant works best for your situation. Drew Mcpherson says that <code>DebugSymbols</code> worked for him rather than <code>DefineDebug</code>.</p>
<p>If you want even more control, another way of choosing a compiler constant is to define your own. You&#8217;ll notice that below the &#8220;Define DEBUG Constant&#8221; box there is a textbox for defining custom constants. If, for example, you have three configurations, such as <code>Debug</code>, <code>Release</code>, and <code>Publish</code>, you could define a constant on the <code>Publish</code> configuration to prevent any other from allowing a publish.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.nathanpjones.com/wp/2010/05/preventing-clickonce-publishing-a-debug-configuration/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>MacBook Pro Right-Click Drag, Fxx Keys, etc.</title>
		<link>http://www.nathanpjones.com/wp/2010/05/macbook-pro-keyboard-mouse/</link>
		<comments>http://www.nathanpjones.com/wp/2010/05/macbook-pro-keyboard-mouse/#comments</comments>
		<pubDate>Wed, 05 May 2010 03:13:47 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[MacBook Pro]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://www.nathanpjones.com/wp/?p=245</guid>
		<description><![CDATA[The MBP comes with a beautiful backlit keyboard and a multitouch trackpad that is also a big button. Both are very pleasant and easy to use&#8211;unless you run Windows or run into an application that require that you press the Home key. Then you&#8217;re hunting newsgroups for the magical key combos. Here are a couple [...]]]></description>
			<content:encoded><![CDATA[<p>The MBP comes with a beautiful backlit keyboard and a multitouch trackpad that is also a big button. Both are very pleasant and easy to use&#8211;unless you run Windows or run into an application that require that you press the Home key. Then you&#8217;re hunting newsgroups for the magical key combos.</p>
<p>Here are a couple of great links that I used to figure out the mysteries of the <em>fn</em> key:</p>
<ul>
<li><a href="http://systemstuff.wordpress.com/2009/06/08/macbook-pro-keyboard-mapping-for-windows/" target="_blank">MacBook Pro Keyboard Mapping</a> (great summary table at top of page)</li>
<li><a href="http://support.apple.com/kb/HT1220" target="_blank">Boot Camp: MacBook Pro built-in keyboard mapping in Windows</a></li>
</ul>
<p><strong><em>Right-Click Drag</em></strong></p>
<p>The tough thing is to figure out how to <em>right-click drag.</em> You can usually find some other way of accomplishing a right-click drag task, but sometimes you just can&#8217;t. If I want to share one folder to another in SourceSafe, there&#8217;s just no other practicable way.</p>
<p>When I need to, I activate System Preferences-&gt;Trackpad-&gt;Secondary Click and choose &#8216;Bottom-Right Corner&#8217;. Then you can simply click the big button in that corner with your right index finger and use your left index finger to move the item around. When you&#8217;re ready to drop, let go with your right finger. I always turn this setting off when I&#8217;m done because I end up right-clicking when I don&#8217;t want to.</p>
<p><strong><em>Funtion Keys</em></strong></p>
<p>The function keys are relatively useless on a MacBook Pro since most of the commands can be accomplished more easily by trackpad gestures. You usually use the alternative functions of the keys like volume and brightness controls.</p>
<p>The opposite it true on a PC, especially for thing like search where you keep hitting F3 or debugging in Visual Studio where you&#8217;re hitting F9 through F11 over and over. It gets to be a real pain to keep hitting that <em>Fn</em> key.</p>
<p>Fortunately, there&#8217;s an easy way to reverse the functionality of the <em>Fn</em> key so that the function keys are fired without pressing anything else and the volume, brightness, etc. controls are the ones enabled by pressing <em>Fn</em>.</p>
<p>Just go to System Preferences-&gt;Keyboard and check the box called <em>Use all F1, F2, etc. keys as standard function keys</em>. Here&#8217;s an example of the setting turned on.</p>
<p><a href="http://www.nathanpjones.com/wp/wp-content/uploads/2010/05/Screen-shot-2010-05-10-at-11.35.33-AM.png"><img class="size-medium wp-image-267 alignnone" title="Keyboard Preferences" src="http://www.nathanpjones.com/wp/wp-content/uploads/2010/05/Screen-shot-2010-05-10-at-11.35.33-AM-300x271.png" alt="" width="300" height="271" /></a></p>
<p>When you&#8217;re done, then go ahead and uncheck the box. Ideally, you could create a script to quickly set and unset the setting for daily usage, but it&#8217;s really not too much to remember it.</p>
<p><strong><em>Insert Key</em></strong></p>
<p>Sometimes, when running Windows, you&#8217;ll need to use the Insert key. None of the keyboard mappings I&#8217;ve seen have indicated what to use except the Insert key on a full keyboard (duh!).</p>
<p>On a MBP, it&#8217;s simply:  <em>Fn+Enter</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.nathanpjones.com/wp/2010/05/macbook-pro-keyboard-mouse/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Obfuscating a ClickOnce Publish</title>
		<link>http://www.nathanpjones.com/wp/2010/04/obfuscating-a-clickonce-publish/</link>
		<comments>http://www.nathanpjones.com/wp/2010/04/obfuscating-a-clickonce-publish/#comments</comments>
		<pubDate>Wed, 28 Apr 2010 03:58:09 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[.net]]></category>
		<category><![CDATA[.NET Reactor]]></category>
		<category><![CDATA[.Net Reflector]]></category>
		<category><![CDATA[ClickOnce]]></category>
		<category><![CDATA[Dotfuscator]]></category>
		<category><![CDATA[obfuscate]]></category>
		<category><![CDATA[publish]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://www.nathanpjones.com/wp/?p=172</guid>
		<description><![CDATA[I needed to create a ClickOnce publish of an obfuscated exe for a customer since he was concerned about theft of his intellectual property. I added in several security features, but they were worthless if I couldn&#8217;t harden the executable against decompilers like .Net Reflector. If you don&#8217;t believe me, try running .Net Reflector on [...]]]></description>
			<content:encoded><![CDATA[<p>I needed to create a ClickOnce publish of an obfuscated exe for a customer since he was concerned about theft of his intellectual property. I added in several security features, but they were worthless if I couldn&#8217;t harden the executable against decompilers like <a href="http://reflector.red-gate.com/download.aspx?TreatAsUpdate=1">.Net Reflector</a>. If you don&#8217;t believe me, try running .Net Reflector on your code. You&#8217;ll be shocked as to how much meaningful information is retained in the output. Not only is your code exposed, but so are all the string literals, member names, and resources.</p>
<p>So I shopped around for an obfuscating (et al.) program. I looked at the industry-standard, <a href="http://www.preemptive.com/products/dotfuscator/overview">Dotfuscator</a>, since a free version even ships with Visual Studio. But the free version is worthless since it only renames <strong>public</strong> members (again, don&#8217;t take my word and just peek into it yourself). The commercial version of Dotfuscator very easily supports obfuscating a ClickOnce publish (see this <a href="http://www.youtube.com/watch?v=vR81WFXiBA4">handy demo</a>) and additional hardening techniques, but the price is $4950 or $5940 depending on which edition you choose. They have a special deal for companies less than 40 employees, but the price is still $2500. I figured it was worth some shoe leather to find a less expensive solution.</p>
<p>After some hunting around and having mixed results with various other products, I found a program called <a href="http://www.eziriz.com/">.Net Reactor</a>. I like it because it&#8217;s straightforward, fully-featured, has comprehensive command-line support, and is very reasonably priced at $179.</p>
<p>Now that I had an obfuscation tool, I had to figure out how to make it work with ClickOnce. I was initially hopeful seeing the post-build command-line property in the project properties. However, if you simply add the obfuscation to the post-build event, the published exe is not obfuscated. It turns out your exe is compiled into an intermediate directory (e.g. &#8220;obj\Release&#8221;) and then copied to your build output path and/or used to create a ClickOnce publish. The post-build event is too late to affect the publish.</p>
<p>To hook in before the publish, you have to turn to MSBuild, the compile tool used in the background by Visual Studio to consume and compile a .Net project. It turns your project file (.vbproj or .csproj) are actually MSBuild files that you can edit directly for more features than are supported through the IDE.</p>
<p>(Forgive me if I&#8217;ve violated MSBuild best-practices in my tasks and properties, but there just isn&#8217;t a lot of help out there and the MSBuild syntax seems pretty sloppy to begin with.)</p>
<h3>Steps</h3>
<ol>
<li>Download this file and place it in the same directory as the project file of the project you want to protect.<br />
<div class="wp-caption aligncenter" style="width: 150px"><a title="Obfuscation MSBuild File" href="http://www.nathanpjones.com/wp/wp-content/uploads/2010/06/Obfuscation.zip" target="_blank"><img title="Download" src="http://www.nathanpjones.com/wp/wp-includes/images/crystal/text.png" alt="Download" width="46" height="60" align="Center" /></a><p class="wp-caption-text">Obfuscation.targets</p></div><br />
This file is analogous to the .Net provided .targets files that are also included with your project by default. This file will override or add to tasks that are handled by those files.<br />
<em>Note:</em> You will have to modify this file to suit your particular situation. Search the targets file for MergeAssembliesList (to use a separator other than &#8220;/&#8221;), MergeAssembliesArg, ObfuscatorName, ObfuscatorLocation, and ObfuscatorLocation. Also, for .Net Reactor, the merging application is built into the obfuscator. If you are using a separate merging app, you&#8217;ll have to add a call to that program. You should be able to figure it out from how this targets file is formatted.</li>
<li>Right-click on the project that you will be publishing and click &#8216;Unload Project&#8217;. (If your project is source-controlled, you may get a warning that says you still have files checked out, but you can just click &#8216;Continue&#8217; without causing any problems.)</li>
<li>Right-click on the project again and click &#8216;Edit MyApp.vbproj&#8217;.</li>
<li>Paste the non-highlighted XML into your project file between the highlighted lines. The &#8216;.targets&#8217; file may have a different file name if you&#8217;re using C# but it will still end in &#8216;.targets&#8217;.
<pre class="brush: xml; gutter: false; highlight: [1,18]; title: ; notranslate">
  &lt;Import Project=&quot;$(MSBuildBinPath)\Microsoft.VisualBasic.targets&quot; /&gt;
  &lt;!-- Use the following settings to control how and if the output is obfuscated. --&gt;
  &lt;Target Name=&quot;BeforeBuild&quot; Condition=&quot; '$(Configuration)|$(Platform)' == 'Release|AnyCPU' &quot;&gt;
    &lt;CreateProperty Value=&quot;true&quot;&gt;
      &lt;Output TaskParameter=&quot;Value&quot; PropertyName=&quot;Obfuscate&quot; /&gt;
    &lt;/CreateProperty&gt;
    &lt;CreateProperty Value=&quot;&quot;&gt;
      &lt;Output TaskParameter=&quot;Value&quot; PropertyName=&quot;ObfuscatorOptionsOverride&quot; /&gt;
    &lt;/CreateProperty&gt;
    &lt;CreateProperty Value=&quot;true&quot;&gt;
      &lt;Output TaskParameter=&quot;Value&quot; PropertyName=&quot;ShouldMergeAssemblies&quot; /&gt;
    &lt;/CreateProperty&gt;
    &lt;CreateProperty Value=&quot;&quot;&gt;
      &lt;Output TaskParameter=&quot;Value&quot; PropertyName=&quot;MergeAssembliesArgOverride&quot; /&gt;
    &lt;/CreateProperty&gt;
  &lt;/Target&gt;
  &lt;Import Project=&quot;$(MSBuildProjectDirectory)\Obfuscation.targets&quot; /&gt;
&lt;/Project&gt;
</pre>
<p>You can change the &#8216;true&#8217; or &#8216;false&#8217; values to control whether or not the obfuscation is done at all and whether or not assemblies are merged when obfuscating. You can also change the configuration from &#8216;Release&#8217; to some other configuration that you have defined.<br />
You can use the Overrides to change the arguments to the obfuscator or merging program. This is helpful if your program can&#8217;t be obfuscated by your chosen default obfuscation settings or you want to merge only certain assemblies.<br />
<em>Note:</em> If you don&#8217;t intend to merge assemblies, each dll or exe that is included with your project must be separately obfuscated (unless of course it&#8217;s a 3rd party include). When obfuscating these includes, make sure <strong>NOT </strong>to obfuscate their public members or your main assembly won&#8217;t be able to use them.</li>
<li>After saving your changes, right-click on the project and click &#8216;Reload Project&#8217;. You may get a security warning, but just choose to &#8216;Load project normally&#8217;.</li>
<li>If you&#8217;re intending to Publish and merge assemblies, there&#8217;s one more step required. You must exclude files that are merged into the main assembly and would be normally output with the publish. Otherwise, these unprotected files, though unused, will be available for the world to decompile. (<em>Note:</em> this doesn&#8217;t apply if you&#8217;re not merging.)<br />
Go to the &#8216;Publish&#8217; tab in &#8216;My Project&#8217; and click on &#8216;Application Files&#8217;. For any dll or exe file listed as &#8216;Include&#8217; or &#8216;Include (auto)&#8217;, change it to &#8216;Exclude&#8217;. If you have 3rd party files or files listed as &#8216;Prerequisite&#8217;, merging may not be an option and you may have to resort to individually protecting your includes by obfuscation and security checks to ensure usage only by your programs.</li>
<li>Change your configuration to &#8216;Release&#8217; and build or publish. <em>Note:</em> For whatever reason, the IDE sometimes forgets what solution configuration was last selected, so always check that you have the right configuration selected if the obfuscator doesn&#8217;t run.</li>
</ol>
<h3>Notes</h3>
<ul>
<li>When you&#8217;re working in XML, don&#8217;t forget to properly escape special characters. For example, a &#8216;&lt;&#8217; should be escaped as <code>&amp;lt;</code>. Also, you must escape quotation marks inside a string literal (using <code>&amp;quot;</code>) but you don&#8217;t have to if you&#8217;re only inside a tag, like when specifying a property value. Here&#8217;s a great <a href="http://stackoverflow.com/questions/1091945/xml-escape-characters">thread on XML escape characters</a>.</li>
<li>To make sure Messages are output, in VS IDE go to Tools-&gt;Options-&gt;Projects &amp; Solutions-&gt;Build &amp; Run and change Output Verbosity from &#8216;Minimal&#8217; to &#8216;Normal&#8217;. It helps a lot when debugging custom MSBuild configs.</li>
<li>MSBuild will halt if a program&#8217;s exit code is not &#8217;0&#8242;. If your obfuscator of choice uses a different exit code or always returns something non-zero, then make sure to trap it in the way I did above and throw an error when appropriate. Actually, the error trapping I did was redundant (I think), but it&#8217;s a handy example.</li>
<li>If you&#8217;re using another obfuscator, it should ideally conform to the MSBuild convention of returning 0 (zero) if successful and a non-zero number on an error. If your obfuscator works differently, for example, always returning 1 on success, or if you just want to ignore certain errors, you may use the following convention to trap and interpret exit codes. This example raises an error for all return values other than 0, effectively duplicating the standard MSBuild convention.
<pre class="brush: xml; gutter: false; title: ; notranslate">
&lt;Exec Command=&quot;$(ObfuscatorLocation) -file &amp;quot;$(SourceExe)&amp;quot; -targetfile &amp;quot;$(SecureExe)&amp;quot; $(ObfuscatorOptions) &quot;&gt;
  &lt;Output TaskParameter=&quot;ExitCode&quot; PropertyName=&quot;ObfuscatorErrorCode&quot; /&gt;
&lt;/Exec&gt;
&lt;Error Condition=&quot;'$(ObfuscatorErrorCode)' != '0'&quot;
       Text=&quot;Error while executing '$(ObfuscatorName)'. Returned exit code of '$(ObfuscatorErrorCode)'.&quot; /&gt;
</pre>
</li>
</ul>
<p><strong>2010-05-30 Updated: </strong>Refined include method and added support for merging assemblies. Also, included instructions for trapping custom errors.<br />
<strong>2011-01-03 Updated: </strong>Fixed problem with handling references to COM assemblies (or possibly other reference types) that would generate the following error:</p>
<ul><code>C:\Dev\MyApplication\Obfuscation.targets(27,5): error MSB4096: The item "obj\Release\Interop.SomeCOMClass.dll" in item list "ReferencePath" does not define a value for metadata "ResolvedFrom".  In order to use this metadata, either qualify it by specifying %(ReferencePath.ResolvedFrom), or ensure that all items in this list define a value for this metadata.</code></ul>
<p>Also added support for files that are included as prerequisites that would generate the following custom error:</p>
<ul><code>Assemblies set to merge during obfuscation but ClickOnce deployment still lists output dependencies!</code></ul>
<p><strong>2011-06-05 Updated: </strong> Updated xml for project file to include all the override arguments options. Also added notes about how the Obfuscation.targets file may need to be modified.</p>
<h3>References</h3>
<ul>
<li><a href="http://guysmithferrier.com/downloads/msbuild.pdf" target="_blank">Great Intro to MSBuild</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/ms366724.aspx">Built-in MSBuild Targets</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/bb629394.aspx">Common MSBuild Project Properties</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/x8zx72cd.aspx">MSBuild Exec Task</a></li>
<li><a href="http://blogs.msdn.com/aaronhallberg/archive/2007/07/16/msbuild-property-evaluation.aspx">MSBuild Property Scoping</a></li>
<li><a href="http://www.xenocode.com/Support/Kb/afmmain.aspx?faqid=8">Using Postbuild with ClickOnce</a> (what I started with in created my MSBuild configuration)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.nathanpjones.com/wp/2010/04/obfuscating-a-clickonce-publish/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Excellent Windows API Tool</title>
		<link>http://www.nathanpjones.com/wp/2010/04/excellent-windows-api-tool/</link>
		<comments>http://www.nathanpjones.com/wp/2010/04/excellent-windows-api-tool/#comments</comments>
		<pubDate>Sat, 10 Apr 2010 00:44:59 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[.net]]></category>

		<guid isPermaLink="false">http://www.nathanpjones.com/wp/?p=159</guid>
		<description><![CDATA[I stumbled across this add-in which automates the insertion of various Windows API declarations. If you&#8217;re like me, you track down solutions to your problem on the Internet, but sometimes it uses an API declaration in C# or VB6. Even worse, sometimes someone will use a non-standard or just plain difficult declaration style, for example: [...]]]></description>
			<content:encoded><![CDATA[<p>I stumbled across this add-in which automates the insertion of various Windows API declarations. If you&#8217;re like me, you track down solutions to your problem on the Internet, but sometimes it uses an API declaration in C# or VB6. Even worse, sometimes someone will use a non-standard or just plain difficult declaration style, for example:</p>
<pre class="brush: vb; light: true; title: ; notranslate">ByVal var As IntPtr</pre>
<p>and marshalling a string rather than</p>
<pre class="brush: vb; light: true; title: ; notranslate">ByVal bytes() As Byte</pre>
<p>Anyhow, the tool is here: <a href="http://www.pinvoke.net/index.aspx">http://www.pinvoke.net/index.aspx</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.nathanpjones.com/wp/2010/04/excellent-windows-api-tool/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>When Compiler Directives Aren&#8217;t Enough</title>
		<link>http://www.nathanpjones.com/wp/2010/02/when-compiler-directives-arent-enough/</link>
		<comments>http://www.nathanpjones.com/wp/2010/02/when-compiler-directives-arent-enough/#comments</comments>
		<pubDate>Fri, 05 Feb 2010 05:09:13 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[.net]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[vb]]></category>

		<guid isPermaLink="false">http://www.nathanpjones.com/wp/?p=132</guid>
		<description><![CDATA[If you&#8217;ve programmed for any length of time in .NET, you&#8217;re probably familiar with the DEBUG compiler constant that you can use to designate code to compile and run depending on your build configuration (e.g. Debug or Release). But very often you don&#8217;t care about the configuration you&#8217;re running&#8211;what you do care about is distinguishing [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve programmed for any length of time in .NET, you&#8217;re probably familiar with the DEBUG compiler constant that you can use to designate code to compile and run depending on your build configuration (e.g. Debug or Release).</p>
<p>But very often you don&#8217;t care about the configuration you&#8217;re running&#8211;what you do care about is distinguishing between you developing the software and the end user using it. In other words, you care whether you&#8217;re running in the IDE or not.</p>
<p>An example of when this would matter is if you accidentally publish in Debug mode, then the end user will get all your debug outputs, extra buttons, etc. You can mitigate this risk if your code is protected by a check for the presence of the debugger instead. This call is:</p>
<pre class="brush: vb; light: true; title: ; notranslate">System.Diagnostics.Debugger.IsAttached</pre>
<p>Now, the end-user can always load up your EXE in Visual Studio and attach a debugger instance, so don&#8217;t assume this call will protect anything super-sensitive in your program. But your code is very susceptible to a decompiler anyways, so always use compiler directives if you don&#8217;t want certain sections of your code to make it to the outside world.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.nathanpjones.com/wp/2010/02/when-compiler-directives-arent-enough/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Converting VB.NET 2003 WinForms to 2005/2008 Partial Classes</title>
		<link>http://www.nathanpjones.com/wp/2010/02/converting-vb-net-2003-winforms-to-20052008-partial-classes/</link>
		<comments>http://www.nathanpjones.com/wp/2010/02/converting-vb-net-2003-winforms-to-20052008-partial-classes/#comments</comments>
		<pubDate>Fri, 05 Feb 2010 04:53:14 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[.net]]></category>
		<category><![CDATA[vb]]></category>

		<guid isPermaLink="false">http://www.nathanpjones.com/wp/?p=120</guid>
		<description><![CDATA[Ever been stuck working in VB.NET 2005 or 2008 with a project created in VB.NET 2003? Aside from language differences, you&#8217;re stuck with forms that except for resources are in one file. Not only is this ugly, but it makes the IDE slower, since it redraws when it detects any changes to a file that [...]]]></description>
			<content:encoded><![CDATA[<p>Ever been stuck working in VB.NET 2005 or 2008 with a project created in VB.NET 2003? Aside from language differences, you&#8217;re stuck with forms that except for resources are in one file. Not only is this ugly, but it makes the IDE slower, since it redraws when it detects any changes to a file that has designer info.</p>
<p>So I started hunting about for a quick solution to convert this over (why isn&#8217;t this automatic MS?) and found a great solution by Duncan Smart, on his blog <a title="Converting to Partial Classes" href="http://blog.dotsmart.net/2008/05/20/converting-visual-studio-2003-winforms-to-visual-studio-20052008-partial-classes/" target="_blank">here</a>. I&#8217;ve modified it to work with VB and tested and ran it in VB 2008. Duncan&#8217;s didn&#8217;t seem to work right on VB code when iterating through the class members, but there does seem to be little predictability when it comes to using the macro system. I also added some extra error checking and a restore-on-error feature.</p>
<p>Here&#8217;s the code for the macro. Instructions for usage are in the comments on the top. Sorry for the sometimes sloppy style&#8211;I wrote it quick and dirty.</p>
<pre class="brush: vb; collapse: true; light: false; title: ; toolbar: true; wrap-lines: false; notranslate">Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports System.Diagnostics

Public Module ExtractWinFormsDesignerFile

    ' -------------------------------------------------------------------------
    ' Extract WinForms Designer File Visual Studio 2005/2008 Macro
    ' -------------------------------------------------------------------------
    ' Extracts the InitializeComponent() and Dispose() methods and control
    ' field delarations from a .NET 1.x VS 2003 project into a VS 2005/8
    ' style .NET 2.0 partial class in a *.Designer.VB file. (This tested to work
    ' with VB only.)
    '
    ' To use:
    '  * Copy the methods below into a Visual Studio Macro Module (use
    '    ALT+F11 to show the Macro editor)
    '  * Select a Windows Form in the Solution Explorer
    '  * Run the macro by showing the Macro Explorer (ALT+F8) and double
    '    clicking the 'ExtractWinFormsDesignerFile' macro.
    '
    ' Duncan Smart, InfoBasis, 2007
    ' From: http://blog.dotsmart.net/2008/05/20/converting-visual-studio-2003-winforms-to-visual-studio-20052008-partial-classes/
    ' Modified and updated by Nathan Jones, 2010
    ' See: http://www.nathanpjones.com/
    ' -------------------------------------------------------------------------

    Sub ExtractWinFormsDesignerFile()

        Dim item As ProjectItem = DTE.SelectedItems.Item(1).ProjectItem
        Dim sourceFileName As String = item.FileNames(1)
        Dim sourceDir As String = System.IO.Path.GetDirectoryName(sourceFileName)
        Dim origCode As String
        Dim bareName As String = System.IO.Path.GetFileNameWithoutExtension(sourceFileName)
        Dim newDesignerFile As String = sourceDir &amp; &quot;\&quot; &amp; bareName &amp; &quot;.Designer.vb&quot;

        If IO.File.Exists(newDesignerFile) Then
            MsgBox(&quot;Designer file already exists!&quot;)
            Exit Sub
        Else
            If MsgBox(&quot;You are about to extract designer code from:&quot; + vbCrLf + _
                      vbCrLf + _
                      &quot;    &quot; + sourceFileName + vbCrLf + _
                      vbCrLf + _
                      &quot;To the following file:&quot; + vbCrLf + _
                      vbCrLf + _
                      &quot;    &quot; + newDesignerFile + vbCrLf + _
                      vbCrLf + _
                      &quot;MAKE SURE TO BACK UP FIRST!&quot;, _
                      MsgBoxStyle.OkCancel Or MsgBoxStyle.DefaultButton2 Or MsgBoxStyle.Question, _
                      &quot;Confirm&quot;) = MsgBoxResult.Cancel Then Exit Sub
        End If
        origCode = System.IO.File.ReadAllText(sourceFileName)

        Dim codeClass As CodeClass
        Dim namespaceName As String

        codeClass = findClass(item.FileCodeModel.CodeElements)
        namespaceName = &quot;&quot;
        If codeClass.Namespace IsNot Nothing Then
            namespaceName = codeClass.Namespace.FullName
        End If

        Dim initComponentText As String
        Dim disposeText As String
        Dim fieldDecls() As String
        Try
            initComponentText = extractMember(codeClass.Members.Item(&quot;InitializeComponent&quot;))
        Catch
            MsgBox(&quot;Error extracting InitializeComponent!&quot;)
            Exit Sub
        End Try
        Try
            disposeText = extractMember(codeClass.Members.Item(&quot;Dispose&quot;))
        Catch
            MsgBox(&quot;Error extracting Dispose! Will restore source file.&quot;)
            System.IO.File.WriteAllText(sourceFileName, origCode)
            Exit Sub
        End Try
        Try
            fieldDecls = extractWinFormsFields(codeClass, initComponentText)
        Catch
            MsgBox(&quot;Error extracting field declares! Will restore source file.&quot;)
            System.IO.File.WriteAllText(sourceFileName, origCode)
            Exit Sub
        End Try

        Dim finalCode As String

        finalCode = IIf(namespaceName &lt;&gt; &quot;&quot;, &quot;Namespace &quot; + namespaceName + vbCrLf + vbCrLf, &quot;&quot;) + _
                    &quot;&lt;Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()&gt; _&quot; + vbCrLf + _
                    &quot;Partial Class &quot; + codeClass.Name + vbCrLf + _
                    &quot;    Inherits System.Windows.Forms.Form&quot; + vbCrLf + _
                    vbCrLf + _
                    disposeText + vbCrLf + _
                    vbCrLf + _
                    fieldDecls(0) + vbCrLf + _
                    vbCrLf + _
                    initComponentText + vbCrLf + _
                    fieldDecls(1) + vbCrLf + _
                    &quot;End Class&quot; + vbCrLf + _
                    IIf(namespaceName &lt;&gt; &quot;&quot;, vbCrLf + &quot;End Namespace&quot; + vbCrLf, &quot;&quot;)

        ' Now write the new designer file

        System.IO.File.WriteAllText(newDesignerFile, finalCode)

        Dim newProjItem As ProjectItem = item.ProjectItems.AddFromFile(newDesignerFile)
        Try
            newProjItem.Open()
        Catch
        End Try
        Try
            DTE.ExecuteCommand(&quot;Edit.FormatDocument&quot;)
        Catch
        End Try

        MsgBox(&quot;Code separated successfully!&quot; + vbCrLf + _
               &quot;You may have residual comments or code regions in the source &quot; + vbCrLf + _
               &quot;class that should be deleted or moved to the new Designer.vb class.&quot;, _
               MsgBoxStyle.Information, _
               &quot;Complete&quot;)

    End Sub

    Function findClass(ByVal items As System.Collections.IEnumerable) As CodeClass

        For Each codeEl As CodeElement In items

            If codeEl.Kind = vsCMElement.vsCMElementClass Then

                Return codeEl

            ElseIf codeEl.Children.Count &gt; 0 Then

                Dim cls As CodeClass = findClass(codeEl.Children)
                If cls IsNot Nothing Then
                    Return findClass(codeEl.Children)
                End If

            End If

        Next

        Return Nothing

    End Function

    Function extractWinFormsFields(ByVal codeClass As CodeClass, ByVal initComponentsCode As String) As String()

        Dim member As CodeElement
        Dim fieldsCode As String
        Dim components As String
        Dim initComponentsCodeForComp As String = initComponentsCode.ToLower

        fieldsCode = &quot;&quot;
        For i As Integer = codeClass.Members.Count To 1 Step -1

            member = codeClass.Members.Item(i)

            If member.Kind = vsCMElement.vsCMElementVariable Then

                Dim field As CodeVariable = member

                If field.Type.TypeKind &lt;&gt; vsCMTypeRef.vsCMTypeRefArray Then

                    If field.Name.ToLower = &quot;components&quot; Then

                        ' We'll insert this separately
                        components = extractMember(field)

                    ElseIf initComponentsCodeForComp Like (&quot;* Me.&quot; + field.Name + &quot; = New *&quot;).ToLower Then

                        fieldsCode = extractMember(field) + vbCrLf + _
                                     fieldsCode

                    End If

                End If

            End If

        Next

        Return New String() {components, fieldsCode}

    End Function

    Function extractMember(ByVal memberElement As CodeElement) As String

        Dim memberStart As EditPoint = memberElement.GetStartPoint().CreateEditPoint()
        Dim memberText As String = String.Empty

        memberText += memberStart.GetText(memberElement.GetEndPoint())
        memberStart.Delete(memberElement.GetEndPoint())

        Return memberText

    End Function

End Module</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.nathanpjones.com/wp/2010/02/converting-vb-net-2003-winforms-to-20052008-partial-classes/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Parallels Desktop 5 vs. VMWare Fusion 3</title>
		<link>http://www.nathanpjones.com/wp/2010/01/parallels-desktop-5-vs-vmware-fusion-3/</link>
		<comments>http://www.nathanpjones.com/wp/2010/01/parallels-desktop-5-vs-vmware-fusion-3/#comments</comments>
		<pubDate>Sun, 24 Jan 2010 22:29:48 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Reviews]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[parallels desktop]]></category>
		<category><![CDATA[review]]></category>
		<category><![CDATA[vmware fusion]]></category>

		<guid isPermaLink="false">http://www.nathanpjones.com/wp/?p=111</guid>
		<description><![CDATA[As everyone else is weighing in with anecdotal evidence so will I. Since I use my Mac to run Windows to program in Windows and DOS for work, it&#8217;s very important to me to select the very best emulator. The odd thing is how each performed very well in different areas, both singularly excelling in [...]]]></description>
			<content:encoded><![CDATA[<p>As everyone else is weighing in with anecdotal evidence so will I. Since I use my Mac to run Windows to program in Windows and DOS for work, it&#8217;s very important to me to select the very best emulator. The odd thing is how each performed very well in different areas, both singularly excelling in areas that I would consider critical. That said, I think Parallels wins&#8230; read on.</p>
<p><em>Parallels Desktop 5</em></p>
<ul>
<li><strong>Faster Virtual Disk Access</strong> &#8211; And this is why it wins for me. Since so much of the performance of the VM is dependent on the virtual hard drive, this puts it way ahead of Fusion especially if you&#8217;re running antivirus on your VM.</li>
<li><strong>Getures</strong> &#8211; Why can&#8217;t Fusion do this? Although I plug in a separate keyboard and mouse, several of my VM&#8217;s I use with the naked (so to speak) hardware. I was doing it by habit already so this is a win.</li>
<li><strong>Serial Ports</strong> &#8211; To be honest I haven&#8217;t gotten the serial port to pipe to work (in about 30 min of trying), but the capabilities are far beyond Fusion, supporting even physical serial ports.</li>
<li><strong>Configuration Options</strong> &#8211; It simply has more configuration options. Generally you don&#8217;t need them, but they&#8217;re there when you need them.</li>
<li><strong>Better Host Integration Mgmt</strong> &#8211; Although turning these features off is anything but straightfoward, you have many more levels of integration from folder to MacLook that makes your Windows programs look like Mac programs. Also, there is (new to v5) a checkbox to completely isolate the VM from the host which will turn off all the other integration features.</li>
</ul>
<p><em>VMWare Fusion 3</em></p>
<ul>
<li><strong>Workhorse CPU Virtualization</strong> &#8211; I have a testing program that tests the output of two different DOS programs running in the Windows XP DOS window (NTVDM). On a physical computer, these each consume up to 50% of the CPU. Parallels chokes and can run about .3-.4 units/sec whereas Fusion can test upwards of .6 units/sec. For whatever reason (probably lousy virtual drive performance), this doesn&#8217;t translate into overall better performance in Fusion.</li>
<li><strong>FULL Keyboard Support</strong> &#8211; Fusion actually captures special keys like F12. I have Cmd+F12 mapped to the Pause/Break key. Parallels won&#8217;t allow this-won&#8217;t even allow setting it without turning off the OSX shortcut. Even in full screen it will bring up the Dashboard.</li>
<li><strong>Good Mouse Support</strong> &#8211; Although it doesn&#8217;t support gestures, it did recognized the &#8220;Back&#8221; and &#8220;Forward&#8221; buttons on my Logitech mouse, and I don&#8217;t have any special Logitech drivers installed on the host or the VM.</li>
<li><strong>Straightforward Config</strong> &#8211; Although not sufficient for the power-user, it does strike me as more accessible for the novice user.</li>
</ul>
<p>These are just a few observations from regular use of both programs. Many of the basic features are identical, but Parallels really has the edge.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.nathanpjones.com/wp/2010/01/parallels-desktop-5-vs-vmware-fusion-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

