<?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>Cypris&#039; lookout</title>
	<atom:link href="http://blog.nkadesign.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.nkadesign.com</link>
	<description>Renaud Bompuis on the interwebs!</description>
	<lastBuildDate>Fri, 16 Mar 2012 09:24:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Programming podcasts</title>
		<link>http://blog.nkadesign.com/2011/programming-podcasts/</link>
		<comments>http://blog.nkadesign.com/2011/programming-podcasts/#comments</comments>
		<pubDate>Wed, 07 Sep 2011 03:37:34 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Fun]]></category>
		<category><![CDATA[Musing]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=719</guid>
		<description><![CDATA[Podcasts are a great way to get educated and entertained. As a developer we are lucky to have a choice of some fine podcasts from industry leaders. If you commute, jog, travel, you can easily use that time away from the computer to get better informed and reflect about our field.]]></description>
			<content:encoded><![CDATA[<p>As a developer it&#8217;s often hard to stay current with your field. New technologies and new ways of doing programming pop up every day, it&#8217;s difficult to know if you should invest any time in learning them or if they are just passing fads.</p>

<p>Podcasts are a great way to get exposed to these new things: if you commute, jog, travel, you can easily use that time away from the computer to get better informed and reflect about our field.</p>

<p>I have a 20 minute walk between home and my office. That&#8217;s more than 3h of free time per week that I can spend thinking, listening to music or getting entertained and educated through relevant podcasts.</p>

<p>These are my preferred shows so far:</p>

<p><img src="/wp-content/uploads/2011/09/hanselminutes.jpg" alt="Hanselminutes podcast" title="Hanselminutes podcast" width="51" height="51" align="left" hspace="5" vspace="5" border="0" /> <strong><a href="http://www.hanselminutes.com/">Hanselminutes</a></strong> <a href="http://itunes.apple.com/us/podcast/hanselminutes/id117488860"><img src="/wp-content/uploads/2011/09/viewinitunes_enbws.png" alt="Subscribe with iTunes" /></a><br />
A 30 minute or so podcast about technologies, usually closely or distantly related to Microsoft development. Scott is an excellent interviewer and his <a href="http://www.hanselman.com/blog/">blog</a> is a must read too.</p>

<p><img src="/wp-content/uploads/2011/09/herdingcode.jpg" alt="Herding Code" title="Herding Code" width="51" height="51" align="left" hspace="5" vspace="5" border="0" /> <strong><a href="http://herdingcode.com/">Herding Code</a></strong> <a href="http://itunes.apple.com/podcast/herding-code/id284067914"><img src="/wp-content/uploads/2011/09/viewinitunes_enbws.png" alt="Subscribe with iTunes" /></a><br />
A 60 minute show with a bunch of well-known developers, <a href="http://odetocode.com/">K. Scott Allen</a>, <a href="http://weblogs.asp.net/kdente/">Kevin Dente</a>, <a href="http://lazycoder.com/weblog/">Scott Koon (Lazycoder)</a>, and <a href="http://weblogs.asp.net/jgalloway/">Jon Galloway</a> discussing wide-ranging topics with their guests.</p>

<p><img src="/wp-content/uploads/2011/09/dotnetrocks.jpg" alt=".Net Rocks!" title=".Net Rocks!" width="51" height="51" align="left" hspace="5" vspace="5" border="0" /><strong><a href="http://dotnetrocks.com/">.Net Rocks</a></strong> <a href="http://itunes.apple.com/podcast/.net-rocks!/id130068596"><img src="/wp-content/uploads/2011/09/viewinitunes_enbws.png" alt="Subscribe with iTunes" /></a><br />
The unavoidable 60 minute grand-father or all .Net podcasts. Funny and always informative. Also check out the related <a href="http://dnrtv.com/">DnrTV</a> for on-topic screencasts, excellent for getting started on a new technology.</p>

<p><img src="/wp-content/uploads/2011/09/polymorphic.jpg" alt="PolymorphicPodcast.com" title="PolymorphicPodcast.com" width="51" height="51" align="left" hspace="5" vspace="5" border="0" /><strong><a href="http://polymorphicpodcast.com/">The Polymorphic podcast</a></strong> <a href="http://itunes.apple.com/podcast/polymorphic-podcast/id73330909"><img src="/wp-content/uploads/2011/09/viewinitunes_enbws.png" alt="Subscribe with iTunes" /></a><br />
A nice podcast, the host, Craig Shoemaker, is a great inteviewer. Only drawback is that shows are not regularly produced.</p>

<p><img src="/wp-content/uploads/2011/09/stackexchange.jpg" alt="The Stack Exchange podcast" title="The Stack Exchange podcast podcast" width="51" height="51" align="left" hspace="5" vspace="5" border="0" /><strong><a href="http://blog.stackoverflow.com/category/podcasts/">The StackExchange podcast</a></strong> <a href="http://itunes.apple.com/us/podcast/the-stack-exchange-podcast/id279215411"><img src="/wp-content/uploads/2011/09/viewinitunes_enbws.png" alt="Subscribe with iTunes" /></a><br />
Sometimes random, mildly irritating at times (guests sound quality, audio sync between guest, ramblings about Stackoverflow&#8217;s principles) but usually both enlightenning and funny. Topics revolve around <a href="http://stackoverflow.com/">Stackoverflow</a> and the various <a href="http://stackexchange.com/sites">StackExchange</a> sites. It&#8217;s always worth listenting to <a href="http://www.joelonsoftware.com/">Joel Spolsky</a>, he tends to see clearly in an industry that often borders on the BS.</p>

<p><img src="/wp-content/uploads/2011/09/thisdeveoperslife.jpg" alt="This Developer's Life podcast" title="This Developer's Life podcast" width="51" height="51" align="left" hspace="5" vspace="5" border="0" /><strong><a href="http://www.thisdeveloperslife.com/">This Developer&#8217;s Life</a></strong> <a href="http://itunes.apple.com/us/podcast/this-developers-life/id389727545"><img src="/wp-content/uploads/2011/09/viewinitunes_enbws.png" alt="Subscribe with iTunes" /></a><br />
Last but not least, a beautifully produced podcast that covers more philosophical topics through interviews and real-life experiences. It&#8217;s not about technology, it&#8217;s about the human aspect of being a coder, and what it means to be one.</p>

<p>Whichever you choose, any of these podcasts are bound to expand your knowledge, educate and entertain you!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2011/programming-podcasts/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Office 2010 SP1 and Access 2010 Runtime SP1 are broken</title>
		<link>http://blog.nkadesign.com/2011/office-2010-sp1-and-access-2010-runtime-sp1-are-broken/</link>
		<comments>http://blog.nkadesign.com/2011/office-2010-sp1-and-access-2010-runtime-sp1-are-broken/#comments</comments>
		<pubDate>Wed, 13 Jul 2011 11:22:25 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[MSAccess]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=706</guid>
		<description><![CDATA[(Updated Saturday 10DEC2011.) On 28th of June 2011, Microsoft Office 2010 Service Pack 1 and the Access 2010 Runtime Service Pack 1 were issued. After upgrading my development machine (Win7 x64) and a few clients (Windows 2008R2 x64) to SP1 (x86), I started to get strange issues: I use .Net libraries from my Access application [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/access.png" alt="Microsoft Access" title="Microsoft Access" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />  (<strong>Updated Saturday 10DEC2011.</strong>) On 28th of June 2011, Microsoft Office 2010 Service Pack 1 and the Access 2010 Runtime Service Pack 1 were issued.</p>

<p>After upgrading my development machine (Win7 x64) and a few clients (Windows 2008R2 x64) to SP1 (x86), I started to get strange issues:</p>

<ul>
<li>I use .Net libraries from my Access application and suddenly, even when not instantiating any .Net objects, Access would crash, usually on startup, but sometimes when opening the VBE.<br />
Decompiling and re-compacting the database would be OK, usually once, but the problem would reappear the next time I would restart the application.<br />
<center><img title="MSAccess error" src="/wp-content/uploads/2011/07/sshot-4.png" width=491 Height=128 style="float:center;margin:10px;" /></center></li>
<li>In the Runtime, I would get strange errors, such as <em>The setting your entered isn&#8217;t valid for this property</em>, or <em>Action Failed Error Number: 2950</em>, or <em>Runtime Error 3270 Property not found</em>.<br />
The strange thing about these errors is that they would occur in places that had not been modified for many releases of our application, parts that have been running without problem until now.<br />
<center><img title="MSAccess error" src="/wp-content/uploads/2011/07/sshot-5.png" width=327 Height=199 style="margin:10px;" /></center></li>
<li>Another weird issue was the systematic reset of our custom ribbon to its first tab. this could happen randomly, but most it could also be reproduced by simply opening a report as a tab page (that fill-in the whole MDI window). When closing that form, the first tab of the ribbon would select itself automatically. This wasn&#8217;t happening when closing pop-up windows.</li>
</ul>

<p>After removing the Office and Runtime Service Pack 1, everything went back to normal.</p>

<h3>A fix, finally!</h3>

<p>A good 6 months after SP1 was released, Microsoft finally issued <a href="http://support.microsoft.com/kb/2596585">hotfix</a> for the issue!<br />
So, <a href="http://answers.microsoft.com/en-us/office/forum/office_2010-access/access-2010-sp1-you-receive-random-crashes-in/d2bf6175-075a-4a12-a2b1-f55d40af271b?page=17">read about it on the MS Forums</a> and get your <a href="http://support.microsoft.com/kb/2596585">KB2596585</a> hotfix, then <a href="http://www.trigeminal.com/usenet/usenet004.asp">decompile</a> your database to clean it out.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2011/office-2010-sp1-and-access-2010-runtime-sp1-are-broken/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Admin: Linux file server performance boost (ext4 version)</title>
		<link>http://blog.nkadesign.com/2010/admin-linux-file-server-performance-boost-ext4-version/</link>
		<comments>http://blog.nkadesign.com/2010/admin-linux-file-server-performance-boost-ext4-version/#comments</comments>
		<pubDate>Sun, 03 Oct 2010 04:34:34 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=665</guid>
		<description><![CDATA[In the previous article, I showed how to improve the performance of an existing file server by tweaking ext3 and mount settings. We can also take advantage of the availability of the now stable ext4 file system to further improve our file server performance. Some distribution, in particular RedHat/CentOS 5, do not allow us to [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/linux.png" alt="Linux" title="Linux" align="left" width="54" height="64" hspace="5" vspace="5" border="0" />In the previous article, I showed how to improve the performance of an existing file server by tweaking ext3 and mount settings.<br />
We can also take advantage of the availability of the now stable ext4 file system to further improve our file server performance.</p>

<p>Some distribution, in particular RedHat/CentOS 5, do not allow us to select ext4 as a formatting option during setup of the machine, so you will initially have to use ext3 as file system (on top of LVM preferably for easy extensibility).</p>

<h3>A small digression on partitioning</h3>

<p>Remember to create separate partitions for your file data: do not mix OS files with data files, they should live on different partitions.
In an enterprise environment, a minimal partition configuration for a file server could look like:</p>

<p>Hardware:</p>

<ul>
<li>2x 160GB HDD for the OS</li>
<li>4x 2TB HDD for the data</li>
</ul>

<p>The 160GB drives could be used as such:</p>

<ul>
<li>200MB RAID1 partition over the 2 drives for <code>/boot</code></li>
<li>2GB RAID1 partition over the 2 drives for swap</li>
<li>all remaining space as a RAID1 partition over the 2 drives for <code>/</code><br />
Note though that it is generally recommended to create additional partitions to further contain <code>/tmp</code> and <code>/var</code>.</li>
</ul>

<p>The 2TB drives could be used like this:</p>

<ul>
<li>all space as RAID6 over all drives (gives us 4TB of usable space) for <code>/data</code></li>
<li>alternatively, all space as RAID5 over all drives (gives us 6TB of usable space)
The point of using RAID6 is that it gives better redundancy than RAID5, so you can safely add more drives later without increasing the risk of failure of the whole array (which is not true of RAID5).</li>
</ul>

<h3>Moving to ext4</h3>

<p>If you are upgrading an existing system, backup first!</p>

<p>Let&#8217;s say that your <code>/data</code> partition is an LVM volume under <code>/dev/VolGroup01/LogVol00</code>.
First, make sure we have the ext4 tools installed on our machine, then unmount the partition to upgrade:</p>

<pre><code># yum -y install e4fsprogs
# umount /dev/VolGroup01/LogVol00
</code></pre>

<p>For a <strong>new system</strong>, <a href="http://www.cyberciti.biz/tips/fdisk-unable-to-create-partition-greater-2tb.html">create a large partition on the disk</a>, then format the volume (this will <strong>destroy all data</strong> on that volume!).</p>

<pre><code># mkfs -t ext4 -E stride=32 -m 0 -O extents,uninit_bg,dir_index,filetype,has_journal,sparse_super /dev/VolGroup01/LogVol00
# tune4fs -o journal_data_writeback /dev/VolGroup01/LogVol00
</code></pre>

<p><em>Note: on a RAID array, use the appropriate <code>-E stride,stripe-width</code> options, for instance, on a RAID5 array using 4 disks and 4k blocks, it could be: <code>-E stride=16,stripe-width=48</code></em></p>

<p>For an <strong>existing system</strong>, upgrading from ext3 to ext4 without damaging existing data is barely more complicated:</p>

<pre><code># fsck.ext3 -pf  /dev/VolGroup01/LogVol00
# tune2fs -O extents,uninit_bg,dir_index,filetype,has_journal,sparse_super /dev/VolGroup01/LogVol00
# fsck.ext4 -yfD /dev/VolGroup01/LogVol00
</code></pre>

<p>We can optionally give our volume a new label to easily reference it later:</p>

<pre><code># e4label /dev/VolGroup01/LogVol00 data
</code></pre>

<p>Then we need to persist the mount options in <code>/etc/fstab</code>:</p>

<pre><code>/dev/VolGroup01/LogVol00    /data    ext4    noatime,data=writeback,barrier=0,nobh,errors=remount-ro    0 0
</code></pre>

<p>And now we can remount our volume:</p>

<pre><code># mount /data
</code></pre>

<p>If you upgraded an existing filesystem from etx3, you may want to run the following to ensure the existing files are using <a href="http://en.wikipedia.org/wiki/Extent_%28file_systems%29">extents</a> for file attributes:</p>

<pre><code># find /data -xdev -type f -print0 | xargs -0 chattr +e
# find /data -xdev -type d -print0 | xargs -0 chattr +e
</code></pre>

<h3>Important notes</h3>

<p>The mounting options we use are somewhat a bit risky if your system is not adequately protected by a UPS.<br />
If your system crashes due to a power failure, you are more likely to lose data using these options than using the safer defaults.<br />
At any rate, you must have a proper backup strategy in place to safeguard data, regardless of what could damage them (hardware failure or user error).</p>

<ul>
<li>The <code>barrier=0</code> option disables <em>Write barriers</em> that enforce proper on-disk ordering of journal commits.</li>
<li>The <code>data=writeback</code> and <code>nobh</code> go hand in hand and allow the system to write data even after it has been committed to the journal.</li>
<li>The <code>noatime</code> ensures that the access time is not updated when we&#8217;re reading data as this is a big performance killer (this one is safe to use in any case).</li>
</ul>

<h3>References</h3>

<ul>
<li><a href="http://blog.smartlogicsolutions.com/2009/06/04/mount-options-to-improve-ext4-file-system-performance/">Mount options to improve ext4 file system performance</a></li>
<li><a href="https://ext4.wiki.kernel.org/index.php/Ext4_Howto">Ext4 Howto</a></li>
<li><a href="http://www.debian-administration.org/article/Migrating_a_live_system_from_ext3_to_ext4_filesystem">Migrating a live system from ext3 to ext4 filesystem</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2010/admin-linux-file-server-performance-boost-ext4-version/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Admin: Linux file server performance boost (ext3 version)</title>
		<link>http://blog.nkadesign.com/2010/admin-linux-file-server-performance-boost/</link>
		<comments>http://blog.nkadesign.com/2010/admin-linux-file-server-performance-boost/#comments</comments>
		<pubDate>Sun, 11 Jul 2010 10:36:47 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=634</guid>
		<description><![CDATA[Using a Linux for an office file server is a no-brainer: it&#8217;s cheap, you don&#8217;t have to worry about unmanageable license costs and it just works. Default settings of most Linux distributions are however not optimal: they are meant to be as standard compliant and as general as possible so that everything works well enough [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/linux.png" alt="Linux" title="Linux" align="left" width="54" height="64" hspace="5" vspace="5" border="0" />
Using a Linux for an office file server is a no-brainer: it&#8217;s cheap, you don&#8217;t have to worry about unmanageable license costs and it just works.</p>

<p>Default settings of most Linux distributions are however not optimal: they are meant to be as standard compliant and as general as possible so that everything works well enough regardless of what you do.</p>

<p>For a file server hosting large numbers of files, these default settings can become a liability: everything slows down as the number of files creeps up and it makes your once-snappy fileserver as fas as a sleepy sloth.</p>

<p>There are a few things that we can do to ensure we get the most of our server.</p>

<h3>Checking our configuration</h3>

<p>First, a couple of commands that will help us investigate the current state of our configuration.</p>

<ul>
<li><p><code>df</code> will give us a quick overview of the filesystem:</p>

<pre><code># df -T
Filesystem    Type   1K-blocks      Used Available Use% Mounted on
/dev/md2      ext3    19840804   4616780  14199888  25% /
tmpfs        tmpfs      257580         0    257580   0% /dev/shm
/dev/md0      ext3      194366     17718    166613  10% /boot
/dev/md4      ext3     9920532   5409936   3998532  58% /var
/dev/md3      ext3      194366      7514    176817   5% /tmp
/dev/md5      ext3    46980272  31061676  13493592  70% /data
</code></pre></li>
<li><p><code>tune2fs</code> will help us configure the options for each ext3 partition.
If we want to check what is the current configuration of a given partition, says we want to know the current options for our <code>/data</code> mount:</p>

<pre><code># tune2fs -l /dev/md5
</code></pre>

<p>If I was using LVM as a Volume manager, I would type something like:</p>

<pre><code># tune2fs -l /dev/VolGroup00/LogVol02
</code></pre>

<p>This would give lots of information about the partition:</p>

<pre><code>tune2fs 1.40.2 (12-Jul-2007)
Filesystem volume name:   &lt;none&gt;
Last mounted on:          &lt;not available&gt;
Filesystem UUID:          d6850da8-af6f-4c76-98a5-caac2e10ba30
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal resize_inode dir_index filetype 
                          needs_recovery sparse_super large_file
Filesystem flags:         signed directory hash
Default mount options:    user_xattr acl
Filesystem state:         clean
Errors behavior:          Continue
....
</code></pre>

<p>The interesting options are listed under <code>Filesystem features</code> and <code>Default mount options</code>. For instance, here we know that the partition is using a journal and that it is using the <code>dir_index</code> capability, already a performance booster.</p></li>
<li><p><code>cat /proc/mounts</code> is useful to know the mounting options for our filesystem (just listed some interesting ones here):</p>

<pre><code>rootfs / rootfs rw 0 0
/dev/root / ext3 rw,data=ordered 0 0
/dev/md0 /boot ext3 rw,data=ordered 0 0
/dev/md4 /var ext3 rw,data=ordered 0 0
/dev/md3 /tmp ext3 rw,data=ordered 0 0
/dev/md5 /data ext3 rw,data=ordered 0 0
none /proc/sys/fs/binfmt_misc binfmt_misc rw 0 0
/dev/md4 /var/named/chroot/var/run/dbus ext3 rw,data=ordered 0 0
</code></pre>

<p>The <code>data=ordered</code> mount parameter tells us of the journaling configuration for the partition.</p></li>
</ul>

<h3>Journaling</h3>

<p>So what is <a href="http://en.wikipedia.org/wiki/Journaling_file_system">journaling</a>?<br />
It&#8217;s one of the great improvements of ext3: a journal is a special log on the disk that keeps track of changes about to be made. It ensures that, in case of failure, the filesystem can quickly recover without loss of information.</p>

<p>There are 3 settings for the journalling feature:</p>

<ul>
<li><code>data=journal</code> the most secure but also slowest option since all data and metadata is written to disk: the whole operation needs to be completed before any other operation can be completed. It&#8217;s sort of going to the bank for a deposit, filling the paperwork and making sure the teller puts the money in the vault before you leave.</li>
<li><code>data=ordered</code> is usually the default compromise: you fill-in the paperwork and remind the teller to put the money in the vault asap.</li>
<li><code>data=writeback</code> is the fastest but you can&#8217;t be absolutely sure that things will be done in time to prevent any loss if a problem occurs soon after you&#8217;ve asked for the data to be written.</li>
</ul>

<p>In normal circumstances all 3 end-up the same way: data is eventually written to disk and everything is fine.<br />
Now if there is a crash just as the data was written only option <code>journal</code> would guarantee that everything is safe. Option <code>ordered</code> is fairly safe too because the money should be in the vault soon after you left; most systems use this option by default.</p>

<p>If you want to boost your performance and use <code>writeback</code> you should make sure that:</p>

<ul>
<li>you have a good power-supply backup to minimise the risk of power failure</li>
<li>you have a good data backup strategy</li>
<li>you&#8217;re ok with the risk of losing the data that was written right before the crash.</li>
</ul>

<p>To change the journaling option you simply use <code>tune2fs</code> with the appropriate option:</p>

<pre><code># tune2fs -o journal_data_writeback /dev/md5
</code></pre>

<h3>Mount options</h3>

<p>Now that we&#8217;ve changed the available options for our partition, we need to tell the system to use them.<br />
Edit <code>/etc/fstab</code> and add <code>data=writeback</code> to the option columns:</p>

<pre><code>/dev/md5     /data    ext3    defaults,data=writeback   1 2
</code></pre>

<p>Next time our partition is mounted, it will use the new option. For that we can either reboot or remount the partition:</p>

<pre><code># mount - o remount /data
</code></pre>

<h3>noatime option</h3>

<p>There is another option that can have a very dramatic effect on performance, probably even more than the journaling options above.</p>

<p>By default, whenever you read a file the kernel will update its last access time, meaning that we end up with a write operation for every read!<br />
Since this is required for POSIX compliance, almost all Linux distributions leave this setting alone by default.<br />
For a file server, this can have such drastic consequence on performance.</p>

<p>To disable this time-consuming and not useful feature (for a file server), simply add the <code>noatime</code> option to the <code>fstab</code> mount options:</p>

<pre><code>/dev/md5     /data    ext3    defaults,noatime,data=writeback   1 2
</code></pre>

<p>Note that updating access times is sometimes required by some software, such as mail software (such as mutt). If you properly keep your company data in a dedicated partition, you can enable the mount options only for that partition and keep other options for the root filesystem.</p>

<h3>dealing with errors in fstab</h3>

<p>After doing the above on one of the servers, I realized that I made a typo when editing <code>/etc/fstab</code>.<br />
This resulted in the root filesystem being mounted read-only, making fstab impossible to edit&#8230;</p>

<p>To make matters worse, this machine was a few thousand miles away and could not be accessed physically&#8230;.</p>

<p>Remounting the root filesystem resulted in errors:</p>

<pre><code># mount -o remount,rw /
mount: / not mounted already, or bad option
</code></pre>

<p>After much trial and rebooting, this worked (you need to specify all mounting options, to avoid the wrong defaults from being read from etc/mtab`):</p>

<pre><code># mount  -o rw,remount,defaults /dev/md2 /
</code></pre>

<p>After that, I could edit <code>/etc/fstab</code> and correct the typo&#8230;</p>

<h3>Conclusions</h3>

<p>How much these options will improve performance really depends on how your data is used: the improvements should be perceptible if your directories are filled with large amounts of small files.<br />
Deletion should also be faster.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2010/admin-linux-file-server-performance-boost/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Access: checking blank variables</title>
		<link>http://blog.nkadesign.com/2009/access-checking-blank-variables/</link>
		<comments>http://blog.nkadesign.com/2009/access-checking-blank-variables/#comments</comments>
		<pubDate>Wed, 09 Sep 2009 05:54:00 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[MSAccess]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=618</guid>
		<description><![CDATA[I often have to test String, Variant or Object variables that have no content and could be considered &#8216;blank&#8217;. The problem is that testing for &#8220;blankness&#8221; can mean many different things to different types: For an Object type, the variable can be Nothing. For a String type, the string can have no content at all: [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/access.png" alt="Microsoft Access" title="Microsoft Access" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />
I often have to test String, Variant or Object variables that have no content and could be considered &#8216;blank&#8217;.</p>

<p>The problem is that testing for &#8220;blankness&#8221; can mean many different things to different types:</p>

<ul>
<li>For an <code>Object</code> type, the variable can be <code>Nothing</code>.</li>
<li>For a <code>String</code> type, the string can have no content at all: <code>""</code>, <code>vbNullString</code>.</li>
<li>For a <code>Variant</code> type, the string can have any of the following attributes or values:

<ul>
<li>it can be <code>Missing</code> if the variable is an unused optional parameter,</li>
<li>it can be <code>Empty</code> if it was never assigned,</li>
<li>it can be <code>Null</code> if, for instance it&#8217;s bound to a nullable field or unbound with no value,</li>
<li>it can be an empty string <code>""</code>, <code>vbNullString</code>.</li>
</ul></li>
</ul>

<p>When having to check these variables in code, it can be tiresome to have to go through testing some of these possibilities just to find out that your variable does or not not contains something useful, regardless of the type of variable you are using.</p>

<p>To avoid having to do all these tests, make the code a bit more tidy and allow me to move on to more important things, I use this small utility function quite often:</p>

<p><textarea name="code" class="vb:nogutter">
'-----------------------------------------------------------------------------
' True if the argument is Nothing, Null, Empty, Missing or an empty string .
'-----------------------------------------------------------------------------
Public Function IsBlank(arg As Variant) As Boolean
    Select Case VarType(arg)
        Case vbEmpty
            IsBlank = True
        Case vbNull
            IsBlank = True
        Case vbString
            IsBlank = (arg = vbNullString)
        Case vbObject
            IsBlank = (arg Is Nothing)
        Case Else
            IsBlank = IsMissing(arg)
    End Select
End Function
</textarea></p>

<p>So now I don&#8217;t have to worry so much about the type of the variable I&#8217;m testing when I want to know if it contains useful data:
<textarea name="code" class="vb:nogutter">
...
' Here assume that CustomerReference is a control on a form.
' By using IsBlank() we avoid having to test both for Null and empty string.
If IsBlank(CustomerReference) Then
   MsgBox "Customer Reference cannot be left blank."
End If
...
</textarea></p>

<p>Obviously, <code>IsBlank()</code> doesn&#8217;t replace the other tests but I found it to be more straightforward to use in most cases.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2009/access-checking-blank-variables/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A story about exceptional service</title>
		<link>http://blog.nkadesign.com/2009/a-story-about-exceptional-service/</link>
		<comments>http://blog.nkadesign.com/2009/a-story-about-exceptional-service/#comments</comments>
		<pubDate>Wed, 26 Aug 2009 02:54:42 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Reviews]]></category>
		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=613</guid>
		<description><![CDATA[Recently I found myself constrained by the puny 200GB of my Mac Book Pro and I bought a 500GB Seagate drive to replace it (a fast 7200 rpm one). The Macbook Pro has no easy access for the drive so you have to resort to dismantling the case to access it. This put me off [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/apple.png" alt="security01.png" title="security01.png" align="left" width="53" height="64" hspace="5" vspace="5" border="0" />Recently I found myself constrained by the puny 200GB of my Mac Book Pro and I bought a <a href="http://www.seagate.com/ww/v/index.jsp?vgnextoid=3a07bfafecadd110VgnVCM100000f5ee0a0aRCRD&amp;locale=en-US&amp;reqPage=Model&amp;modelReqTab=Features">500GB Seagate drive</a> to replace it (a fast 7200 rpm one).<br />
The Macbook Pro has no easy access for the drive so you have to resort to dismantling the case to access it.
This put me off replacing the drive because I would probably be voiding the warranty and was running the risk of damaging this expensive piece of equipment.</p>

<p>I&#8217;ve been filling the drive with pictures from my recent camera purchase and I couldn&#8217;t put it off any longer, so I bought the new drive and went online to find some good tutorial on how to crack open the Macbook Pro case.</p>

<p>After a few searches, I noticed that many people were referring to the <a href="http://www.ifixit.com/">iFixit.com</a> website. 
It was very easy to find the tutorial I was looking for, I didn&#8217;t have to register, and each step was made very clear and simple.<br />
It took no time to open the case and replace the drive.<br />
I was very happy with that find.</p>

<p>Now, that&#8217;s not the end of the story.</p>

<p><img title="Macbook Pro" src="/wp-content/uploads/2009/08/c2dopen2.jpg" width=276 Height=160 style="float:right;margin-left:10px;margin-bottom:5px;" />A couple of days before I replaced the drive the left fan of the laptop suddenly became noisy. This would happen a few times a day, at random, and would last 10-20 minutes.<br />
My only solution to get this repaired was to get to the local Apple service shop. Even though I knew exactly which part number was to be replaced, they still wanted me to:</p>

<ul>
<li>go across town to visit them so they could see for themselves what the problem was: annoying because the problem was intermittent so I may have to go for nothing.</li>
<li>wait for the part to arrive a few days later.</li>
<li>go back to leave the laptop</li>
<li>go again to collect the repaired laptop the next day or so.
So all in all: about 6h spend travelling back and forth + no laptop for a couple of day + <a href="http://www.pcpro.co.uk/news/262978/exposed-the-pc-repair-shops-that-rifle-through-your-photos-and-passwords">the risk that some indiscreet technician start looking through my personal stuff</a>.</li>
</ul>

<p>Instead, I went back to the  <a href="http://www.ifixit.com/">iFixit</a> website:</p>

<ul>
<li>identified my machine</li>
<li>found out the list of spare parts available from their store</li>
<li>added the fan to my cart</li>
<li>paid for it.</li>
<li>found a guide that showed how to replace the part.</li>
</ul>

<p>That took me all of 10 minutes; I placed my order on Thursday and the next Monday I received the part &#8230; halfway across the globe!</p>

<p>I also got a survey request from <a href="http://www.ifixit.com/">iFixit</a> and left some comments, from which I got back two nice detailed email follow-ups, one from the CEO saying they were implementing my remarks as part of their site improvement efforts.</p>

<p>Well, I thought I would share this story. It&#8217;s not that often that you get excited by an online vendor that not only does its job well but goes beyond expectations.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2009/a-story-about-exceptional-service/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Access: Run-time Error 3155 ODBC insert on a linked table failed</title>
		<link>http://blog.nkadesign.com/2009/access-run-time-error-3155-odbc-insert-on-a-linked-table-failed/</link>
		<comments>http://blog.nkadesign.com/2009/access-run-time-error-3155-odbc-insert-on-a-linked-table-failed/#comments</comments>
		<pubDate>Thu, 11 Jun 2009 08:26:06 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[MSAccess]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=606</guid>
		<description><![CDATA[I have been spending a lot of time trying to find out why some of the code used to insert new records into a linked SQL Server table would systematically fail with an error: Run-time Error '3155' ODBC--insert on a linked table failed It was driving me mad. I could insert a simple record using [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/access.png" alt="Microsoft Access" title="Microsoft Access" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />
I have been spending a lot of time trying to find out why some of the code used to insert new records into a linked SQL Server table would systematically fail with an error:</p>

<pre><code>Run-time Error '3155' ODBC--insert on a linked table  failed
</code></pre>

<p>It was driving me mad.<br />
I could insert a simple record using <em>SQL Server Management Studio</em>, I could add new records to the table in datasheet mode within Access, but as soon as I tried to insert a record from code, whether using DAO recordset or executing the same SQL INSERT, it would miserably fail.</p>

<p>After a fair bit of investigation and tests, of which you can read the full account on <a href="http://stackoverflow.com/questions/979269/inserting-null-in-an-nvarchar-fails-in-msaccess/">the question I asked on StackOverflow</a>, it turns out that this is a long-standing bug in the ODBC Driver (or Access).</p>

<p><code>Memo</code> fields in Access are usually translated into <code>nvarchar(MAX)</code> in SQL Server by tools like <a href="/2009/ms-access-upsizing-to-sql-server-2008/">SSMA</a>.<br />
Unfortunately, when you link tables having these fields using the <em>SQL Server Client</em> driver, these fields get incorrectly interpreted as <code>string</code>, even though they appear ok from the table design view.<br />
It&#8217;s only if you try to insert something into the field, either text larger than 255 chars or NULL, that you get the error message.</p>

<p>So, the solution, at least in this case, is to revert to the older <em>SQL Server</em> ODBC driver instead, or use <code>varchar()</code> instead of <code>nvarchar()</code>, but if you&#8217;re dealing with Unicode, you have to stick with <code>nvarchar()</code>.</p>

<h3>References</h3>

<ul>
<li>My question <a href="http://stackoverflow.com/questions/979269/inserting-null-in-an-nvarchar-fails-in-msaccess/">Inserting NULL in an nvarchar fails in MSAccess</a> on <a href="http://stackoverflow.com/">StackOverflow</a>.</li>
<li>A reference I found on this issue: <a href="http://social.msdn.microsoft.com/Forums/en-US/sqldataaccess/thread/c6d2466e-ecb5-4a98-963f-ae827dbf8caa">Ms Access linking table with nvarchar(max)</a>.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2009/access-run-time-error-3155-odbc-insert-on-a-linked-table-failed/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Access vs SQL Server: some stats (part 1)</title>
		<link>http://blog.nkadesign.com/2009/access-vs-sql-server-some-stats-part-1/</link>
		<comments>http://blog.nkadesign.com/2009/access-vs-sql-server-some-stats-part-1/#comments</comments>
		<pubDate>Mon, 13 Apr 2009 04:00:53 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[MSAccess]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=527</guid>
		<description><![CDATA[In the perspective of upsizing my current Access 2007 application, I have been trying to understand a bit more about the possible performance impact of various choices of Primary Keys. My problem is that currently, the Access application uses autoincrement numbers as surrogate Primary Keys (PK). Since I will need to synchronise the data over [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/access.png" alt="Microsoft Access" title="Microsoft Access" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />
In the perspective of upsizing my current Access 2007 application, I have been trying to understand a bit more about the possible performance impact of various choices of Primary Keys.</p>

<p>My problem is that currently, the Access application uses autoincrement numbers as surrogate Primary Keys (PK).
Since I will need to synchronise the data over multiple remote sites, including occasionally disconnected clients, I can&#8217;t use the current autoincrement PK and will need to change to GUID.</p>

<p>To see for myself what could be the impact, I made a series of benchmarks.<br />
This first part is fairly simple:</p>

<ul>
<li>Populate a Product table that contains 3 fields: <code>ID</code>, <code>SKU</code> and <code>Designation</code> with 1,000,000 records.</li>
<li>Test natively on SQL Server and Access 2007.</li>
<li>The records are inserted in transactions batches of 1000 records.</li>
<li>I collect the time taken for each of these transactions and plot it.</li>
</ul>

<h3>Test setup</h3>

<p>Nothing much to say about that:</p>

<blockquote>
  <p>All tests are performed on a dedicated <em>Windows Server 2008 x64</em> rack running <em>Access 2007</em> and <em>SQL Server 2008 Standard (SP1) x64</em>.</p>
</blockquote>

<h3>Test database</h3>

<p>In SQL Server, we created a database with two tables <code>ProductGUID</code> and <code>ProductInt</code>:</p>

<p><textarea name="code" class="sql:nogutter" cols="60" rows="10">
CREATE TABLE ProductGUID (
	ID UNIQUEIDENTIFIER DEFAULT NEWSEQUENTIALID(),
	SKU NVARCHAR(32) NOT NULL,
	Description NVARCHAR(255) NULL
);
CREATE CLUSTERED INDEX ProdGUIDix ON ProductGUID(ID);
GO

CREATE TABLE ProductINT (
	ID INT IDENTITY(1,1),
	SKU NVARCHAR(32) NOT NULL,
	Description NVARCHAR(255) NULL
);
CREATE CLUSTERED INDEX ProdINTix ON ProductINT(ID);
GO
</textarea></p>

<p>For the table using a GUID, we use the <code>NewSequentialID()</code> instead of <code>NewID()</code> to create new keys. This is supposed to offer much better performance as the generated GUIDs are guaranteed to be sequential rather than random, resulting in better index performance on insertion.</p>

<p>For the Access version of the tables, we basically use the same definition, except that we used 4 tables:</p>

<ul>
<li>ProductINT: let Jet/ACE autonumbering create the sequential integer Primary Key.</li>
<li>ProductINTRandom: let Jet/ACE autonumbering create the random integer Primary Key.</li>
<li>ProductGUIDRandom: let Jet/ACE use its own internal <code>GenGUID()</code> for the key which generates random GUIDs instead of sequential ones.  </li>
<li>ProdcutGUIDSequential: call the Windows API (<a href="http://www.pinvoke.net/default.aspx/rpcrt4/UuidCreateSequential.html">UuidCreateSequential</a>) to create sequential ID instead.</li>
</ul>

<h3>SQL Server Test code</h3>

<p>Using the SQL Server Management Studio, we performed the following test once for each table (resetting the database in-between):
<textarea name="code" class="sql:nogutter" cols="60" rows="10">
SET NOCOUNT ON;
GO

DECLARE @i INT = 1;
WHILE (@i <= 1000)
BEGIN
	DECLARE @tstart DATETIME2 = SYSDATETIME();
	BEGIN TRAN
		DECLARE @a INT = 1;
		WHILE (@a <= 1000)
		BEGIN
			INSERT INTO ProductGUID (SKU,Description) 
			VALUES ('PROD' + CONVERT(CHAR,@a), 'Product number ' + CONVERT(CHAR,@a));
			SELECT @a = @a + 1;
		END;
	COMMIT TRAN;
	SELECT DATEDIFF(MILLISECOND, @tstart, SYSDATETIME()) AS timespan;
SELECT @i = @i + 1;
END;
GO
</textarea></p>

<p>Basically, we perform 1000 transactions each inserting 1000 records into the table <code>ProductGUID</code> or <code>ProductINT</code>.</p>

<h3>Access 2007 Test code</h3>

<p>To duplicate the same conditions, the following VBA code will perform 1000 transactions each inserting 1000 records.<br />
Note that the recordset is opened in Append mode only.<br />
The importance of this will be discussed in another article.</p>

<p><textarea name="code" class="vb:nogutter" cols="60" rows="10">
' Run this to inset 1,000,000 products in batches of 1000
' In the given table
Public Sub Benchmark(TableName as String, InsertSeqGUID  as Boolean)
    Dim i As Integer
    For i = 1 To 1000
        Insert1000Products TableName, InsertSeqGUID 
    Next i
End Sub

' Insert 1000 products in a table
Public Sub Insert1000Products(TableName as String, InsertSeqGUID as boolean)
    Dim i As Long
    Dim db As DAO.Database
    Dim rs As DAO.Recordset
    Dim ws As DAO.Workspace
    Dim starttime As Long
    Dim timespan As Long
    
    Set ws = DBEngine.Workspaces(0)
    DoEvents
    starttime = GetClock ' Get the current time in ms
    ws.BeginTrans
    Set db = CurrentDb
    Set rs = db.OpenRecordset(TableName, dbOpenDynaset, dbAppendOnly)
    With rs
        For i = 1 To 1000
            .AddNew
                If InsertSeqGUID Then !ID = "{guid {" & CreateStringUUIDSeq() & "}"
                !SKU = "PROD" & i
                !Description = "Product number " & i
            .Update
        Next i
    End With
    ws.CommitTrans
    rs.Close
    timespan = GetClock() - CDbl(starttime)
    Set rs = Nothing
    Set db = Nothing
    ' Print Elapsed time in milliseconds
    Debug.Print timespan
    DoEvents
End Sub
</textarea></p>

<p>We call this code to perform inserts on each of our Access tables:</p>

<ul>
<li>ProductINT table: we just insert data in the <code>ProductINT</code> table, letting Access create autonumber IDs.</li>
<li>ProductINTRandom table: we just insert data in the <code>ProductINTRandom</code> table, letting Access create random autonumber IDs.</li>
<li>ProductGUIDRandom table: we let Access create the Random GUID for the primary key.</li>
<li>ProductGUIDSequential: we use the Windows API to create a sequential ID that we insert ourselves.</li>
</ul>

<h3>Test results</h3>

<p>Without further ado, here are the raw results, showing the number of inserted record per second that we achieve for each test over the growing size of the database (here are only shown tests comapring Sequantial GUID and Autoincrement on SQL Server and Access, see next sections for the other results):</p>

<p><img src="/wp-content/uploads/2009/04/chart04.png" alt="Inserts per second" /></p>

<p>What we clearly see here is that performance when using autoincrement and Sequential GUID stays pretty much constant over the whole test.<br />
That&#8217;s good new as it means that using Sequential GUIDs do not degrade performance over time.</p>

<p>As a side note, in this particular test, Access offers much better raw performance than SQL Server. In more complex scenarios it&#8217;s very likely that Access&#8217; performance would degrade more than SQL Server, but it&#8217;s nice to see that Access isn&#8217;t a sloth.</p>

<h3>Using Sequential GUID vs Autoincrement in Access</h3>

<p>The results show that we do take a performance hit of about 30% when inserting Sequential GUID vs just using autonumbers.<br />
We&#8217;re still getting good results, but that&#8217;s something to keep in mind.</p>

<p>In terms of CPU consumption, here is what we get:</p>

<p><img src="/wp-content/uploads/2009/04/CPUAccess.png" alt="CPU load Access" /></p>

<p>Random PK, whether they are simple integer or GUID do consume substantially more CPU resources.</p>

<h3>Using Sequential GUID vs Identity in SQL Server</h3>

<p>Out-of-the box, SQL Server performs quite well and there is not much difference whether you&#8217;re using Sequential GUIDs or autoincrement PK.</p>

<p>There is however a surprising result: using Sequential GUIDs is actually slightly <em>faster</em> than using autoincrement!</p>

<p>There is obviously an explanation for this but I&#8217;m not sure what it is so please enlighten me :-)</p>

<p>CPU Consumption:</p>

<p><img src="/wp-content/uploads/2009/04/CPUSQLServer.png" alt="CPU load SQL Server" /></p>

<h3>Using Random GUID vs Sequential GUID vs Random Autonumber in Access</h3>

<p>So, what is the impact of choosing a Sequential GUID as opposed to letting Access create its own random GUIDs?</p>

<p><img src="/wp-content/uploads/2009/04/chart05.png" alt="Inserts per second Random GUID vs Sequential GUID in Access" /></p>

<p>It&#8217;s clear that random GUIDs have a substantial performance impact: their randomness basically messes up indexing, resulting in the database engine having to do a lot more work to re-index the data on each insertion.<br />
The good thing is that this degradation is pretty logarithmic so while it degrades over time, the overall performance remains pretty decent.<br />
While GUIDs are larger than Random Integers (16 bytes vs 4 bytes) the actual performance of inserting records whose PK is a random integrer is actually worse than random GUID&#8230;</p>

<h3>Provisional conclusions</h3>

<p>Here we&#8217;ve check the baseline for our performance tests.
In the next article, we&#8217;ll look exclusively at the performance of inserting data from a remote Access 2007 front end using our VBA code.</p>

<p>Having this baseline will allow us to check the performance overhead of using ODBC and letting Jet/ACE manage the dialogue with the SQL Server backend.</p>

<p>Feel free to leave your comments below, especially if you have any resources or information that would be useful.</p>

<h3>Updates</h3>

<ul>
<li>16APR2009: added test of random autonumber as PK in Access.</li>
<li>13APR2009: Original Article</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2009/access-vs-sql-server-some-stats-part-1/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Sysadmin: SQL server performance madness</title>
		<link>http://blog.nkadesign.com/2009/sysadmin-sql-server-performance-madness/</link>
		<comments>http://blog.nkadesign.com/2009/sysadmin-sql-server-performance-madness/#comments</comments>
		<pubDate>Sun, 12 Apr 2009 11:25:56 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Hardware]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=550</guid>
		<description><![CDATA[I&#8217;ve just lost 2 days going completely bananas over a performance issue that I could not explain. I&#8217;ve got this Dell R300 rack server that runs Windows Server 2008 that I dedicate to running IIS and SQL Server 2008, mostly for development purposes. In my previous blog entry, I was trying some benchmark to compare [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/windows.png" alt="Technology" title="Technology" align="left" width="64" height="60" hspace="5" vspace="5" border="0" />
I&#8217;ve just lost 2 days going completely bananas over a performance issue that I could not explain.</p>

<p>I&#8217;ve got this <a href="http://www.dell.com/content/products/productdetails.aspx/pedge_r300?c=us&amp;cs=555&amp;l=en&amp;s=biz">Dell R300</a> rack server that runs Windows Server 2008 that I dedicate to running IIS and SQL Server 2008, mostly for development purposes.</p>

<p><img src="/wp-content/uploads/2009/04/pedge_r300_overview1.jpg" alt="Dell PowerEdge R300 Rack servers" /></p>

<p>In my <a href="/2009/access-vs-sql-server-some-stats-part-1/">previous blog entry</a>, I was trying some benchmark to compare the performance of Access and SQL Server using INT and GUID and getting some strange results.
<!--
To get a more accurate baseline to explain the results I was getting from the server, I've tried this little snippet of SQL (the test database is simply a table with a IDENTIY column `ID`, and two text columns `SKU`, and `Description`).  
<textarea name="code" class="sql:nogutter" cols="60" rows="10">
DECLARE @tstart DATETIME2 = SYSDATETIME();
-- BEGIN TRAN
	DECLARE @a INT = 1;
	WHILE (@a <= 1000)
	BEGIN
		INSERT INTO Product (SKU,Description) 
		VALUES ('PROD' + CONVERT(CHAR,@a), 'Product number ' + CONVERT(CHAR,@a));
		SELECT @a = @a + 1;
	END;
-- COMMIT TRAN;
SELECT DATEDIFF(MILLISECOND, @tstart, SYSDATETIME()) AS timespan;
</textarea>

OK, so now for the really weird thing that was driving me crazy.

I have SQL Server 2008 Standard installed on 3 different machines: the server, my desktop and my Macbook Pro.
--></p>

<p>Here are the results I was getting from inserting large amounts of data in SQL Server:</p>

<table border=1>
<thead>
<tr>
  <th>Machine</th>
  <th>Operating System</th>
  <th align="center">Test without Transaction</th>
  <th align="center">Test with Transaction</th>
</tr>
</thead>
<tbody>
<tr>
  <td>MacbookPro</td>
  <td>Windows Server 2008 x64</td>
  <td align="center">324 ms</td>
  <td align="center">22 ms</td>
</tr>
<tr>
  <td>Desktop</td>
  <td>Windows XP</td>
  <td align="center">172 ms</td>
  <td align="center">47 ms</td>
</tr>
<tr>
<td>Server</td>
  <td>Windows Server 2008 x64</td>
  <td align="center"><font color="red">8635 ms!!</font></td>
  <td align="center">27 ms</td>
</tr>
</tbody>
</table>

<p>On the server, not using transactions makes the query run more than 8 seconds, <strong>at least an order of magnitude slower than it should!</strong></p>

<p>I initially thought there was something wrong with my server setup but since I couldn&#8217;t find anything, I just spend the day re-installing the OS and SQL server, applying all patches and updates so the server is basically brand new, nothing else on the box, no other services, basically all the power is left for SQL Server&#8230;</p>

<h3>Despair</h3>

<p>When I saw the results for the first time after spending my Easter Sunday rebuilding the machine I felt dread and despair.<br />
The gods were being unfair, it had to be a hardware issue and it had to be related to either memory or hard disk, although I couldn&#8217;t understand really why but these were the only things that I could see have such an impact on performance.</p>

<p>I started to look in the hardware settings:</p>

<p><img src="/wp-content/uploads/2009/04/screen1.png" alt="Device Manager" /></p>

<p>And then I noticed this in the Policies tab of the <em>Disk Device Properties</em> :</p>

<p><img src="/wp-content/uploads/2009/04/screen2.png" alt="DISK Device Properties" /></p>

<p>Just for the <a href="http://encyclopediadramatica.com/Lulz">lulz</a> of it, I ticked the box, close the properties</p>

<p><img src="/wp-content/uploads/2009/04/screen3.png" alt="Enable advanced performance" /></p>

<p>And then tried my query again:</p>

<table border=1>
<thead>
<tr>
  <th>Machine</th>
  <th>Operating System</th>
  <th align="center">Test without Transaction</th>
  <th align="center">Test with Transaction</th>
</tr>
</thead>
<tbody>
<td>Server</td>
  <td>Windows Server 2008 x64</td>
  <td align="center"><font color="red">254 ms!!</font></td>
  <td align="center">27 ms</td>
</tr>
</tbody>
</table>

<p>A <strong>nearly 35 fold increase in performance!</strong></p>

<h3>Moral of the story</h3>

<p>If you are getting strange and inconsistent performance results from SQL Server, make sure you check that <em>Enable advanced performance</em> option.<br />
Even if you&#8217;re not getting strange results, you may not be aware of the issue, only that some operations may be much slower than they should.</p>

<p>Before taking your machine apart and re-installing everything on it, check your hardware settings, there may be options made available by the manufacturer or the OS that you&#8217;re not aware of&#8230;</p>

<p>Lesson learnt.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2009/sysadmin-sql-server-performance-madness/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Access: building &#8216;upsizable&#8217; applications.</title>
		<link>http://blog.nkadesign.com/2009/access-building-upsizable-applications/</link>
		<comments>http://blog.nkadesign.com/2009/access-building-upsizable-applications/#comments</comments>
		<pubDate>Wed, 01 Apr 2009 03:39:45 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[MSAccess]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=433</guid>
		<description><![CDATA[When you start building an Access application, it&#8217;s tempting to just think about today&#8217;s problem and not worry at all about the future. If your application is successful, people will want more out of it and, over time, you&#8217;ll be faced with the task of moving the back-end database to a more robust system like [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/access.png" alt="Microsoft Access" title="Microsoft Access" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />
When you start building an Access application, it&#8217;s tempting to just think about today&#8217;s problem and not worry at all about the future.<br />
If your application is successful, people will want more out of it and, over time, you&#8217;ll be faced with the task of moving the back-end database to a more robust system like SQL Server.</p>

<p>While there are <a href="/2009/ms-access-upsizing-to-sql-server-2008/">tools like SSMA that can help you move an Access database to SQL Server</a>, <strong>a lot of the problems you&#8217;ll encounter can be solved before you even have to think about upsizing</strong>.<br />
Abiding by a few simple rules will cost you nothing when creating your Access application but will save you a lot of headache if -when- the time comes to upsize.</p>

<p>So here are a few things to keep in mind.</p>

<h3>Naming conventions</h3>

<p>Access is pretty liberal about naming conventions and it will let you freely name your tables, columns indexes and queries.
When these get moved to another database you&#8217;ll most probably be faced with having to rename them.<br />
In some cases, you could actually create subtle bugs because something that used to work fine in Access may be tolerated in the new database but be interpreted differently.</p>

<ul>
<li><p><strong>Do not use spaces or special characters</strong> in your data object names.<br />
Stick to characters in the range <code>A</code> through <code>Z</code>,  <code>0</code> to <code>9</code> with maybe underscores <code>_</code> somewhere in between (but not at the start or the end).<br />
Also try to respect casing wherever you reference this name (especially for databases like MySQL which are case-sensitive if the hosted on a Linux platform for instance).<br />
eg:<br />
<code>Customer Order Lines (archive)</code> should be  <code>CustomerOrderLines_Archive</code>.<br />
<code>Query for last Year's Turnover</code> should be <code>QueryLastYearTurnover</code>.<br />
Index <code>ID+OrderDate</code> should become instead <code>ID_OrderDate</code>.</p></li>
<li><p><strong>Do not use keywords that are reserved</strong> or might mean something else whether they are SQL keywords or functions names:<br />
A column called <code>Date</code> could be renamed <code>PurchaseDate</code> for instance.<br />
Similarly, <code>OrderBy</code> could be renamed <code>SortBy</code> or <code>PurchaseBy</code> instead, depending on the context of <em>Order</em>.<br />
Failing to do so may not generate errors but could result in weird and difficult to debug behaviour.</p></li>
<li><p><strong>Do not prefix tables with <code>Sys</code>, <code>USys</code>, <code>MSys</code> or a tilde <code>~</code>.</strong><br />
Access has its own internal system tables starting with these prefixes and it&#8217;s best to stay away from these.<br />
When a table is deleted, Access will often keep it around temporarily and it will have a tilde as its prefix.</p></li>
<li><p><strong>Do not prefix Queries with a tilde <code>~</code>.</strong><br />
Access use the tilde to prefix the hidden queries kept internally as recordsource for controls and forms.</p></li>
</ul>

<h3>Database design</h3>

<ul>
<li><p><strong>Always use Primary keys.</strong><br />
Always have a non-null primary key column in every table.<br />
All my tables have an autonumber column called <code>ID</code>.  Using an automatically generated column ID guarantees that each record in a table can be uniquely identified.<br />
It&#8217;s a painless way to ensure a minimum level of data integrity.</p></li>
<li><p><strong>Do not use complex multivalue columns.</strong><br />
Access 2007 introduced <a href="http://office.microsoft.com/en-us/access/HA012337221033.aspx">complex columns that can record multiple values</a>.<br />
They are in fact fields that return whole recordset objects instead of simple scalar values.  Of course, this being an Access 2007 only feature, it&#8217;s not compatible with any other database.
Just don&#8217;t use it, however tempting and convenient it might be.<br />
Instead use a table to record Many-To-Many relationships between 2 tables or use a simple lookup to record lists of choices in a text field itself if you&#8217;re only dealing with a very limited range of multivalues that do not change.</p></li>
<li><p><strong>Do not use the Hyperlink data type.</strong><br />
Another Access exclusive that isn&#8217;t available in other databases.</p></li>
<li><p><strong>Be careful about field lookups.</strong><br />
When you create Table columns, Access allows you to define lookup values from other tables or lists of values.<br />
If you <em>manually</em> input a list of values to be presented to the user, these won&#8217;t get transferred when upsizing to SQL Server.<br />
To avoid having to maintain these lookup lists all over your app, you could create small tables for them and use them as lookup instead; that way you only need to maintain a single list of lookup values.</p></li>
<li><p><strong>Be careful about your dates.</strong><br />
Access date range is much larger than SQL Server.<br />
This has 2 side-effects:<br />
1) if your software has to deal with dates outside the range, you&#8217;ll end-up with errors.<br />
2) if your users are entering dates manually, they could have made mistakes when entering the year (like 09 instead of 2009).<br />
Ensure that user-entered dates are valid for your application.</p></li>
</ul>

<h3>VBA</h3>

<p>While most of your code will work fine, there are a few traps that will bomb your application or result in  weird errors:</p>

<ul>
<li><p><strong>Always explicitly specify options when opening recordsets or executing SQL.</strong><br />
With SQL Server, the <code>dbSeeChange</code> is mandatory whenever you open a recordset for update.<br />
I recommend using <code>dbFailOnError</code> as well as it will ensure that the changes are rolled back if an error occurs.
<textarea name="code" class="vb:nogutter">
Dim rs as DAO.RecordSet
' Open for read/write
set rs = db.OpenRecordSet("Stock", dbOpenDynaset, dbSeechanges + dbFailOnError)
' Open for read only
set rs = db.OpenRecordSet("Stock", dbOpenSnapshot)
' Direct SQL execution
CurrentDB.Execute "INSERT INTO ...",  dbSeeChanges + dbFailOnError
</textarea></p></li>
<li><p><strong>Get the new autonumbered ID <em>after</em> updating the record.</strong><br />
In Access, autonumbered fields are set as soon as the record is added even if it hasn&#8217;t been saved yet.<br />
That doesn&#8217;t work for SQL Server as autonumbered IDs are only visible after the records have been saved.
<textarea name="code" class="vb:nogutter">
' Works for Access tables only
' We can get the new autonumber ID as soon as the record is inserted
rs.AddNew
mynewid = rs!ID
...
rs.Update

' Works for ODBC and Access tables alike
' We get the new autonumber ID after the record has been updated
rs.AddNew
...
rs.Update
rs.Move 0, rs.LastModified
mynewid = rs!ID
</textarea></p></li>
<li><p><strong>Never rely on the type of your primary key.</strong><br />
This is more of a recommendation but if you use an autonumbered ID as your primary key, don&#8217;t rely in your code or you queries on the fact that it is a <em>long integer</em>.<br />
This can become important if you ever need to upsize to a replicated database and need to transform your number IDs into GUID.<br />
Just use a Variant instead.</p></li>
</ul>

<h3>Parting thoughts</h3>

<p>These simple rules will not solve all your problems but they will certainly reduce the number of issues you&#8217;ll be faced with when upsizing you Access application.<br />
Using a tool like <a href="/2009/ms-access-upsizing-to-sql-server-2008/">SSMA</a> to upsize will then be fairly painless.</p>

<p>If you have other recommendations, please don&#8217;t hesitate to leave them in the comments, I&#8217;ll regularly update this article to included them.</p>

<h3>References</h3>

<ul>
<li>You will find lots of other bits of wisdom on this page: <a href="http://www.granite.ab.ca/access/sqlserverupsizing.htm">My random thoughts on SQL Server Upsizing from Microsoft Access</a> by Tony, from Granite Consulting.</li>
<li>Martin Green&#8217;s Office tips has a series of <a href="http://www.fontstuff.com/siteindex.htm#access">articles on Access to SQL Server migration</a>.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2009/access-building-upsizable-applications/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MS Access: upsizing to SQL Server 2008</title>
		<link>http://blog.nkadesign.com/2009/ms-access-upsizing-to-sql-server-2008/</link>
		<comments>http://blog.nkadesign.com/2009/ms-access-upsizing-to-sql-server-2008/#comments</comments>
		<pubDate>Tue, 17 Mar 2009 07:00:36 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[MSAccess]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=285</guid>
		<description><![CDATA[I&#8217;m currently researching ways to move my main MS Access application from a simple local network client/backend setup to a global, multiple remote sites configuration using SQL Server. One of the challenges is to upsize the current MS Access 2007 backend database to SQL Server 2008. If you try it from Access itself using the [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/access.png" alt="Microsoft Access" title="Microsoft Access" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />
I&#8217;m currently researching ways to move my main MS Access application from a simple local network client/backend setup to a global, multiple remote sites configuration using SQL Server.</p>

<p>One of the challenges is to upsize the current MS Access 2007 backend database to SQL Server 2008.
If you try it from Access itself using the Upsizing Wizard, you may end up getting this error message:</p>

<blockquote>
  <p><em>The Upsizing Wizard only works with Microsoft SQL Server (Versions 6.50 SP5 or higher). Please log in to a SQL Server data source.</em></p>
  
  <p><img src="/wp-content/uploads/2009/01/UpsizingErrorsm.png" alt="The Upsizing Wizard only works with Microsoft SQL Server (Versions 6.50 SP5 or higher). Please log in to a SQL Server data source." /></p>
</blockquote>

<p>After spending some time fiddling around with SQL Server settings I couldn&#8217;t understand why I was still getting this error.<br />
Turns out that the upsizing wizard is apparently sensitive to the version of SQL Server you&#8217;re using and it doesn&#8217;t consider SQL Server v10 (2008) as being later than v6.50&#8230;</p>

<p>This issue is in fact a blessing.<br />
Microsoft provides a migration tool for upsizing MS Access database to SQL Server 2008 that&#8217;s orders of magnitude better than anything the basic wizard can do: the <a href="http://www.microsoft.com/sqlserver/en/us/product-info/migration-tool.aspx#Access">SQL Migration Assistant for Access, or SSMA</a>.</p>

<p><img src="/wp-content/uploads/2009/03/7282.migrate_2D00_from_2D00_access.png" alt="Migrate from Access to SQL Server" width="246" height="104" align="right" hspace="5" vspace="5" border="0"  />SSMA lets you take a bunch of Access databases and move the tables and queries you choose to SQL Server, automatically linking them in your original database if you want.<br />
It&#8217;s not just a one-off thing either: SSMA keeps track of the objects that where transferred and allows you to synchronise both schema and data as often as you need.</p>

<p>So here you are: do <strong>not</strong> use the basic <em>MS Access Upsizing Wizard</em>, download and use SSMA instead.</p>

<h3>Strange COM Error</h3>

<p>While SSMA works perfectly fine on my Windows 2008 x64 laptop, on my main Windows XP desktop it throws an exception when trying to load an Access database:</p>

<blockquote>
  <p><em>Unable to cast COM object of type &#8216;Microsoft.Office.Interop.Access.Dao.DBEngineClass&#8217; to interface type &#8216;Microsoft.Office.Interop.Access.Dao._DBEngine&#8217;<br />
  &#8230; {00000021-0000-0010-8000-00AA006D2EA4}&#8230;</em></p>
</blockquote>

<p>It was a COM error saying that the library for DAO couldn&#8217;t be loaded.</p>

<p><a title="Disabling Filesystem Compression" style="border:0;" href="/wp-content/uploads/2009/01/sshot-568.png" rel="lightbox"><img title="Disabling Filesystem Compression" src="/wp-content/uploads/2009/01/sshot-568sm.png" style="float:right;margin-left:10px;margin-bottom:5px;" /></a>
I couldn&#8217;t find any relevant information on the web.<br />
After a while, I had a look at the DAO driver in<br />
<code>C:\Program Files\Common Files\Microsoft Shared\DAO\dao360.dll</code><br />
and I noticed that the filename was in blue: that reminded me that I had set compression on the filesystem.</p>

<p>I disabled compression for the file and, magically, SSMA worked again&#8230;</p>

<p>Moral of the story: be careful about compressing your filesystem, some registered libraries and system files may work in unpredictable ways&#8230;</p>

<h3>References</h3>

<ul>
<li><a href="http://blogs.msdn.com/b/ssma/">SQL Server Migration Assistant Team Blog</a></li>
<li><a href="http://www.microsoft.com/sqlserver/en/us/product-info/migration-tool.aspx#Access">SQL Server Migration Assistant for Access</a> main page.</li>
<li><a href="http://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;id=28763">SQL Server Migration Assistant download</a>. Note that you will have to register to get a license file that you need to save on your PC before you can use this free tool.</li>
<li><a href="http://www.microsoft.com/communities/newsgroups/en-us/default.aspx?dg=microsoft.public.access.sqlupsizing&amp;tid=a1198438-f914-4710-91ca-440da168dc5d&amp;cat=&amp;lang=&amp;cr=&amp;sloc=&amp;p=1">&#8220;Access 2007 Upsizing to SQL Server 2008 Express in SQL Upsizing&#8221;</a> discussion on Microsoft groups.</li>
<li><a href="http://support.microsoft.com/kb/838594">&#8220;KB838594: Error message when you try to upsize your Access database by using the Upsizing Wizard&#8221;</a> is not the problem here, but some may find the reference useful if you&#8217;re trying to upsize your MS Access database to a SQL Server database on a network.</li>
<li><a href="http://www.granite.ab.ca/access/sqlserverupsizing.htm">My random thoughts on SQL Server Upsizing from Microsoft Access</a> from Tony&#8217;s Access MVP website, and his <a href="http://www.granite.ab.ca/access/sqlserverupsizinglinks.htm">list of links to other resources</a>.</li>
</ul>

<h3>Updates</h3>

<ul>
<li>23FEB2012: Added link to SSMA Team blog and updated download link to current version (5.2)</li>
<li>17MAR2009: Added section on the strange COM error.</li>
<li>14MAR2009: Added links to Tony&#8217;s Access MVP website.</li>
<li>05JAN2009: Original publication.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2009/ms-access-upsizing-to-sql-server-2008/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
		<item>
		<title>Technical ebooks: some publishers don&#8217;t get it</title>
		<link>http://blog.nkadesign.com/2009/technical-ebooks-some-publishers-dont-get-it/</link>
		<comments>http://blog.nkadesign.com/2009/technical-ebooks-some-publishers-dont-get-it/#comments</comments>
		<pubDate>Wed, 11 Mar 2009 03:47:43 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Books]]></category>
		<category><![CDATA[Business]]></category>
		<category><![CDATA[Reviews]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=435</guid>
		<description><![CDATA[I like buying technical books. Unfortunately, here in Hong Kong, we have less choice: there are not that many technical bookstores that cater for English-language books and the selection is rather limited. So whenever a book isn&#8217;t available here, I buy it online as a PDF. It&#8217;s cheaper, saves postage and I can keep them [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/stupidity02.png" alt="Stupid things" title="Linux" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />I like buying technical books.<br />
Unfortunately, here in Hong Kong, we have less choice: there are not that many technical bookstores that cater for English-language books and the selection is rather limited.</p>

<p>So whenever a book isn&#8217;t available here, I buy it online as a PDF.<br />
It&#8217;s cheaper, saves postage and I can keep them handy on my desktop computer at work and my laptop.</p>

<p>I love <a href="http://safaribooksonline.com/">Safari</a> and being able to access such a large library of books online in such a flexible way is great, but if you&#8217;re not in the US, the experience is not always that pleasant, with the site sometimes becoming a bit too slow for comfort.</p>

<p><center>
<img src="/wp-content/uploads/2009/03/graffititek-bookshelf2.jpg" alt="GraphitiTek by Charles Kalpakian" />
</center></p>

<p>The publishers I regularly buy ebooks from are <a href="http://oreilly.com/store/">O&#8217;Reilly</a>, when they make the PDF available, and <a href="http://apress.com/">Apress</a>.</p>

<p>O&#8217;Reilly&#8217;s PDF may have your subscribtion details embedded at the bottom of each page.<br />
It&#8217;s perfectly reasonable and doesn&#8217;t ruin the experience: I can still search, copy snippets to the clipboard and print the book if I need to keep an annotated copy.</p>

<p>Apress encrypt the PDF with your account email. Again, that&#8217;s fine by me, they don&#8217;t prevent me from using the book and it&#8217;s not a great annoyance to have to type the password to unlock the book.</p>

<p>Now comes <a href="http://www.wrox.com/WileyCDA/">Wrox</a> (Wiley): they publish fine books and even have some available as ebooks.<br />
The biggest issue I have though is that they assume that people who buy their books are all potential criminals:</p>

<ul>
<li>The book is <a href="http://www.wrox.com/WileyCDA/WroxTitle/Professional-IIS-7.productCd-0470097825.html">as expensive in paper</a> as it is in <a href="http://www.wrox.com/WileyCDA/WroxTitle/Professional-IIS-7.productCd-0470289767.html">ebook format</a>. That can&#8217;t be right: ebooks have zero reproduction cost while paper books have huge material costs.</li>
<li>The ebook version needs to be registered with <a href="http://www.adobe.com/products/digitaleditions/">Adobe Digital Editions</a> that locks it to a particular machine.</li>
<li>You&#8217;re only <a href="http://www.wrox.com/WileyCDA/WroxTitle/Professional-IIS-7.productCd-0470289767,descCd-ebook.html">allowed</a> to download the ebook to 4 different PCs and you&#8217;ve got 2 weeks to do so.<br />
This seems fair, but it&#8217;s not: if I change OS or PC, I&#8217;ve already burnt 2 licenses.</li>
<li>You can&#8217;t copy/paste more than a page at a time, up to 10 pages every week&#8230; that&#8217;s just a bit silly.</li>
<li>Can&#8217;t copy any of the artwork, diagrams, etc.</li>
<li>Doesn&#8217;t say anything about what happens if Adobe drops their particular DRM software or if I need to use the book on the next laptop I&#8217;ll buy a year from now.</li>
<li>Adobe Digital Edition only supports <a href="http://www.adobe.com/products/digitaleditions/systemreqs/">Windows and Mac and a Sony reader</a>. So using Linux (even though <a href="http://www.wrox.com/WileyCDA/Section/id-WROX_SEARCH_RESULT.html?queryText=linux&amp;field=keyword">Wrox plublishes books about it</a>) or a Kindle or any other mobile device is out of the question.</li>
</ul>

<p>So the net advantage of buying an eBook from Wrox (Wiley) is: your guess is as good as mine.</p>

<p>Yeah, you can <a href="http://www.wrox.com/WileyCDA/WroxTitle/productCd-0470097825,descCd-buy_chapters.html">buy each chapter as a PDF</a>: great value, at US$4.99 per chapter, the book is costing you nearly US$100. You can get the fully printed version for half the cost&#8230;<br />
Still, I&#8217;ll concede that being able to download a particular chapter can be useful.</p>

<p>The bottom line is: if your book gets printed, it&#8217;s going to be pirated and distributed for free in ebook format within a couple of weeks of being published.<br />
While thinking they are protecting their copyright, Wiley is in fact punishing people who <strong>buy</strong> their books.</p>

<p>I&#8217;ll stick with <a href="http://apress.com/">Apress</a> and <a href="http://oreilly.com/store/">O&#8217;Reilly</a> I think. At least I don&#8217;t feel treated like a thief.</p>

<hr />

<p><strong>12FEB2010 Update</strong>: <a href="http://p2p.wrox.com/content/blogs/jminatel/wrox-pdf-ebooks-drm-free">Wrox is now trying DRM-free PDF ebooks</a>. We can only applaud this decision. While the offering is still limited at the moment, most or all of their books will eventually be available DRM-free.</p>

<hr />

<p><small>Bookshelf by <a href="http://www.hellokarl.com/">Charles Kalpakian</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2009/technical-ebooks-some-publishers-dont-get-it/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Sysadmin: Multiple ISP firewall &#8211; The setup</title>
		<link>http://blog.nkadesign.com/2009/sysadmin-multiple-isp-firewall-servers-and-redundancy/</link>
		<comments>http://blog.nkadesign.com/2009/sysadmin-multiple-isp-firewall-servers-and-redundancy/#comments</comments>
		<pubDate>Wed, 04 Feb 2009 07:22:24 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=336</guid>
		<description><![CDATA[After suffering broadband trouble for the past 9 months, including interruptions that lasted a few days, I decided to get an additional line installed by a different ISP. I could have bought one of these multi-WAN devices but decided against it for a couple of reasons: I like a challenge and I wanted to achieve [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/linux.png" alt="Linux" title="Linux" align="left" width="54" height="64" hspace="5" vspace="5" border="0" />
After suffering broadband trouble for the past 9 months, including interruptions that lasted a few days, I decided to get an additional line installed by a different ISP.<br />
I could have bought one of these multi-WAN devices but decided against it for a couple of reasons: I like a challenge and I wanted to achieve a particular setup that I wasn&#8217;t sure could be answered by off-the-shelf products (for a reasonable price that is).</p>

<p>This long article is fairly detailed but if your setup is similar it should be enough to get you going quickly.</p>

<ul>
<li><a href="#basicsetup">The basic setup</a></li>
<li><a href="#objectives">Objectives</a></li>
<li><a href="#technologies">Technologies</a></li>
<li><a href="#thingstoknow">Things to know</a></li>
<li><a href="#thingstoread">Things to read</a></li>
<li><a href="#installingshorewall">Installing shorewall</a></li>
<li><a href="#preparingthesystem">Preparing the system</a></li>
<li><a href="#shorewallconfiguration">Shorewall configuration</a></li>
<li><a href="#installingourfirewallrules">Installing our firewall rules</a></li>
<li><a href="#dns">DNS</a></li>
<li><a href="#initialconclusions">Initial conclusions</a></li>
<li><a href="#references">References</a></li>
</ul>

<h3 id="basicsetup">The basic setup</h3>

<p>Without further ado, this is the network configuration:</p>

<p><img src="/wp-content/uploads/2009/02/20090203NetworkDiagram.png" alt="Network Diagram" /></p>

<h4>Notable things</h4>

<p>We have 2 broadband connections:</p>

<ul>
<li><strong>CYBR</strong>, a standard DSL line with a fixed IP <code>111.99.88.77</code> allocated through PPPoE.</li>
<li><strong>HKBN</strong>, a standard 100Mbps line with a fixed IP <code>30.40.50.62</code>.</li>
</ul>

<p>The network is split into different <em>zones</em>:</p>

<ul>
<li>the <strong>Internet zone</strong>, connected to our Firewall through interfaces <code>eth0</code> (<code>ppp0</code>) and <code>eth1</code>.</li>
<li>a <strong>Firewall zone</strong>, delimited by the firewall system itself</li>
<li>a <strong><a href="http://en.wikipedia.org/wiki/DMZ_(computing)">DMZ</a> zone</strong> connected through interface <code>eth2</code> for the servers we want to make visible from the Internet.<br />
The DMZ has its own private subnet delimited by <code>192.168.254.0/255.255.255.0</code>.</li>
<li>a <strong>LAN zone</strong> connected through interface <code>eth3</code> so local computers can access the Internet and be protected from it.<br />
The DMZ has its own private subnet delimited by <code>192.168.0.0/255.255.255.0</code>.  </li>
</ul>

<h3 id="objectives">Objectives</h3>

<p>What we want from our setup:</p>

<ol>
<li>our <em>firewall</em> protects our DMZ and LAN from unwanted access.</li>
<li>our <em>win</em> server can host websites or other services.</li>
<li>our <em>linux</em> server can handle receiving and sending email or other services.</li>
<li>our <em>firewall</em> can handle incoming traffic from either ISP.</li>
<li>our <em>firewall</em> can load-balance local outgoing traffic across both ISP.</li>
<li>If one line fails, <em>incoming</em> traffic switches to the other line.</li>
<li>If one line fails, <em>outgoing</em> traffic switches to the other line.</li>
<li>Eventually, we want both the <em>linux</em> and <em>win</em> servers to be able to host different websites and we want the firewall to send incoming requests to the right server.</li>
</ol>

<p>In this first article, I&#8217;ll present the setup for items 1-5.<br />
The remaining topics will be the subject of subsequent articles of their own.</p>

<h3 id="technologies">Technologies</h3>

<p>The firewall is our primary subject. What is being discussed here is pretty much distribution-independent and should work on all flavours of Linux.</p>

<h4>OS on the firewall system</h4>

<p>I chose <a href="http://www.centos.org/">CentOS</a> on the firewall.<br />
Being an almost byte-for-byte identical copy of <a href="http://www.redhat.com/rhel/">RedHat Enterprise Linux</a>, all configuration will be identical on RedHat and its derivatives such as Fedora.</p>

<h4>Firewall software, first try</h4>

<p>When my firewall needs are simpler, I use the <a href="http://tldp.org/HOWTO/IP-Masquerade-HOWTO/stronger-firewall-examples.html">Stronger IP Firewall Ruleset</a> from the <a href="http://tldp.org/HOWTO/IP-Masquerade-HOWTO/index.html">Linux IP Masquerade HOWTO</a>.<br />
I started to modify the script to adapt it to my new Multi-ISP setup but things got complicated once I needed to debug routing tables.<br />
I got it 80% of the way but tracing network connections and packet routing is complicated and time-consuming.<br />
After a couple of days of peering into log files and <a href="http://www.wireshark.org/">wireshark</a> capture screens, I gave up manual configuration and decided to go with something else.</p>

<h4>Firewall software, final</h4>

<p>The product I chose in the end is <a href="http://shorewall.net/">shorewall</a>: it&#8217;s a very flexible firewall system that create the necessary iptable rules and configure most of the routing needs to properly handle complex network setup.<br />
Shorewall is Open Source, very stable, has been out for a long time, is actively maintained and has lots of excellent documentation and examples.</p>

<h3 id="thingstoknow">Things to know</h3>

<p>Before we get into the meat of the article, you should brush up on the following topics:</p>

<ul>
<li>You have some knowledge of Linux system administration, know how to configure network connections, know how to enable/disable/stop/start  services, able to edit config files.</li>
<li>Networking: you should know what a netmask is, what a gateway is, what a subnet is and have a passing understanding of IP classes, IP notation, what ports are for, what&#8217;s the difference between the tcp, udp, icmp protocols, what Dynamic Port Forwarding (DNAT) is, what Network Address Translation (NAT) is, what <em>masquerading</em> means.</li>
<li>Some basic understanding of DNS and local host name resolving (using <code>host.conf</code> and <code>resolv.conf</code>)</li>
<li>Some basic knowledge of what <em>routing</em> is for and how it works.</li>
<li>Some knowledge of how the linux kernel handles network packets (NetFilter, basics of iptables).</li>
</ul>

<p>You don&#8217;t need to be a specialist in any of these areas but any knowledge helps.<br />
I&#8217;m far from being well versed into Netfilter and routing, it&#8217;s not often that I have to deal directly with these topics, but brushing up on these topics helped.</p>

<h4 id="thingstoread">Things to read</h4>

<p>Shorewall has very extensive documentation. So much so that it can be a bit daunting, not knowing where to start.<br />
I found the following documents helpful to get me started:</p>

<ul>
<li><a href="http://shorewall.net/shorewall_setup_guide.htm">Setup Guide for multiple interfaces</a>.</li>
<li><a href="http://shorewall.net/Shorewall_and_Routing.html">Routing article</a></li>
<li><a href="http://shorewall.net/MultiISP.html">Guide for handling Multi-ISP</a></li>
</ul>

<h3 id="installingshorewall">Installing shorewall</h3>

<p>Go to the download site list [http://shorewall.net/download.htm#Sites]  and download the most appropriate binary package for your distribution.</p>

<p>If you get RPMs for RedHat systems, you only need to install (<code>rpm -ivh</code>) the following packages:</p>

<pre><code>shorewall-4.X.X-X.noarch.rpm
shorewall-perl-4.X.X-X.noarch.rpm 
</code></pre>

<p>If you install from source, only download, compile and install the <em>common</em>, <em>doc</em> and <em>perl</em> packages.</p>

<h3 id="preparingthesystem">Preparing the system</h3>

<p>For shorewall to properly handle both our firewall and packet routing needs, we need to make sure that the other parts of the system are not interfering with it.</p>

<h4>Internet lines</h4>

<p>Make sure that your multiple internet lines are properly working on their own!</p>

<h4>Disable routing</h4>

<ul>
<li>Make sure that you don&#8217;t define a <code>GATEWAY</code> in the configuration of your network interfaces (in <code>/etc/sysconfig/network-scripts/ifcfg-XXX</code>) .</li>
<li>If you use an (A)DSL connection, also set <code>DEFROUTE=no</code> if its <code>ifcfg-XXX</code> file as well.</li>
<li>Remove the <code>GATEWAY</code> from the <code>/etc/sysconfig/network</code> file if there is one.</li>
<li>Edit your <code>/etc/sysctl.conf</code> file and set <code>net.ipv4.conf.default.rp_filter = 0</code>.</li>
</ul>

<h4>Disable firewall</h4>

<p>Disable the current firewall, for instance using the <code>system-config-securitylevel</code> helper tool.<br />
Be careful if you&#8217;re directly connected to the Internet, you will be left without protection!<br />
You can actually wait until shorewall is properly configured to disable the firewall.</p>

<h3 id="shorewallconfiguration">Shorewall configuration</h3>

<p>Shorewall uses a set of simple configuration files, all located under <code>/etc/shorewall/</code>.
For exact detail of each configuration files, have a look at the list of <a href="http://shorewall.net/Manpages.html">man pages</a>.</p>

<h4>Zones</h4>

<p><code>zones</code> are probably the simplest configuration file.<br />
Details in the <a href="http://shorewall.net/manpages/shorewall-zones.html">zones man page</a>.
Here we just name the various zones we want our firewall to handle:</p>

<pre><code>################################################################
#ZONE   TYPE          OPTIONS       IN                  OUT
#                                   OPTIONS             OPTIONS
fw      firewall
net     ipv4
loc     ipv4
dmz     ipv4
</code></pre>

<p>This just reflects our setup as highlighted in the diagram above.</p>

<p>Note that the <code>fw</code> zone is often referred to as the  <code>$FW</code> variable instead in various configuration files.</p>

<h4>Interfaces</h4>

<p>Here we list all the network interfaces connected to our firewall and for which zone they apply.<br />
Details in the <a href="http://shorewall.net/manpages/shorewall-interfaces.html">interfaces man page</a>.</p>

<pre><code>################################################################
#ZONE   INTERFACE       BROADCAST       OPTIONS
net     ppp0            detect
net     eth1            detect
dmz     eth2            detect
loc     eth3            detect
</code></pre>

<p>Note that for our <code>net</code> zone, we list the 2 interfaces connected to our ISPs.<br />
If you&#8217;re using PPPoE to connect, don;t use the interface name <code>eth0</code> but use <code>ppp0</code> instead.</p>

<h4>Policy</h4>

<p>The <code>policy</code> file tells shorewall which default actions should be taken when traffic is moving from one zone to another.<br />
These default actions are taken if no other special action was specified in other configuration files.<br />
View the <code>policy</code> file as a list of default actions for the firewall.<br />
Details about this configuration file as in its <a href="http://shorewall.net/manpages/shorewall-policy.html">man page</a>.</p>

<pre><code>################################################################
#SOURCE DEST    POLICY          LOG     LIMIT:      CONNLIMIT:
#                               LEVEL   BURST       MASK
net     net     DROP            info
loc     net     ACCEPT
dmz     net     ACCEPT
loc     dmz     ACCEPT
loc     $FW     ACCEPT
dmz     $FW     ACCEPT
$FW     net     ACCEPT
dmz     loc     DROP            info
net     all     DROP            info
all     all     DROP            info
</code></pre>

<p>Traffic from one zone to another needs to be explicitely <code>ACCEPTed</code>, <code>REJECTed</code> or <code>DROPped</code>.<br />
For instance, <code>loc net ACCEPT</code> means that we allow all traffic from our local LAN to the Internet, while <code>net all DROP</code> means we don&#8217;t allow incoming traffic from the internet to anyone (remember this is the default action, in most cases we will override this for specific types of traffic in the <code>rules</code> file).<br />
When we set the default action to <code>DROP</code>, we can tell shorewall to keep a trace of the details in the <code>/var/log/messages</code> log.</p>

<h4>Providers</h4>

<p>The providers file is generally only used in a multi-ISP environment.<br />
Here we define how we want to <em>mark</em> packets originating from one ISP with a unique ID so we can tell the kernel to route these packets to the right interface.<br />
Not doing this would get packets received from one interface to be routed to the default gateway instead.<br />
The details of this configuration file are explained in the <a href="http://shorewall.net/manpages/shorewall-providers.html">providers man page</a> for it.</p>

<pre><code>#############################################################################
#NAME NUMBER MARK DUPLICATE INTERFACE GATEWAY      OPTIONS          COPY
CYBR  1      0x1  main      ppp0      -            track,balance=1  eth2,eth3
HKBN  2      0x2  main      eth1      30.40.50.61  track,balance=5  eth2,eth3
</code></pre>

<p>Note that the <code>DUPLICATE</code> columns tells shorewall that it should make a copy of the main default routing table for this particular routing table (called <code>CYBR</code> or <code>HKBN</code> depending on which ISP we refer to).<br />
Packets are marked with number 0&#215;1 or 0&#215;2 so we can distinguish them during their travel through the system.<br />
For PPPoE connections, don&#8217;t specify a <code>GATEWAY</code> since it&#8217;s most likely that your ISP didn&#8217;t give you one.</p>

<p>The most interesting part of this file are the <code>OPTIONS</code>: <code>track</code> means that we want the packets to be tracked as they travel through the system; <code>balance</code> tells the kernel that we want traffic coming out to be spread over both interfaces.<br />
Additionally, we want HKBN to receive more or less 5 times more traffic than CYBR (note that this has no effect on reply packets).</p>

<p>The <code>COPY</code> columns will ensure that the routing tables created for CYBR and HKBN are copied for each internal interface, so our <code>eth2</code> and <code>eth3</code> interfaces know how to route packets to the right ISP.</p>

<h4>Route Rules</h4>

<p>For our purpsose, the <code>route_rules</code> file only describes how traffic should be routed through one or the other ISP we set up in <code>/etc/shorewall/providers</code>.<br />
Details are in the <a href="http://shorewall.net/manpages/shorewall-route_rules.html">route_rules file man page</a>.</p>

<pre><code>#####################################################################
#SOURCE             DEST               PROVIDER        PRIORITY
ppp0                -                  CYBR            1000
eth1                -                  HKBN            1000
</code></pre>

<p>Here we simply say that all traffic through the <code>CYBR</code> table should be sent to <code>ppp0</code>.<br />
The <code>PRIORITY</code> is an ordering number that tell shorewall to consider this routing rule before it marks the packets. Since we know the packets originated from <code>ppp0</code> or <code>eth1</code> we don&#8217;t really need to mark them.</p>

<h4>Masq</h4>

<p>The <code>masq</code> file will contain the masquerading rules for our private interfaces: in essence, we want traffic from the local LAN and DMZ to be hidden behind our limited number of external IPs.<br />
See the <a href="http://shorewall.net/manpages/shorewall-masq.html">masq manpage</a> for all the details.</p>

<pre><code>#####################################################################
#INTERFACE              SOURCE           ADDRESS                 
# Ensure that traffic originating on the firewall and redirected via 
# packet marks always has the source IP address corresponding to the 
# interface that it is routed out of.
# See http://shorewall.net/MultiISP.html#Example1
ppp0                    30.40.50.62      111.99.88.77
eth1                    111.99.88.77     30.40.50.62
ppp0                    eth2             111.99.88.77
eth1                    eth2             30.40.50.62
ppp0                    eth3             111.99.88.77
eth1                    eth3             30.40.50.62
</code></pre>

<p>The first part ensures that the traffic coming out of our public interfaces but originating from the other is actually rewritten as originating from the right IP for the interface.<br />
This ensures that packets leaving <code>eth1</code> for instance don&#8217;t come out with the wrong source address of the <em>other</em> interface.<br />
The second part of the ensures that packets from our LAN or DMZ leaving either public interfaces are doing so with the right IP address, so traffic from my desktop going through <code>ppp0</code> for instance, will have its source address as <code>100.90.80.70</code>.</p>

<h4>Rules</h4>

<p>This is the main file where we tell shorewall our basic configuration and how we want packets to be handled in the general case.<br />
The <code>/etc/shorewall/rules</code> file contains the specific instructions on where to direct traffic that will override the default actions defined in the <code>/etc/shorewall/policy</code> file.</p>

<pre><code>#####################################################################
#ACTION    SOURCE                DEST                   PROTO  
#                                                                     
SECTION NEW
# Drop and log packets that come from the outside but pretend 
# to have a local address
DROP:info  net:192.168.0.0/24    all
DROP:info  net:192.168.254.0/24  all

# Redirect incoming traffic to the correct server for WWW and email
DNAT       all                   dmz:192.168.254.20     tcp   www
DNAT       all                   dmz:192.168.254.10     tcp   110
DNAT       all                   dmz:192.168.254.10     tcp   143
DNAT       all                   dmz:192.168.254.10     tcp   25
</code></pre>

<p>In its most basic form, what we&#8217;ve just defined here is that we want all traffic from anywhere destined for port 80 (www) to be sent to our <em>win</em> server.<br />
All mail traffic, POP3 (port 110), IMAP (port 143) and SMTP (port 25) is to be redirected to our <em>linux</em> server in the DMZ.</p>

<p>There are a few more useful rules that we can include, for instance, I want to be able to access my servers  through either ISPs from home (IP <code>123.45.67.89</code>) and disallow everyone else from accessing it.</p>

<pre><code>#####################################################################
#ACTION    SOURCE                DEST                   PROTO  
#                                                                     
# Allow SSH to the firewall from the outside only from home

ACCEPT     net:123.45.67.89      $FW                    tcp   ssh
# Redirect input traffic to the correct server for RDP, VNC and SSH 
DNAT       net:123.45.67.89      dmz:192.168.254.10:22  tcp   2222
DNAT       net:123.45.67.89      dmz:192.168.254.10     tcp   5901
DNAT       net:123.45.67.89      dmz:192.168.254.20     tcp   3389
</code></pre>

<p>When I SSH to <code>30.40.50.62</code> or <code>100.90.80.70</code>, on the normal port 22, I will access the firewall.<br />
Now if I SSH to the non-standard port 2222, I will instead access the <em>linux</em> server.<br />
Ports 5901 are for remoting through VNC on the <em>linux</em> machine, and port 3389 will be used for Remote Desktop connections to the <em>win</em> server.</p>

<p>To make sure my machines are up and running, I like to be able to ping them:</p>

<pre><code>#####################################################################
#ACTION    SOURCE              DEST              PROTO  
#                                                                     
# Accept pings between zones
ACCEPT     dmz                 loc               icmp  echo-request
ACCEPT     loc                 dmz               icmp  echo-request
</code></pre>

<p>Note that ping will only work between the LAN and the DMZ and pinging my firewall from the Internet will result in the requests being silently dropped.<br />
I usually prefer that configuration as it makes discovering the servers by random bots slightly less likely.</p>

<p>There are lots of other cool things we can do with forwarding but that will do for now.</p>

<h4>shorewall.conf</h4>

<p>The last file we&#8217;re going to look at is the main configuration file for shorewall.<br />
See details about each option from the <a href="http://shorewall.net/manpages/shorewall.conf.html">man page for <code>shorewall.conf</code></a>.</p>

<p>Most options are OK by default. The only ones that I have had to change are:</p>

<pre><code>STARTUP_ENABLED=Yes
MARK_IN_FORWARD_CHAIN=Yes
FASTACCEPT=Yes
OPTIMIZE=1
</code></pre>

<p>The first option tells shorewall that we want it to start automatically when the system boots.<br />
That&#8217;s not enough though, so make sure that the service will be started:</p>

<pre><code># chkconfig shorewall --levels 235 on
</code></pre>

<h3 id="installingourfirewallrules">Installing our firewall rules</h3>

<p>Shorewall configuration files need to be compiled without error before the firewall is actually loaded by shorewall.<br />
The command:</p>

<pre><code># shorewall restart
</code></pre>

<p>will stop and recompile the current configuration.<br />
If there are any errors, the current firewall rules will be unchanged.<br />
There are lots of other commands that can be issued. Check the man page for a complete list.</p>

<p>If you use PPPoE, you will want the firewall to be restarted every time the line reconnects.<br />
The simplest way is to create a file <code>/etc/ppp/if-up.local</code> with only a single line:</p>

<pre><code>shorewall restart
</code></pre>

<h3 id="dns">DNS</h3>

<p>There is one remaining issue with our firewall: if a user on the LAN attempts to access the web server by its name the request will probably fail.<br />
Same for accessing our mail server: we can configure our desktop to connect to <code>192.168.254.10</code> to get and send emails, but on the laptop we would usually use something like <code>pop.acme.com</code> instead so we can read our emails from outside the office.</p>

<p>Similarly, trying to access <code>www.acme.com</code> hosted on the <em>win</em> server from the <em>linux</em> server will fail.</p>

<p>One solution is to route traffic through the firewall but that&#8217;s actually fairly complicated to setup properly.<br />
The shorewall FAQ 2 discourages this and instead recommends the use of <a href="http://en.wikipedia.org/wiki/Split-horizon_DNS">split-DNS</a>: it&#8217;s very easy to setup and it works like a charm.</p>

<h4>dnsmasq</h4>

<p>Just install  <a href="http://www.thekelleys.org.uk/dnsmasq/doc.html">dnsmasq</a> on the firewall. There are ready-made packages available for it and a simple <code>yum install dsnmasq</code> should suffice.</p>

<p>Dnsmasq provides a simple DNS forwarding and DHCP service. I had already configured <code>dhcpd</code> -which is already fairly simple to configure- on my firewall so I won&#8217;t need DHCP from dnsmasq but you can easily set it up if you want.</p>

<p>On the DNS side, dnsmasq can be told to first try to resolve hostnames by looking at the standard <code>/etc/hosts</code> file and then query the DNS servers defined in <code>/etc/resolv.conf</code> if necessary.</p>

<p>This simple trick means that we can:</p>

<ul>
<li>Keep our normal DNS service pointing to say <code>100.90.80.70</code> for <code>www.acme.com</code> so that people on the Internet will properly resolve their web requests to our <em>win</em> server.</li>
<li>Add an entry in the firewall&#8217;s <code>hosts</code> file to point local clients to <code>192.168.254.20</code> instead.</li>
</ul>

<p>To achieve this, simply edit  <code>/etc/hosts</code>and add entries matching all your services:</p>

<pre><code># Acme's services. 
# One line for each DNS entries accessible from the Internet
192.168.254.20        acme.com
192.168.254.20        www.acme.com
192.168.254.10        pop.acme.com
192.168.254.10        mail.acme.com
</code></pre>

<h4>dsnmasq configuration</h4>

<p>Edit the <code>/etc/dsnmasq.conf</code> and uncomment or add the following lines:</p>

<pre><code># Never forward plain names (without a dot or domain part)
domain-needed
# Never forward addresses in the non-routed address spaces.
bogus-priv
# listen on DMZ and LAN interfaces
interface=eth2
interface=eth3
# don't want dnsmasq to provide dhcp
no-dhcp-interface=eth2
no-dhcp-interface=eth3
</code></pre>

<p>Then make sure that dsnmasq will start on boot:</p>

<pre><code># chkconfig dnsmasq --levels 235 on
# service dnsmasq restart
</code></pre>

<h4 id="dnsresolution">DNS resolution</h4>

<p>There may be one last issue with DNS: in your <code>/etc/resolv.conf</code> you will have listed the DNS servers of one or both of your ISPs.<br />
The problem is that some ISPs don&#8217;t allow access to their name servers from a network different than theirs.</p>

<p>The result is that each time any of the systems issues a DNS request it may fail and need to be sent to the next server instead, which may also fail and introduce delays in accessing named resources on the Internet.</p>

<p>One easy way out is to not use the ISPs DNS servers but instead only list the free <a href="http://opendns.org/">OpenDNS</a> name servers in your <code>resolv.conf</code>:</p>

<pre><code>search acme.com
nameserver 208.67.222.222
nameserver 208.67.220.220
</code></pre>

<p>Then make sure that you disable DNS in your <code>/etc/sysconfig/network-config/ifcfg-XXX</code> configuration file for your PPPoE connection:</p>

<pre><code>PEERDNS=no
</code></pre>

<p>Failure to do so will result in your <code>/etc/resolv.conf</code> file being rewritten with the DNS servers of one of your ISP every time you reconnect to them.</p>

<h4>DHCP configuration</h4>

<p>If you use <code>dhcpd</code> for local users, then you will need to make sure that its DNS server is set to the firewall&#8217;s:</p>

<pre><code># DHCP Server Configuration file.
ddns-update-style none;
ignore client-updates;

subnet 192.168.0.0 netmask 255.255.255.0 {
    option routers                  192.168.0.1;
    option subnet-mask              255.255.255.0;
    option domain-name              "acme.com";
    option domain-name-servers      192.168.0.1;
    range 192.168.0.200 192.168.0.250;
    default-lease-time 86400;
    max-lease-time 132000;
}
</code></pre>

<p>On your local machines that use DHCP, make sure to renew your IP.<br />
All other machines should be configured to use <code>192.168.0.1</code> as their unique DNS server and the machines in the DMZ should have their DNS set to <code>192.168.254.1</code>.</p>

<p>Unless you reboot, don&#8217;t forget and flush the local DNS cache of each machine:<br />
On Windows, from the command line:</p>

<pre><code>C:\&gt; ipconfig /flushdns
</code></pre>

<p>On Mac, from the terminal:</p>

<pre><code>bash-x.xxx$ dnscacheutil -flushcache
</code></pre>

<h3 id="initialconclusions">Initial conclusions</h3>

<p>I believe this type of firewall setup is fairly common and I hope that the -rather long- article helped you get your own setup in place.<br />
In the -much shorter- follow-up articles, we&#8217;ll make our system as redundant as possible so our web and email services stay online even when one of the broadband connections fails.</p>

<p>In the meantime, don&#8217;t hesitate to leave your comments and corrections below.</p>

<h3 id="history">History</h3>

<ul>
<li>06FEB2009: added info about restarting the firewall on <a href="#installingourfirewallrules">PPPoE reconnection</a> and disabling <a href="#dnsresolution">ISP&#8217;s DNS resolution</a>.</li>
<li>04FEB2009: initial release.</li>
</ul>

<h3 id="references">References</h3>

<ul>
<li><a href="http://shorewall.net/">Shorewall</a>&#8216;s main site.</li>
<li>Shorewall&#8217;s [man page][manpage] list for all configuration files.</li>
<li><a href="http://opendns.org/">OpenDNS</a> free worldwide DNS service (and more).</li>
<li><a href="http://www.thekelleys.org.uk/dnsmasq/doc.html">dnsmasq</a> DNS forwarder (for easily setting up <a href="http://en.wikipedia.org/wiki/Split-horizon_DNS">split-horizon-DNS</a>).</li>
<li><a href="http://www.centos.org/">CentOS</a> linux distribution, based on <a href="http://www.redhat.com/rhel/">RedHat Enterprise Linux</a>.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2009/sysadmin-multiple-isp-firewall-servers-and-redundancy/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Sysadmin: file and folder synchronisation</title>
		<link>http://blog.nkadesign.com/2009/sysadmin-data-folder-synchronisation/</link>
		<comments>http://blog.nkadesign.com/2009/sysadmin-data-folder-synchronisation/#comments</comments>
		<pubDate>Mon, 19 Jan 2009 14:54:09 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[sync]]></category>
		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=311</guid>
		<description><![CDATA[Over the years I&#8217;ve struggled to keep my folder data synchronised between my various desktop and laptops. Here I present the tools I&#8217;ve tried and what I&#8217;ve finally settled on as possibly the ultimate answer to the problem of synchronising files and folders across multiple computers: rsync unison WinSCP General Backup tools Revision Control Systems [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/technology01.png" alt="Technology" title="Technology" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />
Over the years I&#8217;ve struggled to keep my folder data synchronised between my various desktop and laptops.</p>

<p>Here I present the tools I&#8217;ve tried and what I&#8217;ve finally settled on as possibly the ultimate answer to the problem of synchronising files and folders across multiple computers:</p>

<ul>
<li><a href="#rsync">rsync</a></li>
<li><a href="#unison">unison</a></li>
<li><a href="#winscp">WinSCP</a></li>
<li><a href="#backup">General Backup tools</a></li>
<li><a href="#rcs">Revision Control Systems</a></li>
<li><a href="#compexsetup">Complex setup</a></li>
<li><a href="#whatwewant">What we want from data synchronisation</a></li>
<li><a href="#livemesh">Live Mesh folders</a></li>
<li><a href="#conclusion">Conclusion</a></li>
<li><a href="#references">References</a></li>
</ul>

<p><center><img src="http://blog.nkadesign.com/wp-content/uploads/2009/01/mesh.png" alt="Sync Files" title="Sync" width="416" height="232" class="size-full wp-image-323" /></center></p>

<h3 id="rsync">rsync</h3>

<p>I&#8217;ve tried <a href="http://samba.anu.edu.au/rsync/">rsync</a>, which is a great Open Source tool to securely synchronise data either one-way or both-ways.<br />
It&#8217;s very efficient with bandwidth as it only transfer blocks of data that have actually changed in a file instead of the whole file. It can tunnel traffic across SSH and I&#8217;ve got a few <a href="http://en.wikipedia.org/wiki/Cronjob">cronjobs</a> set up between various servers to back-up files daily.</p>

<p>It&#8217;s only weaknesses are that:</p>

<ul>
<li>Every time it runs, it needs to inspect all files on both sides to determine the
 changes, which is quite an expensive operation.   </li>
<li>Setting up synchronisation between multiple copies of the data can be tricky: 
 you need to sync your computers in pairs multiple times, which quickly becomes 
 expensive and risky if you have the same copy across multiple computers.</li>
<li>It doesn&#8217;t necessarily detect that files are in use at the time of the sync, which 
could corrupt them.</li>
</ul>

<h3 id="unison">unison</h3>

<p>It a folder synchronisation tool whose specific purpose is to address some of the shortcomings of <code>rsync</code> when synchronising folders between computers.
It&#8217;s also a cross-platform Open Source tool that works on Linux, OS/X, Windows, etc.</p>

<p><a href="http://www.cis.upenn.edu/~bcpierce/unison/">Unison</a> uses the efficient file transfer capabilities of <code>rsync</code> but it is better at detecting conflicts and it will give you a chance to decide which copy you want when a conflict is detected.</p>

<p>The issue though is that, like <code>rsync</code>, it needs to inspect all files to detect changes which prevents it from detecting and propagating updates as they happen.</p>

<p>The biggest issue with these synchronisation tools is that they tend to increase the risk of conflict because changes are only detected infrequently.</p>

<h3 id="winscp">WinSCP</h3>

<p><a href="http://winscp.net/eng/">WinSCP</a> Is an Open Source Windows GUI FTP utility that also allows you to synchonise folders between a local copy and a remote one on the FTP server.</p>

<p>It has conflict resolution and allows you to decide which copy to keep.</p>

<p>It&#8217;s great for what it does and allows you to keep a repository of your data in sync with your local copies but here again, WinSCP needs to go through each file to detect the differences and you need to sync manually each computer against the server, which is cumbersome and time consuming.</p>

<h3 id="backup">General Backup tools</h3>

<p>There are lot more tools that fall into that category of backup utilities: they all keep a copy of your current data in an archive, on a separate disk or online.
Some are great in that they allow you to access that data on the web (I use the excellent <a href="http://www.jungledisk.com/">JungleDisk</a> myself) but file synchronisation is not their purpose.</p>

<p>Now for some <a href="http://uncyclopedia.wikia.com/wiki/Captain_Obvious">Captain Obvious</a> recommendation: remember that file synchronisation is <em>not a backup plan</em>: you must have a separate process to keep read-only copies of your important data.<br />
File synchronisation will update and delete files you modify across all your machines, clearly not what you want if you need to be able to recover them!</p>

<h3 id="rcs">Revision Control Systems</h3>

<p><a href="http://en.wikipedia.org/wiki/Revision_control">Revision control software</a> like <a href="http://savannah.nongnu.org/project/memberlist.php?detailed=1&amp;group=cvs">cvs</a>, <a href="http://subversion.tigris.org/">subversion</a>, <a href="http://en.wikipedia.org/wiki/Git_(software)">git</a>, <a href="http://en.wikipedia.org/wiki/Comparison_of_revision_control_software">etc</a> are generally used to keep track of changes of source code files; however, they have also been used successfully to keep multiple copies of the same data in sync.<br />
It&#8217;s actually exactly <a href="http://tortoisesvn.tigris.org/">what I use</a> for all my source code and associated files: I have a subversion server and I check-out copies of my software project folders on various computers.</p>

<p>After making changes on one computer, I <em>commit</em> the changes back to the server and <em>update</em> these changes on all other computers manually.</p>

<p>While great at keeping track of each version of your files and ideally suited to pure text documents like source code, using revision control systems have drawbacks that make them cumbersome for general data synchronisation:</p>

<ul>
<li>you need to manually commit and update your local copies against the server.</li>
<li>not all of them are well suited to deal with binary files</li>
<li>when they work with binary files, they just copy the whole file when it changed, which is wasteful and inefficient.</li>
</ul>

<p>Revision Control System are great for synchronising source code and configuration files but using them beyond that is rather cumbersome.</p>

<h3 id="compexsetup">Complex setup</h3>

<p>All of the above solutions also have a major drawback: getting them to work across the Internet requires complex setup involving firewall configurations, security logins, exchange of public encryption keys in some cases, etc.</p>

<p>All these are workable but don&#8217;t make for friendly and piece-of-mind setup.</p>

<h3 id="whatwewant">What we want from data synchronisation</h3>

<p>I don&#8217;t know about you but what I&#8217;m looking for in a synchronisation tool is pretty straightforward:</p>

<ul>
<li>Being able to point to a folder on one computer and make it synchronise across one or multiple computers.</li>
<li>Detect and update the changed files transparently in the background without my intervention, as the changes happen.</li>
<li>Be smart about conflict detection and only ask me to make a decision if the case isn&#8217;t obvious to resolve.</li>
</ul>

<h3 id="livemesh">Live Mesh folders</h3>

<p>Enters <a href="http://en.wikipedia.org/wiki/Windows_Live_Core">Microsoft Live Mesh Folders</a>, now in beta and available to the public.
Live Mesh is meant to be Microsoft answer&#8217;s to synchronising <em>information</em> (note, I&#8217;m not saying <em>data</em> here) across computers, devices and the Internet.<br />
While Live Mesh wants to be something a lot bigger than just synchronising folders, let&#8217;s just concentrate on that aspect of it.</p>

<p>Installing Live Mesh is pretty easy: you will need a Windows Live account to log-in but once this is done, it&#8217;s a small download and a short installation.</p>

<p>Once you&#8217;ve added your computer to your &#8220;Mesh&#8221; and are logged in you are ready to use Live Mesh:</p>

<ul>
<li>You decide how the data is synchronised for each computer participating in your Mesh:<br />
you&#8217;re in charge of what gets copied where, so it&#8217;s easy to make large folders pair between say your laptop and work desktop and not your online Live Desktop (which has a 5GB limit) or your computer at home. You&#8217;re in control.</li>
<li>Files are automatically synchronised as they change across all computers that share the particular folder you&#8217;re working in.<br />
If the file is currently used, it won&#8217;t be synced before it is closed.</li>
<li>If the other computers are not available, the sync will automatically happen as they are up again.</li>
<li>There is no firewall setup: each computer knows how to contact the others and automatically -and uses- the appropriate network: transfers are local if the computers are on the same LAN or done across the Internet otherwise.<br />
All that without user intervention at all.</li>
<li>Whenever possible, data is exchanged in a P2P fashion where each device gets data from all the other devices it can see, making transfers quite efficient.</li>
<li>File transfers are encrypted so they should be pretty safe even when using unsafe public connections.</li>
<li>If you don&#8217;t want to allow sync, say you&#8217;re on a low-bandwidth dialup, you can work offline.</li>
<li>The Mesh Operating Environment (MOE) is pretty efficient at detecting changes to files. Unlike other systems, in most cases it doesn&#8217;t need to scan all files to find out which ones have been updated or deleted.</li>
</ul>

<p><strong>Some drawbacks</strong></p>

<ul>
<li>It&#8217;s not a final product, so there are some quirks and not all expected functionalities are there yet.</li>
<li>The Mesh Operating Environment (MOE) services can be pretty resource hungry, although, in fairness, it&#8217;s not too bad except that it slows down your computer&#8217;s responsiveness while it loads at boot time.</li>
<li>You can&#8217;t define patterns of files to exclude in your folder hierarchy.<br />
That can be a bit annoying if the software you use is often creating large backup files automatically (like CorelDraw does) or if there are sub folders you don&#8217;t need to take everywhere.</li>
<li>The initial sync process can take a long time if you have lots of files.<br />
A solution if you have large folders to sync is to copy them first manually on each computer and then force Live Mesh to use these specific folders: the folders will be merged together and the initial sync process will be a lot faster as very little data needs to be exchanged between computers.</li>
</ul>

<p>Bear in mind that Live Mesh is currently early beta and that most of these drawback will surely be addressed in the next months.</p>

<h3 id="conclusion">Conclusion</h3>

<p>I currently have more than 18GB representing about 20,000 files synchronised between 3 computers (work desktop, laptop and home desktop) using Live Mesh.</p>

<p>While not 100% there, Live Mesh Folder synchronisation is really close to the real thing: it&#8217;s transparent, efficient, easy to use and it just works as you would 
expect.</p>

<p>Now that Microsoft has released the <a href="http://msdn.microsoft.com/en-us/sync/default.aspx">Sync Framework</a> to developers, I&#8217;m sure that other products will come on the market to further enhance data synchronisation in a more capable way.<br />
In the meantime, Live Mesh has answered my needs so far.</p>

<h3 id="references">References</h3>

<ul>
<li><a href="http://en.wikipedia.org/wiki/File_synchronization">Wikipedia reference on file synchronisation</a>.</li>
<li><a href="http://samba.anu.edu.au/rsync/">rsync</a> home page and <a href="http://en.wikipedia.org/wiki/Rsync">Wikipedia entry</a></li>
<li><a href="http://www.cis.upenn.edu/~bcpierce/unison/">unison</a> home page and <a href="http://en.wikipedia.org/wiki/Unison_(file_synchronizer)">Wikipedia entry</a></li>
<li><a href="http://www.jungledisk.com/">JungleDisk</a> online backup (cheap and very configurable, uses <a href="http://aws.amazon.com/s3/">Amazon S3</a> for storage)</li>
<li>Microsoft <a href="http://mesh.com">Live Mesh</a> web site and <a href="http://en.wikipedia.org/wiki/Windows_Live_Core">Live Mesh Wikipedia entry</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2009/sysadmin-data-folder-synchronisation/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Sysadmin: Recovering deleted Windows partitions</title>
		<link>http://blog.nkadesign.com/2009/sysadmin-recovering-deleted-partitions/</link>
		<comments>http://blog.nkadesign.com/2009/sysadmin-recovering-deleted-partitions/#comments</comments>
		<pubDate>Thu, 08 Jan 2009 02:57:08 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=306</guid>
		<description><![CDATA[I made a mistake the other day: I wanted to delete the partition on an external drive and in my haste ended up deleting the partition of a local hard drive instead&#8230; The good thing is when you delete a partition using the Windows Disk Management console it doesn&#8217;t actually delete your files, only the [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/windows.png" alt="Technology" title="Technology" align="left" width="64" height="60" hspace="5" vspace="5" border="0" />I made a mistake the other day: I wanted to delete the partition on an external drive and in my haste ended up deleting the partition of a local hard drive instead&#8230;</p>

<p>The good thing is when you delete a partition using the Windows Disk Management console it doesn&#8217;t actually delete your files, only the partition header.</p>

<p><img src="/wp-content/uploads/2009/01/Recover1.png" alt="Windows Disk Management Console" /></p>

<p>With NTFS files systems, there is a backup at the end of the partition. The problem is how do you recover it?</p>

<p>I first looked at the instructions from Microsoft knowledge base article <a href="http://support.microsoft.com/kb/245725">kb245725</a>, downloaded the low-level sector editor <code>Dskprobe</code> but was getting no-where with it.</p>

<p>Searching google brings you to the usual list of recovery software that you can&#8217;t be sure will actually do the job until you fork $$ for them.<br />
I&#8217;ve got nothing against paying for software but I&#8217;ve been bitten by false promises before.</p>

<p>My search ended up with <a href="http://www.cgsecurity.org/wiki/TestDisk"><code>TestDisk</code></a> an OpenSource utility to manipulate and recover partitions that works on almost all platforms.<br />
The user interface is DOS only, so it&#8217;s not pretty, not point-and-click user friendly but it has a fair amount of options and after fiddling around with it for 10 minutes, I was able to simply recover the backup boot sector and tada! all my files were back!</p>

<p><img src="/wp-content/uploads/2009/01/Recover2.png" alt="TestDisk in action" /></p>

<p>So, some recommendations when recovering lost partitions:</p>

<ul>
<li>Don&#8217;t panic! If you only deleted the partition (whichever type), chances are you&#8217;re likely to recover it or at least salvage the files.</li>
<li>Obviously, be careful not to write anything over them, like recreating partitions and a file system.</li>
<li>If you use a utility like <code>TestDisk</code>, don&#8217;t blindly follow the on-screen instructions. At first, it was telling me that I had 2 Linux partitions on the device (which used to be true) but it did not see the NTFS one. Then it thought I had a FAT partition only until I switched to the advanced options and inspected the boot partition.<br />
Just know enough about file systems to know what you&#8217;re looking for.</li>
<li>Low-level tools are not for everyone, so if you&#8217;re not comfortable using them, don&#8217;t tempt your luck and try a paid-for recovery tool with an easier interface.</li>
</ul>

<p>If you use <code>TestDisk</code> and you manage to recover your files, don&#8217;t forget to <a href="http://www.cgsecurity.org/wiki/Donation">donate</a> to encourage Christophe GRENIER, the author.</p>

<h3>References</h3>

<ul>
<li><a href="http://support.microsoft.com/kb/245725">KB245725: How To Recover an Accidentally Deleted NTFS or FAT32 Dynamic Volume.</a></li>
<li><a href="http://www.cgsecurity.org/wiki/TestDisk">TestDisk</a> data recovery utility for Windows, Linux, OS/X, etc</li>
<li><a href="http://www.cgsecurity.org/wiki/PhotoRec">PhotoRec Digital Picture and File Recovery</a> Open Source utility from the same author.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2009/sysadmin-recovering-deleted-partitions/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>.Net: Working with OpenOffice 3</title>
		<link>http://blog.nkadesign.com/2008/net-working-with-openoffice-3/</link>
		<comments>http://blog.nkadesign.com/2008/net-working-with-openoffice-3/#comments</comments>
		<pubDate>Wed, 05 Nov 2008 20:06:27 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[OpenOffice]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=245</guid>
		<description><![CDATA[(Updated Wednesday 30JAN2009.) Developing applications that manipulate OpenOffice documents has always been rather tricky; not very difficult, but just tricky to get right. With OpenOffice 3, things got trickier and applications that used to work will now fail. I&#8217;ve just spend nearly a day trying to get a mail-merge application I built to work again [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/technology02.png" alt="technology02.png" title="technology02.png" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />(<strong>Updated Wednesday 30JAN2009.</strong>) Developing applications that manipulate OpenOffice documents has always been rather tricky; not very difficult, but just tricky to get right.</p>

<p>With OpenOffice 3, things got trickier and applications that used to work will now fail.
I&#8217;ve just spend nearly a day trying to get a mail-merge application I built to work again with the new version of OO.<br />
<a href="http://www.openoffice.org"><img src='/wp-content/uploads/2008/11/ooo3.png' alt='OOo3'  style="float:right;margin-left:10px;margin-bottom:5px" border=0 width=250 height=162/></a></p>

<h3>Changes and limitations</h3>

<p>Developing .Net applications with OpenOffice 3 <a href="http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/ProUNO/CLI/CLI_Language_Binding">now requires that the .Net framework 3.5 be installed</a>.<br />
Only one version of OpenOffice/StarOffice must be installed.</p>

<h3>Getting the CLI assemblies in your project</h3>

<p>OpenOffice used to ship with a bunch of CLI DLLs for manipulating Open Documents from .Net.
With OpenOffice version 3, these DLLs are directly installed in the GAC and not available in the Program installation folder any longer, making them unavailable when you need to add them as references to your Visual Studio project.</p>

<p>The trick is to extract the DLLs from the installation CAB, then reference those and make sure you exclude them in your setup file so only the latest version installed on the user&#8217;s computer&#8217;s GAC will get used.</p>

<ol>
<li>Open the installation folder where the installation files are extracted (usually left on your desktop under a folder like <code>OpenOffice.org 3.0 (en-US) Installation Files</code> during the OO installation process.</li>
<li>Open the <code>openofficeorg1.cab</code> file (using a utility like <a href="http://www.7-zip.org/">7zip</a> if necessary) and extract the files matching <code>cli_*.dl</code>.  </li>
<li>Add the ones you need to your VS Project&#8217;s references and make sure the properties of these references have their <em>Copy Local</em> and <em>Specific Version</em> properties set to <em>false</em>.</li>
<li>If you have a setup project that added these references to the list of files, right-click each of them and select <em>Exclude</em> to make sure they won&#8217;t be packaged.</li>
</ol>

<p>The reason for not deploying the DLLs is that they are very specific to a given OpenOffice version and the latest assemblies relevant to the user&#8217;s OpenOffice installation will already be deployed to the target machine&#8217;s GAC.<br />
When .Net loads assemblies, if they are not included in the path of the application being launched, they will be loaded from the GAC if they can be found there.</p>

<h3>Path and environment setup</h3>

<p>Before being able to call OpenOffice from your application you now must set your application&#8217;s environment variables to the correct paths so the assemblies can find the actual OpenOffice library and program files.</p>

<p>Basically, you need to add to your <code>PATH</code> the path to the folder where the UNO java libraries reside.
You also need to add a <code>UNO_PATH</code> environment variable that points to the program folder of OpenOffice.
Basically, before any call to OpenOffice functions you must:</p>

<ul>
<li>Append to <code>PATH</code> something like <code>C:\Program Files\OpenOffice.org 3\URE\bin</code>.</li>
<li>Create a <code>UNO_PATH</code> variable set to <code>C:\Program Files\OpenOffice.org 3\program</code>.</li>
</ul>

<p>Because there is no guarantee that these paths will not change or are valid for all systems you must get them from specific keys located in the Registry:</p>

<ul>
<li><code>PATH</code> is appended with the vaue of <code>HKLM\SOFTWARE\OpenOffice.org\Layers\URE\1\UREINSTALLLOCATION</code> to which you must append the <code>bin</code> directory.</li>
<li><code>UNO_PATH</code> is set to the content of the <code>HKLM\SOFTWARE\OpenOffice.org\UNO\InstallPath</code> key.</li>
</ul>

<p>See the C# and VB.Net code below for working examples.</p>

<h3>Special Considerations for x64 systems</h3>

<p>My development machine runs Windows Server 2008 x64 and I&#8217;ve ran into some specific issues that you&#8217;re likely to encounter when deploying to a 64 bits OS.</p>

<p><strong>OpenOffice is 32 bits only</strong><br />
That means that your .Net project must be set to target x86 systems only:<br />
Open your Solution&#8217;s <em>Configuration Manager</em> and under <em>Active solution platform</em> click <em>New&#8230;</em> then:</p>

<p><center><img src="/wp-content/uploads/2008/11/sshot-4.png" alt="Configuration" /></center></p>

<p>Make sure you repeat this for both the <em>Debug</em> and <em>Release</em> configurations.</p>

<p><strong>Registry keys are elsewhere</strong><br />
32 bit applications see their registry keys normally expected under:<br />
<code>HKEY_LOCAL_MACHINE\Software</code> moved to:<br />
<code>HKEY_LOCAL_MACHINE\Software\Wow6432Node</code> instead.<br />
This of course creates issues when you&#8217;re trying to read a registry key that&#8217;s not where it should be&#8230;</p>

<h3>The Code</h3>

<p>The code below will allow you to correctly connect to OpenOffice 3 under 32 or 64 bit systems.<br />
It reads the registry to find the proper paths and appends the <code>PATH</code> and creates the <code>UNO_PATH</code> environment variables expected by the the bootstrapper to find the OpenOffice program and libraries.</p>

<p>The code is built upon information and a test program made available by <a href="http://www.schrievkrom.de/blog/">Marten Feldtmann</a> on his <a href="http://www.schrievkrom.de/blog/?p=199">blog</a> (more information, in English, is available on <a href="http://www.oooforum.org/forum/viewtopic.phtml?p=302441">OOoForum</a> ).</p>

<p>Please let me know if this works for you or if you have any corrections.
<textarea name="code" class="c#:nogutter" cols="60" rows="10">
private void InitOpenOfficeEnvironment() {
  string baseKey;
  // OpenOffice being a 32 bit app, its registry location is different in a 64 bit OS
  if (Marshal.SizeOf(typeof(IntPtr)) == 8)
      baseKey = @"SOFTWARE\Wow6432Node\OpenOffice.org\";	
  else
      baseKey = @"SOFTWARE\OpenOffice.org\";  

  // Get the URE directory
  string key = baseKey + @"Layers\URE\1";
  RegistryKey reg = Registry.CurrentUser.OpenSubKey(key);
  if (reg==null) reg = Registry.LocalMachine.OpenSubKey(key);
  string urePath = reg.GetValue("UREINSTALLLOCATION") as string;
  reg.Close();
  urePath = Path.Combine(urePath, "bin");

  // Get the UNO Path
  key = baseKey + @"UNO\InstallPath";
  reg = Registry.CurrentUser.OpenSubKey(key);
  if (reg==null) reg = Registry.LocalMachine.OpenSubKey(key);
  string unoPath = reg.GetValue(null) as string;
  reg.Close();

  string path;
  path = string.Format ("{0};{1}", System.Environment.GetEnvironmentVariable("PATH"), urePath);
  System.Environment.SetEnvironmentVariable("PATH", path);
  System.Environment.SetEnvironmentVariable("UNO_PATH", unoPath);
}
</textarea></p>

<p>In VB.Net:
<textarea name="code" class="vb:nogutter" cols="60" rows="10">
Private Sub InitOpenOfficeEnvironment()
  Dim baseKey As String
  ' OpenOffice being a 32 bit app, its registry location is different in a 64 bit OS
  If (Marshal.SizeOf(GetType(IntPtr)) = 8) Then
    baseKey = "SOFTWARE\Wow6432Node\OpenOffice.org\"
  Else
    baseKey = "SOFTWARE\OpenOffice.org\"
  End If

  ' Get the URE directory
  Dim key As String = (baseKey + "Layers\URE\1")
  Dim reg As RegistryKey = Microsoft.Win32.egistry.CurrentUser.OpenSubKey(key)
  If (reg Is Nothing) Then
    reg = Registry.LocalMachine.OpenSubKey(key)
  End If
  Dim urePath As String = CType(reg.GetValue("UREINSTALLLOCATION"),String)
  reg.Close
  urePath = Path.Combine(urePath, "bin")

  ' Get the UNO Path
  key = (baseKey + "UNO\InstallPath")
  reg = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(key)
  If (reg Is Nothing) Then
    reg = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(key)
  End If
  Dim unoPath As String = CType(reg.GetValue(Nothing),String)
  reg.Close

  Dim path As String
  path = String.Format ("{0};{1}",System.Environment.GetEnvironmentVariable("PATH"),urePath)
  System.Environment.SetEnvironmentVariable("PATH", path)
  System.Environment.SetEnvironmentVariable("UNO_PATH", unoPath)
End Sub
</textarea></p>

<h3>Updates</h3>

<p>07MAY2009 -- Added reference link to OOo documentation.<br />
03DEC2008 -- Added VB.Net translation. Thanks to Stefan for suggesting it.<br />
30JAN2009 -- Added reference to Aleksandr Sazonov&#8217;s article on CodeProject (thanks for the the article).</p>

<h3>References</h3>

<ul>
<li><a href="http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/ProUNO/CLI/CLI_Language_Binding">CLI Language Binding</a></li>
<li><a href="http://www.oooforum.org/forum/viewtopic.phtml?t=76356&amp;start=0&amp;postdays=0&amp;postorder=asc&amp;highlight=">OOoForum thread</a> on getting sample C# code to work with OpenOffice 3</li>
<li><a href="http://www.oooforum.org/forum/viewtopic.phtml?p=302441">OOoForum thread</a> on upgrading code from OpenOffice 2.4 to 3</li>
<li><a href="http://opendocument4all.com/content/view/68/47/">Programming with .Net quick start guide</a>.</li>
<li><a href="http://www.oooforum.org/forum/viewtopic.phtml?p=302441">CLI UNO bridge not working</a></li>
<li><a href="http://www.codeproject.com/KB/cs/TblProc.aspx">Cross-compatible spreadsheet processor</a> in .Net for Excel and OOo Calc, article from Aleksandr Sazonov on CodeProject.</li>
<li><a href="http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/ProUNO/CLI/Writing_Client_Programs">Writing client programs -- from the OOo documentation</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2008/net-working-with-openoffice-3/feed/</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>Windows 2008 / Windows 7 x64: The &#8216;Microsoft.Jet.OLEDB.4.0&#8242; provider is not registered on the local machine.</title>
		<link>http://blog.nkadesign.com/2008/windows-2008-the-microsoftjetoledb40-provider-is-not-registered-on-the-local-machine/</link>
		<comments>http://blog.nkadesign.com/2008/windows-2008-the-microsoftjetoledb40-provider-is-not-registered-on-the-local-machine/#comments</comments>
		<pubDate>Tue, 28 Oct 2008 13:31:53 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=236</guid>
		<description><![CDATA[There are times when the coexistence of 64 and 32 bit code on the same machine can cause all sorts of seemingly strange issues. One of them just occurred to me while trying to run the ASPx demos from Developer Express, my main provider of .Net components (the best supplier I&#8217;ve ever been able to [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/technology01.png" alt="Technology" title="Technology" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />There are times when the coexistence of 64 and 32 bit code on the same machine can cause all sorts of seemingly strange issues.<br />
One of them just occurred to me while trying to run the <a href="http://www.devexpress.com/Downloads/NET/OnlineDemos.xml">ASPx demos</a> from <a href="http://www.devexpress.com/">Developer Express</a>, my main provider of .Net components (the best supplier I&#8217;ve ever been able to find).<br />
I was getting the following error:</p>

<p><em>The &#8216;Microsoft.Jet.OLEDB.4.0&#8242; provider is not registered on the local machine:</em> 
<center><img src="/wp-content/uploads/2008/10/sshot-2.png" alt="Server Error" /></center></p>

<p>It may look otherwise, but this error is generally due to either of two thing:</p>

<ul>
<li>you don&#8217;t have Office 2007/2010 Jet drivers installed</li>
<li>or you are running a 32 bit application in a default x64 environment.</li>
</ul>

<p>The first issue is easy to solve, just download the <a href="http://www.microsoft.com/download/en/details.aspx?id=13255">Access 2010 Database Engine</a> from Microsoft (works with Access 2007 databases as well).</p>

<p>For the second one, the fix is also easy enough:</p>

<ul>
<li><em>For Windows 2008</em>: Navigate to  Server Manager > Roles > Web Server (IIS)  > Internet Information Services (IIS) Manager,  then look under your machine name > Application Pool.</li>
<li><em>For Windows 7</em>: Navigate to  Programs > Administrative Tools > Internet Information Services (IIS) Manager,  then look under your machine name > Application Pool.</li>
</ul>

<p><center><a title="Server Manager" style="border:0;" href="/wp-content/uploads/2008/10/sshot-6.png" rel="lightbox"><img title="Server Manager" src="/wp-content/uploads/2008/10/sshot-6sm.png" width=560 Height=410 /></a></center></p>

<p>Under there you can call the DefaultAppPool&#8217;s advanced settings to change <code>Enable 32-Bits Applications</code> to <code>True</code>:<br />
<center><img src="/wp-content/uploads/2008/10/sshot-3.png" alt="Advanced Settings" /></center></p>

<p>You may have to restart the service for it to take effect but it should work.</p>

<h3>References</h3>

<ul>
<li><a href="http://www.hanselman.com/blog/BackToBasics32bitAnd64bitConfusionAroundX86AndX64AndTheNETFrameworkAndCLR.aspx">Scott Hanselman&#8217;s blog entry</a> about undestanding 64 vs. 32 bitness in .Net.</li>
<li><a href="http://www.microsoft.com/download/en/details.aspx?id=13255">Access 2010 Database Engine driver</a></li>
</ul>

<h3>Updates</h3>

<ul>
<li>10DEC2011: Updated driver link to use the Access 2010 engine.</li>
<li>03APR2010: Added instructions for Windows 7</li>
<li>12FEB2009: Added reference to Scott&#8217;s article.</li>
<li>28OCT2008: Original version</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2008/windows-2008-the-microsoftjetoledb40-provider-is-not-registered-on-the-local-machine/feed/</wfw:commentRss>
		<slash:comments>74</slash:comments>
		</item>
		<item>
		<title>Sysadmin: Macbook Pro, after the honeymoon</title>
		<link>http://blog.nkadesign.com/2008/sysadmin-macbook-pro-after-the-honeymoon/</link>
		<comments>http://blog.nkadesign.com/2008/sysadmin-macbook-pro-after-the-honeymoon/#comments</comments>
		<pubDate>Sat, 18 Oct 2008 19:00:29 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Hardware]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[Reviews]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=207</guid>
		<description><![CDATA[I&#8217;ve been using the MacBook Pro I introduced in my previous blog entry for a few weeks now. Between love and frustration I hang&#8230; Here is a review of our relationship so far. The Great Hardware delight Whether running OS/X or Windows 2008 I&#8217;ve got no major complaint about the performance of the machine. It&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/apple.png" alt="security01.png" title="security01.png" align="left" width="53" height="64" hspace="5" vspace="5" border="0" />I&#8217;ve been using the MacBook Pro I introduced in my <a href="/2008/mac-installing-windows-server-2008-x64-on-a-macbook-pro/">previous blog entry</a> for a few weeks now.<br />
Between love and frustration I hang&#8230;<br />
Here is a review of our relationship so far.</p>

<h2>The Great</h2>

<h3>Hardware delight</h3>

<p>Whether running OS/X or Windows 2008 I&#8217;ve got no major complaint about the performance of the machine.
It&#8217;s fast, stable (except sometimes it&#8217;s not waking up from sleep or it does but the screen remains black). The screen is nice and vibrant, I just love the magnetic power connector and the small size of the power adapter.
I have a few complaints though, see below.</p>

<h3>OSX battery Power usage</h3>

<p>For such a large and powerful laptop I&#8217;m pleasantly surprised with the duration of the battery under OSX: I&#8217;ve been able to watch videos for 3h, full screen, without trouble and overheating (although I would lower the screen brightness to reduce consumption).<br />
I haven&#8217;t had such luck under Windows 2008 where I&#8217;ve been struggling to find the right power settings balance, but remember that&#8217;s a server OS and it&#8217;s not really meant to be run on a laptop.</p>

<p><center><img title="mac vs vista" src="/wp-content/uploads/2008/08/GetAMacAd.jpg" width=420 Height=319 style="margin-left:10px;margin-bottom:5px;" /></center></p>

<h2>The Ugly</h2>

<h3>The mouse</h3>

<p>You wonder why Apple, in all its hardware expertise could design the mighty-mouse with a single big button that can still do right-clicking but can&#8217;t give us the same thing with the enormous single-button of the trackpad.<br />
Now the new models -just released this week- have done away with the button entirely, which may be just as well although I&#8217;m curious about how well the drivers will work under Windows.</p>

<p>Mouse acceleration in OSX is pretty frustrating to me.
When you&#8217;ve got a large screen, you&#8217;re endlessly shuffling the mouse to get that pointer in the right place. It feels slow, inaccurate and is extremely irritating after a while.
The problem is even worse when you&#8217;re working in OSX under VMware Fusion: while it might still be usable under OSX, the difference is really severe and unnatural in Windows.<br />
This does not happen under bootcamp though where mouse acceleration behaves as you would expect (for windows).<br />
I&#8217;ve tried a number of utilities (<a href="http://lavacat.com/iMouseFix/index.html">iMouse</a> , <a href="http://plentycom.jp/en/steermouse/">SteerMouse</a> and others) but none gave me what I needed.</p>

<h3>The keyboard</h3>

<p>The keyboard feels great to type on, with a nice spring and softness.
There are a few issues though:<br />
Why is the Return key so small compared to the right Shift?<br />
The rule is that the more a key is used, the bigger it is, yet the Enter is rather small, it&#8217;s the same size as the caps lock which serves almost no useful purpose in comparison.<br />
The arrow keys are also minuscule, another probable example of Apple choosing form over function.
The lack of delete key forces you to type both the <code>fn</code> + <code>backspace</code> keys instead, which is an unnecessary pain, it&#8217;s not like understanding the difference between <code>delete</code> and <code>backspace</code> is <em>that</em> confusing to people using a complex machine like a computer.</p>

<h3>The lid</h3>

<p>I love the way the hooks for the lid come out just when you close it. It makes for a neat screen without protruding bits of metal or plastic.<br />
My main issue with the lid is with its limited opening angle: if you&#8217;re just a little tall and you place your laptop on your lap then there is no way to open the screen enough to have it properly face you.<br />
This is also an issue if you place your Macbook Pro on a cooling pad or a riser that&#8217;ll put the laptop too vertical (for instance to free some space around it when using an external keyboard): you just can&#8217;t use these devices.</p>

<h3>The sound</h3>

<p>That one really makes me mad: the MacBook Pro has audio issues that you won&#8217;t even find in a US$15 MP3 player and it&#8217;s totally unacceptable.<br />
When idle, I can hear hissing sounds that vary in power and frequency if I slide the volume control; when playing music, there is a lot of noise and &#8220;cutting&#8221; sounds between songs.<br />
These are not noticeable when using the integrated speakers but,they become really annoying once you use earphones.<br />
I am sorely disappointed with sound quality to say the least.</p>

<h3>Electronic noises</h3>

<p>On top of the annoying sounds from the sound chipset, the LCD inverter also makes a hissing sound that increases in volume when I lower the LCD brightness&#8230;<br />
Coupled with that, the processor also makes a hissing noise when it gets into its C4 power saving state&#8230;<br />
The noise is probably not high enough to get the laptop fixed but it might be great as a mosquito repellent.</p>

<h3>Boot &#8216;song&#8217;</h3>

<p>Apple knows best and they know that your only aim in life is to become a poster boy for the brand.<br />
When booting/rebooting your mac, it likes to play its welcome song that says &#8220;hey, over here, I&#8217;m a mac and I&#8217;m telling the world I&#8217;m booting up. Everyone listen how awesome I am!&#8221;.<br />
The perverse thing is that even if you have earphones plugged in (as in: you don&#8217;t want to disturb people around you) the boot song will be played on the speakers&#8230;<br />
Of course, there is no option anywhere to disable it.<br />
Apple knows best.<br />
After much trials, I found that booting under OSX, lowering the volume to zero, then rebooting under windows and changing the volume there would be OK: no more booting song -at least for now- and I can still change the volume in OSX and Windows.</p>

<h2>Conclusion</h2>

<p>Would I buy a Mac again knowing what I know now?<br />
Mmmm, probably <em>not</em>.<br />
I find the annoyances a bit too much relative to my expectations and my usage scenario.
To be fair, it&#8217;s not all bad and most of the time I&#8217;m happy with my mac but I find myself trying to avoid the things that infuriate me and it&#8217;s not really what I want from a laptop; it&#8217;s supposed to liberate me and give me the freedom I need to get things done, not get in the way.<br />
Re-adapting to a strangely layout keyboard, having to deal with Apple&#8217;s brand awareness arrogance, battling with stuff that you just normally take for granted, all this is a bit too much of a price to pay for what is essentially for me a Windows development machine.<br />
I prefer to waste my time actually getting things done rather than searching forums on how to keep Windows and OSX time in sync or bring back my machine for repair if a CD stays stuck in the CD Drive.</p>

<p>So, let&#8217;s say that our relationship is more ambivalent than needed to be.</p>

<h3>References</h3>

<p>Other links to pages of interest.</p>

<ul>
<li><a href="http://www.siftware.co.uk/blog/2007/05/things-that-suck-about-mac-os-x/">Things that suck about Mac OS X</a></li>
<li><a href="http://arewold.wordpress.com/2006/07/22/mac-os-x-annoyances-part-1-whats-up-with-the-mouse-acceleration/">Mac OS X annoyances: What’s up with the mouse acceleration?</a></li>
<li><a href="http://www.macworld.com/article/49691/2006/03/turbomice.html">A manual setting to change the speed factor in OSX</a></li>
<li>The <a href="http://plentycom.jp/en/steermouse/">Steermouse</a> driver to unleash your mouse in OSX</li>
<li>The <a href="http://lavacat.com/iMouseFix/index.html">iMouse</a> utility to correct pointer acceleration in OSX.</li>
<li>Another mouse utility called <a href="http://livecn.huasing.org/imouse/">iMouse</a>, for performing right-clicking in Windows this time.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2008/sysadmin-macbook-pro-after-the-honeymoon/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SysAdmin: Installing Windows Server 2008 x64 on a Macbook Pro</title>
		<link>http://blog.nkadesign.com/2008/mac-installing-windows-server-2008-x64-on-a-macbook-pro/</link>
		<comments>http://blog.nkadesign.com/2008/mac-installing-windows-server-2008-x64-on-a-macbook-pro/#comments</comments>
		<pubDate>Sun, 31 Aug 2008 06:04:39 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[MSAccess]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=149</guid>
		<description><![CDATA[My trusty old gigantic Sony Vaio is about 4 years old. It served me well and still works but it&#8217;s about to become my main development machine for the next couple of months and I can&#8217;t afford to have it die on me during that time. It was time to get something as gigantic and [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/apple.png" alt="security01.png" title="security01.png" align="left" width="53" height="64" hspace="5" vspace="5" border="0" />My trusty old gigantic <a href="http://etc.nkadesign.com/Linux/SonyVaio">Sony Vaio</a> is about 4 years old. It served me well and still works but it&#8217;s about to become my main development machine for the next couple of months and I can&#8217;t afford to have it die on me during that time.<br />
It was time to get something as gigantic and more up-to-date in terms of technology.</p>

<p>I use VMware on my main desktop to keep multiple OS setups that match typical configurations of my customer&#8217;s machines.<br />
This allows me to test my software before deployment and make sure everything works as expected.
It saved me many times from strange bugs and I would consider these final tests to be a mandatory step before deployment.<br />
My old trusty vaio would be hard pressed to run any of these without slowing down to a crawl.</p>

<p>I looked at some possible replacements. Initially I checked Lenovo&#8217;s offerings but they don&#8217;t seem to offer anything in large screen size (<a href="http://en.wikipedia.org/wiki/WUXGA">WUXGA</a> 1920&#215;1200) (Note, actually, <a href="http://www.tomshardware.com/news/Lenovo-W700-wacom-17-thinkpad,6117.html">they have</a>, but not really for me).<br />
Dito for Dell, not counting their humongous <a href="http://www.dell.com/content/products/productdetails.aspx/xpsnb_m1730?c=us&amp;l=en&amp;s=dhs">XPS M1730</a> luggable gaming machine that was wayyy over the top as a work computer, not to mention probably heavier than its volume in pure gold.</p>

<p><a title="Powerbook Pro" style="border:0;" href="/wp-content/uploads/images/MacBookPro_cr.png" rel="lightbox"><img title="Macbook Pro" src="/wp-content/uploads/images/MacBookPro_sm.png" width=250 Height=163 style="float:right;margin-left:10px;margin-bottom:5px;" /></a>
On a hint from a friend I checked out <a href="http://store.apple.com/hk/configure/MB166ZP/A?mco=NzUzNDY0">Apple&#8217;s online store</a> and saw they had a nice Macbook Pro configuration. I went to check it out in the retail store close to my office and they had that exact specification in stock, so, in what must have been the highest rated expense/time-to-think ratio of any decision I ever took, well, I bought it&#8230;</p>

<p>The spec, some bragging rights:</p>

<ul>
<li>Macbook Pro 17&#8243;</li>
<li>Core Duo T9500 2.6GHz processor</li>
<li>nVidia 8600M GT 512MB graphics card</li>
<li>200GB 7200rpm drive</li>
<li>Kingston 4GB DDR2 667MHz RAM</li>
<li>Hi Resolution 17&#8243; 1920&#215;1200 glossy screen</li>
</ul>

<p>It&#8217;s a <em>very</em> nice machine, Apple knows how to make nice hardware, there is no question there.<br />
OSX has some cool features, some of them still a bit foreign to me and some minor annoyances are creeping up, like Thunderbird&#8217;s not picking up my system date and time settings and displaying the date in the wrong format (a <a href="http://blog.nkadesign.com/2007/people-mind-your-dates-plz/">pet peeve</a> of me), probably not Apple&#8217;s fault but annoying nonetheless.<br />
So far so good and while I don&#8217;t mind using OSX for my browsing, email and creative stuff, that machine is meant to be running Windows Server 2008 x64 as a development platform.</p>

<h3>Why Windows Server 2008 x64?</h3>

<p>Well, it has some excellent features, a smaller footprint than Vista, all the aero eye candy, is apparently <a href="http://exo-blog.blogspot.com/2008/03/windows-2008-vista-done-right.html">noticeably faster than Vista</a> and has none of the nagging security prompt (you are considered administrator though, so keeping safe is entirely up to you).<br />
The 64 bit version can also address the full 4GB of RAM without limitation and all server features are optionally installable.<br />
By default, the installation is actually pretty minimal and you have to set services and options to get Windows configured as a proper workstation. It is after all, meant to be a server.<br />
Oh, I almost forgot that there is also support for <a href="http://en.wikipedia.org/wiki/Hyperv">HyperV</a>, although you must make sure you download the right version (if you list all available downloads in your MSDN subscription, you&#8217;ll see some that are explicitly without that technology).</p>

<h3>Installing Windows Server 2008 x64 is remarkably easy.</h3>

<ul>
<li>Get your hands on the ISO from your MSDN subscription or an install DVD from somewhere else (like a MS event, or even as a <a href="www.microsoft.com/windowsserver2008">free 240 days download from Microsoft</a>).</li>
<li>You&#8217;ll need to repackage the ISO as it won&#8217;t work properly (something to do with <a href="http://support.microsoft.com/kb/931708">non-standard file naming options</a>).<br />
It&#8217;s fairly easy if you follow the instructions from <a href="http://jowie.com/blog/post/2008/02/24/Select-CD-ROM-Boot-Type-prompt-while-trying-to-boot-from-Vista-x64-DVD-burnt-from-iso-file.aspx">Jowie&#8217;s website</a> <em>(<a href="/wp-content/uploads/2008/08/Select-CD-ROM-Boot-Type-prompt-while-trying-to-boot-from-Vista-x64-DVD-burnt-from-iso-file.aspx.htm">cached version</a>)</em>: you can get the <a href="http://www.imgburn.com/">ImgBurn</a> software for free as well, which is a good find in itself. It should&#8217;t take more than 30 minutes to repackage the DVD.</li>
<li>In OSX, go to Applications > Utilities > Boot camp and follow the instructions on screen.<br />
You will be able to resize the default partition by just moving the slider. I left 60GB for OSX and allocated the rest to Windows. The good thing is that OSX can read Windows partitions, so you can always store data there. Windows however, can&#8217;t read the <a href="http://en.wikipedia.org/wiki/HFS_Plus">HFS+</a> mac file system, although there are some third-party tools that can do it  <a href="http://www.ufsexplorer.com/">[1]</a> <a href="http://www.macdisk.com/prospen.php3">[2]</a> <a href="http://www.acutesystems.com/">[3]</a>.</li>
<li>Insert your repackaged DVD and Bootcamp will have rebooted the machine.<br />
After a few minutes of blank screen (and no HDD activity light to let you know something is happening), windows setup launches.</li>
<li>You will be then prompted with the choice of partition to install to.<br />
Select the one named BOOTCAMP, then click the <em>advanced options</em> button and click <em>format</em>.
From there one, windows will install everything, then reboot, then carry on installing, then reboot one last time.</li>
<li>Now, insert your <em>OSX recovery CD 1</em>. It should automatically launch the driver installation.<br />
Once done, you&#8217;ll reboot to a nice, full-resolution windows prompt.</li>
<li>All drivers will have been installed correctly except the one for Bluetooth. To easily solve that issue, just go to <a href="http://www.harbar.net/Default.aspx">Spencer Harbar&#8217;s website</a> and read <a href="http://www.harbar.net/archive/2008/06/13/Enabling-Bluetooth-on-MacBook-Pro-and-Windows-Server-2008-x64.aspx">how to install the Bluetooth drivers</a>. Takes 5 minutes tops.</li>
</ul>

<h3>The final touches</h3>

<p>A few notes to quickly get things running as expected.</p>

<ul>
<li>Get the most of your configuration by following the <a href="http://blogs.msdn.com/vijaysk/archive/2008/02/11/using-windows-server-2008-as-a-super-desktop-os.aspx">list of tweaks from Vijayshinva Karnure</a> from Microsoft India.</li>
<li>There are <a href="http://www.win2008workstation.com/wordpress/">more tweaks</a>, and <a href="http://weblogs.asp.net/israelio/archive/2008/02/21/windows-server-2008-as-workstation.aspx">even more tweaks</a> available as well (don&#8217;t forget to enable <a href="http://www.2008server.org/?q=SuperFetch">Superfetch</a>).</li>
<li>Microsoft has a whole KB entry on <a href="http://support.microsoft.com/kb/947036">enabling user experience</a>.</li>
<li>In the Control Panel > System > Advanced System Settings > Advanced > Settings > Advanced > Processor scheduling, set to <em>Programs</em> instead of <em>Background services</em>.</li>
<li>Activate your copy of Windows using Control Panel > System.<br />
I was getting an error code 0x8007232B <em>DNS name does not exist</em> error. To force activation, just click on the <em>Change Product Key</em> button and re-enter the same key you used during install.<br />
Windows will activate straight away.</li>
<li>When booting your Macbook, press the <em>Option</em> key and you will be presented a list of boot choices.</li>
<li>You can check on <a href="http://www.apple.com/support/bootcamp/">Apple&#8217;s Bootcamp webpage</a> other information about how to use the track pad, keyboard layouts etc,</li>
</ul>

<h3>References</h3>

<ul>
<li><a href="http://stuartd.blogspot.com/2008/04/windows-server-2008-boot-camp-and.html">http://stuartd.blogspot.com/2008/04/windows-server-2008-boot-camp-and.html</a></li>
<li><a href="http://burnetts.homeserver.com/post/Windows-Server-2008-on-the-Mac.aspx">http://burnetts.homeserver.com/post/Windows-Server-2008-on-the-Mac.aspx</a></li>
<li><a href="http://csaborio.wordpress.com/2008/03/28/installing-windows-server-2008-on-a-mac-book-pro/">http://csaborio.wordpress.com/2008/03/28/installing-windows-server-2008-on-a-mac-book-pro/</a></li>
<li><a href="http://exo-blog.blogspot.com/2008/03/windows-2008-vista-done-right.html">http://exo-blog.blogspot.com/2008/03/windows-2008-vista-done-right.html</a></li>
<li><a href="http://www.sturmnet.org/blog/archives/2008/10/02/stuff-i-use-on-the-mac/">http://www.sturmnet.org/blog/archives/2008/10/02/stuff-i-use-on-the-mac/</a> Lots of software recommendations for someone switching from Windows to the Mac.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2008/mac-installing-windows-server-2008-x64-on-a-macbook-pro/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Linux: AutoCAD DWG to SVG preview conversion.</title>
		<link>http://blog.nkadesign.com/2008/linux-autocad-dwg-to-svg-preview-conversion/</link>
		<comments>http://blog.nkadesign.com/2008/linux-autocad-dwg-to-svg-preview-conversion/#comments</comments>
		<pubDate>Fri, 18 Jul 2008 09:16:15 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=95</guid>
		<description><![CDATA[Years ago I did a small utility to convert DWG or DXF files into a vector-graphic, zoomable, SVG preview. The Linux command-line utility was used in a larger drawing management application that I had built before I left that company for greener pastures. The Linux server-based application would scan the vast (100,000s of CAD drawings) [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/linux.png" alt="Linux" title="Linux" align="left" width="54" height="64" hspace="5" vspace="5" border="0" />
Years ago I did a <a href="http://etc.nkadesign.com/Download/Cad2svg">small utility</a> to convert <a href="http://en.wikipedia.org/wiki/.dwg">DWG</a> or <a href="http://en.wikipedia.org/wiki/AutoCAD_DXF">DXF</a> files into a vector-graphic, zoomable, <a href="http://en.wikipedia.org/wiki/Svg">SVG</a> preview.
The Linux command-line utility was used in a larger drawing management application that I had built before I left that company for greener pastures.</p>

<p>The Linux server-based application would scan the vast (100,000s of <a href="http://en.wikipedia.org/wiki/Computer-aided_design">CAD drawings</a>) and, depending on their format, attempt to create thumbnails and extract textual information from them and populate a database so we could easily find related drawings through a simple web-interface.</p>

<p><img src='/wp-content/uploads/2008/07/sshot-390.png' alt='CAD File'  style="float:right;margin-left:10px;margin-bottom:5px"/> The software would present thumbnails of the drawings; when the drawing was in DWG or DXF format, the thumbnail would be an SVG vector representation of the original drawing instead of an image. That made the preview much more useful as you could zoom in and still retain enough detail to ascertain if the drawings was actually what you were looking for.</p>

<p>Other file formats (<a href="http://en.wikipedia.org/wiki/Tagged_Image_File_Format">TIFF</a>, <a href="http://en.wikipedia.org/wiki/HPGL">HPGL</a> plots, etc) were transformed into <a href="http://en.wikipedia.org/wiki/Portable_Network_Graphics">PNG</a> image previews that were saved into 2 size: a small thumbnail, good enough to be displayed in a list, and a larger one that would show more details.</p>

<p>The server software was written in <a href="http://www.perl.org/">Perl</a>, with some of the converters in <a href="http://en.wikipedia.org/wiki/C_(programming_language)">C</a>. Every night, the server would go through the whole tree of drawings on the filesystem, looking for drawings it hadn&#8217;t seen before and it would pass them to the appropriate plug-in for extracting text -where possible- and create thumbnails.</p>

<p>Memories of fun projects&#8230;</p>

<h3>Download links:</h3>

<ul>
<li>cad2svg: <a href="http://etc.nkadesign.com/Download/Cad2svg">http://etc.nkadesign.com/Download/Cad2svg</a></li>
<li>cad2text: <a href="http://etc.nkadesign.com/Download/Cad2text">http://etc.nkadesign.com/Download/Cad2text</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2008/linux-autocad-dwg-to-svg-preview-conversion/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>MS Access: checking network paths without freezing your application</title>
		<link>http://blog.nkadesign.com/2008/ms-access-checking-network-paths-without-freezing-your-application/</link>
		<comments>http://blog.nkadesign.com/2008/ms-access-checking-network-paths-without-freezing-your-application/#comments</comments>
		<pubDate>Fri, 20 Jun 2008 08:48:31 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[MSAccess]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=93</guid>
		<description><![CDATA[Access programming is inherently single-threaded. That&#8217;s usually OK as most operations are sequential anyway and it keeps things simple at the programming level. There are times though where the lack of ability to run code on another thread is sorely missing: anything that takes a long time to run will just freeze the application, making [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/access.png" alt="Microsoft Access" title="Microsoft Access" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />
Access programming is inherently single-threaded. That&#8217;s usually OK as most operations are sequential anyway and it keeps things simple at the programming level.<br />
There are times though where the lack of ability to run code on another thread is sorely missing: anything that takes a long time to run will just freeze the application, making it unresponsive and appearing to be locked and about to crash to the user.</p>

<h3>Checking for the existence of network paths</h3>

<p>Checking for the existence of network paths (directories or files) is one of these issues that can freeze an application for 30 seconds or more if the folder is not accessible.</p>

<p>This is a type of problem that benefits greatly from running in a separate thread: it can take such a long time that the best way to check for these remote paths is to launch the verification for their existence outside of Access and somehow get the result back and cache it for the current session so we don&#8217;t have to suffer these delays again every time we check for that path&#8217;s existence.</p>

<p>One easy way to do achieve that goal is to create plain DOS batch files that execute hidden from view, create a result file when they complete their task and delete themselves automatically when they are finished.</p>

<h3>How to use it</h3>

<p>Download the sample database below then just add the <code>FileUtilities</code>, <code>HashTable</code> and <code>MD5</code> modules to your project and you can use the code as such:</p>

<p><textarea name="code" class="vb:nogutter">
Dim status As AsyncDirectoryStatus
status = FileUtilities.PathExistAsync("\\123.45.67.89\shared folder")
</textarea>
The <code>status</code> variable will return either of the following values:</p>

<ul>
<li><code>AsyncDirectoryStatus.OK</code> if the path was found.</li>
<li><code>AsyncDirectoryStatus.NotFound</code> if the path was not found (either because it doesn&#8217;t exist or you don&#8217;t have the rights to access it).</li>
<li><code>AsyncDirectoryStatus.Checking</code> if the verification is in progress and we haven&#8217;t received a definite answer yet.<br />
It&#8217;s up to you to decide how you want to handle that case. You could periodically check it, like I did in the example database, or you could disable the controls until you&#8217;re getting a confirmed result (by checking every time the user performs some action, like moving from record to record in a datasheet for instance).</li>
</ul>

<p>You can call <code>PathExistAsync</code> as often as you want to check the status: it will not slow down your application (read the <em>optional arguments</em> section below though).<br />
The result of the verification is cached, so querying the existence of the path is actually only done once; the result of subsequent queries for the same path is just instantly retrieved from memory.</p>

<h3>Optional arguments</h3>

<p>If you want to force the actual re-checking of a path without using the cached value, you can simply pass the <code>ForceCheck</code> optional parameter:
<textarea name="code" class="vb:nogutter">
Dim status As AsyncDirectoryStatus
status = FileUtilities.PathExistAsync("\\123.45.67.89\shared folder", ForceCheck:=true)
</textarea>
The first time you query for a path (or force it to be rechecked) there will be a short 150ms delay to give a chance to the function to return its result straight away (in case the path can be resolved quickly).<br />
This may not be desirable if you&#8217;re checking a bunch of directories at a time. For instance, this is what I do when my application launches:
<textarea name="code" class="vb:nogutter">
' Check a bunch of paths in parallel
PathExistAsync strPathToQualityDocuments, NoDelay:=true
PathExistAsync strPathToFinancialDocuments, NoDelay:=true
PathExistAsync strPathToShippingDocuments, NoDelay:=true
PathExistAsync strPathToPurchasingDocuments, NoDelay:=true
</textarea>
By querying the existence of all these paths as soon as my application launches, I am starting the verification process without introducing delays in the application itself: each verification will start in its own process, in parallel to the main application.<br />
Later in the application, when I need to actually use these paths, their result is likely to be known.</p>

<h3>How it works</h3>

<p>The <code>FileUtilities</code> module contains the main code.<br />
In it, the <code>PathExistAsync</code> function works in slightly different ways depending on whether it&#8217;s the first time it is being called for a particular path or not.</p>

<p><strong>The first time</strong><br />
The first time the function is called for a given path, we create in the user&#8217;s temporary folder the small batch file whose name is simply a MD5 hash (see below) of the path with <code>.bat</code> appended to it.<br />
This batch file simply checks for the existence of the path and will create a small file (whose name is the MD5 hash of the path) with either <code>0</code> or <code>1</code> in it depending on the result of the verification.<br />
We initially cache the status of the verification for the Path into the <code>AsyncDirectories</code> hashtable (see below) as <code>Checking</code>.</p>

<p>Example of batch file automatically created to verify a path:
<textarea name="code" class="bat">
IF NOT EXIST "\\123.56.78.9\going nowhere" GOTO NOTEXIST
echo 1 > "C:\DOCUME~1\Renaud\LOCALS~1\Temp\463C7367D8329BD6209A65A70A7DA08C"
GOTO END
:NOTEXIST
echo 0 > "C:\DOCUME~1\Renaud\LOCALS~1\Temp\463C7367D8329BD6209A65A70A7DA08C"
:END
DEL %0</textarea>
The Batch file name is <code>463C7367D8329BD6209A65A70A7DA08C.bat</code> where the long number is actually the MD5 hash of the path we&#8217;re checking <code>\\123.56.78.9\going nowhere</code>.</p>

<p><strong>Getting back the result</strong><br />
Whenever the <code>PathExistAsync</code> function is called, we check the currently cached result from the <code>AsyncDirectories</code> hastable.<br />
If it is still <code>Checking</code> then we try to verify if we the result file has been created from the running batch. If not, we just return the same status, if yes, we read the result from the file, save it in the hashtable and delete the result file.</p>

<h3>Useful libraries</h3>

<p>The code makes use of 2 extremely useful libraries that I end up using quite often:</p>

<ul>
<li><p><strong>a <a href="http://en.wikipedia.org/wiki/Hash_table">HashTable</a> implementation.</strong><br />
It makes it easy to create hashtable objects (otherwise known as <em>Associative Arrays</em>) to store and retrieve key/value pairs quickly.<br />
Hashtables are often used to cache data and can be thought of arrays where the index is a string value instead of an number.<br />
Here I use a hashtable to keep track of the paths we&#8217;ve checked and their result.</p></li>
<li><p><strong>a <a href="http://en.wikipedia.org/wiki/Md5">MD5</a> hash implementation.</strong><br />
MD5 is a way to get a somewhat unique fixed-length value from a chunk of data.<br />
It&#8217;s a mathematical function that guarantees that a small change in input (say a single bit in the input data) has a large effect on the output value (a totally different number will be generated) and that you can&#8217;t reverse the function (you can&#8217;t obtain the input just by looking at the output).<br />
It is often used in security applications to transform sensitive data like passwords into unique values that can be (somewhat) safely stored because you can&#8217;t easily reverse a md5.<br />
Well, MD5 are <a href="http://en.wikipedia.org/wiki/Md5#Vulnerability">not that secure</a> any longer but here we just use their ability to transform our path into a unique number that we can easily use as a filename and a key for our hash to retrieve the current status of the path being checked.</p></li>
</ul>

<h3>Sample database</h3>

<p><a href='http://blog.nkadesign.com/wp-content/uploads/2008/06/pathexistasync01.zip' title='Sample database'><img src="/wp-content/uploads/2008/05/download.png" alt="Download" /></a>Download the <a href='http://blog.nkadesign.com/wp-content/uploads/2008/06/pathexistasync01.zip' title='Test database'>PathExistAsync01.zip (67KB)</a> containing the  <strong>Access 2007 ACCDB</strong> database.</p>

<p><a href='http://blog.nkadesign.com/wp-content/uploads/2008/06/pathexistasync02b.zip' title='Sample database'><img src="/wp-content/uploads/2008/05/download.png" alt="Download" /></a>Download the <a href='http://blog.nkadesign.com/wp-content/uploads/2008/06/pathexistasync02b.zip' title='Test database'>PathExistAsync02b.zip (121KB)</a> containing the <strong>MDB</strong> database<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup> (untested as I only have Access 2007).</p>

<p><center><img src="/wp-content/uploads/2008/06/sshot-112.png" alt="Test Database" /></center></p>

<h3>License</h3>

<p>Please refer to the source code in the database for the exact licensing terms.<br />
Note that the license only refers to code by me. When code from other sources is used, you will have to conform to their own licensing terms.</p>

<p><!--- Code source license -->
<a rel="license" href="http://creativecommons.org/licenses/by/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by/3.0/80x15.png"/></a><br/>This <span xmlns:dc="http://purl.org/dc/elements/1.1/" href="http://purl.org/dc/dcmitype/Text" rel="dc:type">work</span> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 Unported License</a>.</p>

<h3>References</h3>

<ul>
<li><a href="http://www.bytemycode.com/snippets/snippet/251/119/">Hashtable implementation in VB</a></li>
<li><a href="http://www.di-mgt.com.au/crypto.html">Cryptography Software Code</a> (for the MD5 hash implementation in VB)</li>
</ul>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>A specific version for Access 2000 now included in the archive (updated 25JUL2008).&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2008/ms-access-checking-network-paths-without-freezing-your-application/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Now I can prove Microsoft is an evil corporation</title>
		<link>http://blog.nkadesign.com/2008/now-i-can-prove-microsoft-is-an-evil-corporation/</link>
		<comments>http://blog.nkadesign.com/2008/now-i-can-prove-microsoft-is-an-evil-corporation/#comments</comments>
		<pubDate>Fri, 13 Jun 2008 03:52:19 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Fun]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=89</guid>
		<description><![CDATA[It&#8217;s official, Gold Member is working for Microsoft, apparently doing some evil research in an unnamed Microsoft lair. Here is the absolute proof: He calls himself Erik Meijer now and apparently solved his skin issue but you only need to listen to them to know it&#8217;s the same person. Yes, they are both Dutch, which [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/mood02.png" alt="mood02.png" title="mood02.png" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />It&#8217;s official, Gold Member is working for Microsoft, apparently doing some evil research in an unnamed Microsoft lair.</p>

<p>Here is the absolute proof:</p>

<p><center><img src="/wp-content/uploads/2008/06/goldmember01.jpg" alt="Evil Gold Member" /></center>
<center><img src="/wp-content/uploads/2008/06/217552217_57aa333e41_o.jpg" alt="Erik Meijer" /></center></p>

<p>He calls himself <a href="http://research.microsoft.com/~emeijer/">Erik Meijer</a> now and apparently solved his skin issue but you only need to listen to them to know it&#8217;s the same person.</p>

<p><center><object width="320" height="243"><param name="movie" value="http://www.youtube.com/v/aRtNfb6D3Mc&#038;hl=en"></param><embed src="http://www.youtube.com/v/aRtNfb6D3Mc&#038;hl=en" type="application/x-shockwave-flash" width="320" height="243"></embed></object></center></p>

<p><center><a target="_blank" href="
http://channel9.msdn.com/posts/AdamKinney/Erik-Meijer-Democratizing-the-Cloud/"><img src="/wp-content/uploads/2008/06/sshot-109.png" alt="Erik Meijer on video" /></a></center></p>

<p>Yes, they are both Dutch, which in itself is already proof enough of their evilness and further confirms they are one and the same.</p>

<p>There is some talk that Microsoft has been the refuge of all that is Bad, and some even say that Steve Ballmer may be none other than Dr Evil himself&#8230;</p>

<p>That being said, you should check out videos on <a href="http://channel9.msdn.com/">Channel 9</a> where <a href="http://research.microsoft.com/~emeijer/">Erik Meijer</a> appears. Despite his obvious evilness, he is actually one of the very bright and interesting characters at Microsoft and always has fascinating things to say about programming languages:</p>

<ul>
<li><a href="http://channel9.msdn.com/shows/Going+Deep/Expert-to-Expert-Erik-Meijer-and-Bertrand-Meyer-Objects-Contracts-Concurrency-Sleeping-Barbers/">Expert to Expert: Erik Meijer and Bertrand Meyer -- Objects, Contracts, Concurrency, Sleeping Barbers</a></li>
<li>Tier Splitting Volta: Who. What. How. Why -- <a href="http://channel9.msdn.com/shows/Going+Deep/Tier-Splitting-Volta-Who-What-How-Why-Part-1/">Part 1</a> and  <a href="http://channel9.msdn.com/shows/Going+Deep/Tier-Splitting-Volta-Who-What-How-Why-Part-2/">Part 2</a></li>
<li><a href="http://channel9.msdn.com/shows/Going+Deep/Erik-Meijer-Functional-Programming/">Erik Meijer: Functional Programming</a></li>
<li><a href="http://channel9.msdn.com/shows/Going+Deep/Erik-Meijer-Gilad-Bracha-Mads-Torgersen-Perspectives-on-Programming-Language-Design-and-Evolution/">Erik Meijer, Gilad Bracha, Mads Torgersen: Perspectives on Programming Language Design and Evolution</a></li>
<li><a href="http://channel9.msdn.com/posts/scobleizer/Paul-Vick-and-Erik-Meijer-Dynamic-Programming-in-Visual-Basic/">Paul Vick and Erik Meijer -- Dynamic Programming in Visual Basic</a></li>
<li><a href="http://channel9.msdn.com/posts/AdamKinney/Erik-Meijer-Democratizing-the-Cloud/">Erik Meijer: Democratizing the Cloud</a></li>
<li><a href="http://channel9.msdn.com/shows/Going+Deep/Anders-Hejlsberg-Herb-Sutter-Erik-Meijer-Brian-Beckman-Software-Composability-and-the-Future-of/">Anders Hejlsberg, Herb Sutter, Erik Meijer, Brian Beckman: Software Composability and the Future of the CLR</a></li>
<li>JAOO 2007: Joe Armstrong -- On Erlang, OO, Concurrency, Shared State and the Future, <a href="http://channel9.msdn.com/posts/Charles/JAOO-2007-Joe-Armstrong-On-Erlang-OO-Concurrency-Shared-State-and-the-Future-Part-1/">Part 1</a> and <a href="http://channel9.msdn.com/posts/Charles/JAOO-2007-Joe-Armstrong-On-Erlang-OO-Concurrency-Shared-State-and-the-Future-Part-2/">Part 2</a></li>
<li>CLR Team Tour -- The Future of Languages (PDC panel preview) -- <a href="http://channel9.msdn.com/posts/scobleizer/CLR-Team-Tour-Part-I-Preparing-for-the-PDC/">Part 1</a> and <a href="http://channel9.msdn.com/posts/scobleizer/CLR-Team-Tour-Part-II-The-Future-of-Languages-PDC-panel-preview/">Part 2</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2008/now-i-can-prove-microsoft-is-an-evil-corporation/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Linux sysadmin: a short RAID trouble-shooting story</title>
		<link>http://blog.nkadesign.com/2008/linux-sysadmin-a-short-troubleshooting-story/</link>
		<comments>http://blog.nkadesign.com/2008/linux-sysadmin-a-short-troubleshooting-story/#comments</comments>
		<pubDate>Sat, 07 Jun 2008 11:15:29 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=86</guid>
		<description><![CDATA[I recently had an issue at a remote location (12000km away) where the old multi-purpose Linux server that had been working for the past 5 years wouldn&#8217;t boot again after a nasty power failure. The server was used as a firewall, a local email store, a file server and a backup server, so its failure [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/linux.png" alt="Linux" title="Linux" align="left" width="54" height="64" hspace="5" vspace="5" border="0" />
I recently had an issue at a remote location (12000km away) where the old multi-purpose Linux server that had been working for the past 5 years wouldn&#8217;t boot again after a nasty power failure.<br />
The server was used as a firewall, a local email store, a file server and a backup server, so its failure is a big deal for the small business that was using it.<br />
<center><img src="http://blog.nkadesign.com/wp-content/uploads/2008/06/266169495_863b3d935f.jpg" alt="RAID explained" /><br />
<small>RAID configurations explained</small></center>
You can&#8217;t always have complete redundancy, so some amount of bad crash is to be expected over the years. Fortunately, I always construct my servers around a simple software RAID1 array and that leaves some hope for recovery.<br />
In this instance, the server would start and then miserably fail in a fashion that would suggest a hardware failure of some sort. Not being able to be physically present and having no dedicated system admin on location, I directed the most knowledgeable person there to use a spare internet router to recover Internet connectivity and connect one of the disk to another Linux server (their fax server) through a USB external drive.</p>

<p>Doing this, I was able to remotely connect to the working server and access the disk, mount it and access the data.</p>

<h3>Salvaging the data</h3>

<p>Once one of the RAID1 drives was placed into the USB enclosure and connected to the other available Linux box it was easy to just remount the drives:</p>

<p><code>fdisk</code> will tell us which partitions are interesting, assuming that <code>/dev/sdc</code> is our usb harddrive:</p>

<pre><code>[root@fax ~]# fdisk -l /dev/sdc

Disk /dev/sdc: 81.9 GB, 81964302336 bytes
16 heads, 63 sectors/track, 158816 cylinders
Units = cylinders of 1008 * 512 = 516096 bytes  

Device      Boot    Start         End      Blocks   Id  System
/dev/sdc1   *           1         207      104296+  fd  Linux raid autodetect
/dev/sdc2             208       20526    10240776   fd  Linux raid autodetect
/dev/sdc3           20527       22615     1052856   fd  Linux raid autodetect
/dev/sdc4           22616      158816    68645304    f  W95 Ext'd (LBA)
/dev/sdc5           22616      158816    68645272+  fd  Linux raid autodetect
</code></pre>

<p>We can&#8217;t simply <code>mount</code> the partitions, they need to be assembled into a RAID partition first:</p>

<pre><code>[root@fax ~]# mdadm --assemble /dev/md6 /dev/sdc1 --run
mdadm: /dev/md6 has been started with 1 drive (out of 2).
</code></pre>

<p>The <code>--run</code> argument forces the RAID partition to be assembled, otherwise, <code>mdadm</code> will complain that there is only a single drive available instead of the 2 -or more- it would expect.</p>

<p>Now simply mount the assembled partition to make it accessible in <code>/mnt</code> for instance:</p>

<pre><code>[root@fax ~]# mount /dev/md6 /mnt
</code></pre>

<p>We can now salvage our data by repeating this process for every partition.<br />
Using RAID1 means you have at least 2 disks to choose from, so if one is damaged beyond repair, you may be lucky and the mirror one on the other drive should work.</p>

<p>If the drives are not physically damaged but they won&#8217;t boot, you can always use a pair (or more) of USB HDD enclosures and reconstruct the RAID arrays manually from another Linux box.</p>

<h3>Planning for disasters</h3>

<p>The lesson here is about planning: you can&#8217;t foresee every possible event and have contingencies for each one of them, either because of complexity or cost,  but you can easily make your life much easier by planning ahead a little bit.</p>

<p>Most small businesses cannot afford dedicated IT staff, so they will usually end-up having the least IT-phobic person become their &#8216;system administrator&#8217;.<br />
It&#8217;s your job as a consultant/technical support to ensure that they have the minimum tools at hand to perform emergency recovery, especially if you cannot intervene yourself quickly.</p>

<h3>On-Site emergency tools</h3>

<p>In every small business spare parts closet there should be at least:</p>

<ul>
<li>Whenever possible, a <strong>spare Linux box</strong>, even if it&#8217;s just using older salvaged components (like a decommissioned PC). Just have a generic Linux install on it and make sure it is configured so it can be plugged in and accessed from the network.</li>
<li>a <strong>spare US$50 router</strong>, preferably pre-configured to be a temporary drop-in replacement for the existing router/firewall. Ideally, configure it to forward port 22 (SSH) to the spare Linux box so you can easily access the spare box from outside.</li>
<li>USB external <strong>hard-drive enclosure</strong>.</li>
<li>a spare PC <strong>power supply</strong>.</li>
<li>some network cables, a couple of screwdrivers.</li>
</ul>

<p>There are many more tools, such as rescue-CDs (like bootable Linux distributions), spare HDD, etc that can be kept but you have to remember that your point of contact need to be able to be your eyes and hands, so the amount of tools you provide should match their technical abilities.<br />
Don&#8217;t forget to clearly label confusing things like network ports (LAN, WAN) on routers, cables and PCs.</p>

<p>The point is that if you can&#8217;t be on site within a short period of time, then having these cheap tools and accessories already on site mean that your customers can quickly recover just by following your instructions on the phone.<br />
Once everything is plugged-in, you should be able to remotely carry-out most repairs.</p>

<h3>Resources</h3>

<ul>
<li><a href="http://www.linuxconfig.org/Linux_Software_Raid_1_Setup">Linux software RAID1 setup</a></li>
<li><a href="http://dailypackage.fedorabook.com/index.php?/categories/11-System-Recovery-Week">Fedora System Recovery Week</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2008/linux-sysadmin-a-short-troubleshooting-story/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>MS Access: Enhanced Message Box Replacement</title>
		<link>http://blog.nkadesign.com/2008/ms-access-enhanced-message-box-replacement/</link>
		<comments>http://blog.nkadesign.com/2008/ms-access-enhanced-message-box-replacement/#comments</comments>
		<pubDate>Tue, 20 May 2008 10:39:54 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Business]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[MSAccess]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=76</guid>
		<description><![CDATA[This project provides a custom and enhanced message box replacement for the default MsgBoxfound in Access. A Test database for Access 2007 is available at the bottom of this post. (Updated Tuesday 17MAR2009.) What&#8217;s wrong with the default MsgBox The default message box in Access is sometimes useful to warn, inform or ask confirmation from [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/access.png" alt="Microsoft Access" title="Microsoft Access" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />
This project provides a custom and enhanced message box replacement for the default <code>MsgBox</code>found in Access. A Test database for Access 2007 is available at the bottom of this post. (<strong>Updated Tuesday 17MAR2009.</strong>)</p>

<h3>What&#8217;s wrong with the default MsgBox</h3>

<p>The default message box in Access is sometimes useful to warn, inform or ask confirmation from the user.
<center><img src="/wp-content/uploads/2008/05/sshot-79.png" alt="Standard MsgBox" /></center></p>

<p>It has, however, a few drawbacks:</p>

<ul>
<li>It is bland: the standard message box does not even follow the currently selected Office 2007 scheme.</li>
<li>The amount of text it can display is limited: if you try to display too much text it will be truncated.</li>
<li>You can&#8217;t copy or save the content of the message.</li>
<li>Because popup boxes are viewed as intrusive, people tend not to read them and end-up closing message boxes before they realize they may have contained useful information.</li>
<li>They only displays plain text: you cannot format the message to draw attention to the key points.</li>
<li>They are blocking, meaning that nothing can happen in the main application while the box is displayed (it can&#8217;t even shut down).</li>
</ul>

<p>Sometimes you need to display an important message or require users to make take a decision.<br />
Message boxes are not to be abused but they serve a useful purpose.</p>

<h3>An enhanced message box</h3>

<p>Rather than using the bland standard message box you can now have something a bit more customized.</p>

<p><strong>Plain Text</strong> version of the enhanced custom message box under the Office Blue Colour Scheme:
<center><img src="/wp-content/uploads/2008/05/sshot-81.png" alt="Plaintex Enhanced Message Box" /></center></p>

<p><strong>RichText</strong> version of the enhanced custom message box under the Office Black Colour Scheme:
<center><img src="/wp-content/uploads/2008/05/sshot-78.png" alt="RichText Enhanced Message Box" /></center></p>

<p>Here are the features of the enhanced message box:</p>

<ul>
<li>It is entirely compatible with the standard one: just change <code>MsgBox</code> to <code>Box</code> 
using <em>find and replace</em> should be enough (see tip below to avoid getting strange errors).</li>
<li>It allows the user to simply click on a button to copy the content of the message to 
the clipboard or save it to a text file to a configurable default location.</li>
<li>It looks and feels like it belongs to the main application, following its colour scheme.</li>
<li>It attempts to prevent users from blindly closing the modal box reading the message: buttons will first be inactive for a configurable amount of time. It&#8217;s not a perfect solution, but it is quite effective.</li>
<li>There is a <code>RichBox</code> version that can display rich HTML content, not just plain text, so important parts of the message can be formatted in a useful way.</li>
<li>It is able to display large amount of data. While it&#8217;s not something you usually want, it may be useful for the message box to display more text in some situations (log or tracing information, legal documentation, etc).</li>
<li>Rather than sprinkling your code with &#8220;<code>&amp; vbCrLf &amp; _</code>&#8221; uglies, you can embed newlines in the text itself by using C-style &#8220;<code>\n</code>&#8221; escape sequences that will automatically be transformed into the appropriate newlines. Makes for clearer code and less typing.</li>
<li>Because you get the source, you can easily customise the message box with new icons and colours to better match your overall application&#8217;s personality.</li>
<li>It is non-blocking: if your application forces users to log-off after a certain amount of inactivity, the enhanced message box will just close rather than prevent Access from shutting down like the standard <code>MsgBox</code> does. Of course, it&#8217;s up to you to decide how to handle that gracefully, if at all.</li>
<li>It properly displays the expected button captions based on the language of the operating system, so it behaves very much like the default <code>MsgBox</code> (for instance, it will properly display &#8220;<em>Cancel</em>&#8221; on English systems and &#8220;<em>Annuler</em>&#8221; on French ones).</li>
<li>It also properly plays the system sounds associated with the type of message. You can also enable or disable the sound effect as needed.</li>
</ul>

<h3>How to use it</h3>

<p>Download the demo below and copy (drag &amp; drop) the following into your application:</p>

<ul>
<li>the <code>FormDialog</code> form,</li>
<li>the <code>API_GetTextMetrics</code> module,</li>
<li>the <code>Dialog</code> module.</li>
</ul>

<p>If you rename the <code>FormDialog</code>, make sure you replace any occurrence to it in the code, in particular in the <code>Dialog</code> module.</p>

<p>Since the enhanced message box is just a replacement for the standard one, you just use it like you  would use the <code>MsgBox</code>.<br />
<textarea name="code" class="vb:nogutter">
'-----------------------------------------------------------------------------
' Simple use of the Plaintext box
' Note the use of n that will be converted into a newline
Dialog.Box "This is a plaintext message.\nClick OK to dismiss", 
           vbOKOnly+vbinformation, _
           "Message Title"

'-----------------------------------------------------------------------------
' Getting the result back
Dim dr as vbMsgBoxresult
dr = Dialog.Box("Are you sure you want to delete?", _
     vbYesNoCancel+vbQuestion, "Confirm action")
if (dr = vbYes) then DeleteRecords

'-----------------------------------------------------------------------------
' Using named parameters
Dialog.Box Prompt:="All your bases are belong to us", _
           Buttons:=(vbOkOnly+vbCritical), _
           Title:="Bad error"

'-----------------------------------------------------------------------------
' Using the RichBox to display simple HTML
' The first line will be bold, then the word 'button' will be printed in red
' Here the n will be escaped to '<br/>' tags to simulate newlines.
Dialog.RichBox "<strong>This is a bold message</strong>.\n" & _
               "Click the <font color=""#FF0000"">button</font> to dismiss.", 
               vbOKOnly+vbinformation, _
               "RichText Message Title"
</textarea>
There are a few additional settings that can be used to change the behaviour of the enhanced message boxes.<br />
One is that you can adjust the delay before the buttons become activated.<br />
<textarea name="code" class="vb:nogutter">
'-----------------------------------------------------------------------------
' Use the ButtonDelay to specify the time in seconds before the buttons become activated
' The default is 2s. Use 0 to activate the buttons immediately.
Dialog.Box Prompt:="All your bases are belong to us", _
           Buttons:=(vbOkOnly+vbCritical), _
           Title:="Bad error",
           ButtonDelay:=1

'-----------------------------------------------------------------------------
' Change the default delay value.
' To disable the activation delay
Dialog.DefaultButtonDelay = 0

' To make the user wait 3 seconds before they can press any button
Dialog.DefaultButtonDelay = 3</textarea>
Another one is that you can enable or disable whether beeps should be played or not.<br />
<textarea name="code" class="vb:nogutter">
'-----------------------------------------------------------------------------
' Use AllowBeep to specify whether beeps should be played when the message box opens
' By default, they are.
Dialog.Box Prompt:="All your bases are belong to us", _
           Buttons:=(vbOkOnly+vbCritical), _
           Title:="Bad error",
           AllowBeep:=false

'-----------------------------------------------------------------------------
' Change the default behaviour. This is true by default.
Dialog.DefaultAllowBeep = false
</textarea>The last settings is the folder where we should save the content of the message when the user clicks the Save button on the message box.<br />
<textarea name="code" class="vb:nogutter">
'-----------------------------------------------------------------------------
' Change the save folder.
' By default, the text messages will be saved in the same directory as the database.
' Here we want them to be saved to a temp directory
Dialog.DefaultSavedTextFileFolder= "C:temp"
</textarea>
These few settings make the enhanced message box more customizable.</p>

<h3>Large text</h3>

<p>The standard <code>MsgBox</code> cannot display much text. On the other hand, there is no real limitation to the amount of text the <code>Box</code> and <code>RichBox</code> can display.<br />
When the amount of information is too much to fit the maximum allowed size for the message box the text will overflow and can be scrolled up/down as necessary.</p>

<h3>Limitations of the RichBox</h3>

<p>The <code>RichBox</code> version relies on the normal TextBox control&#8217;s ability under Access 2007 to display RichText wich is nothing more than lightweight HTML.<br />
Because font size may be varying a lot in the message, it becomes very difficult to accurately predict the size of the box needed to display the whole message.<br />
Short of implementing a complete HTML engine, we have to rely on some assumptions to display HTML.<br />
The risk is that sometimes the content may not properly fit the TextBox control in some circumstances.<br />
If you use the <code>RichBox</code>, thoroughly try displaying your messages and tweak the HTML as necessary to include additional lines or non-breaking spaces to ensure that the result looks good.<br />
If you don&#8217;t overuse font size and don&#8217;t display in multiple fonts the <code>RichBox</code> should do the right thing most of the time.<br />
Don&#8217;t overuse the <code>RichBox</code> to display colourful messages. There is a fine line between being informative and tasteless. Keep colours and formatting where it is useful.<br />
I think that in most cases, the plain text version <code>Box</code> is more than enough.</p>

<h3>Replacing MsgBox in existing code</h3>

<p>As I said above, replacing the standard <code>MsgBox</code> is easy but you need to make sure your search and replace parameters are configured correctly:
<center><img src="/wp-content/uploads/2008/05/sshot-407.png" alt="Search and replace options" /></center></p>

<p>If you&#8217;re getting strange compile errors, it may be because you forgot to tick the <em>Find Whole Word Only</em> and some of the strings containing the letter sequence &#8220;msgbox&#8221; were replaced in the process.</p>

<p>If that&#8217;s the case, you can revert the damage by simply doing a search and replace across the whole project on:<br />
- <code>VbboxStyle</code> or <code>VbDialog.BoxStyle</code> to be replaced with <code>VbMsgBoxStyle</code><br />
- <code>VbboxResult</code> or <code>VbDialog.BoxResult</code>to be replaced with <code>VbMsgBoxResult</code></p>

<h3>How it works</h3>

<p>The code makes extensive use of Win32 API calls.<br />
Most of the hard work is done in the <code>FomDialog</code> class form. There is too much there to really go into the details but you are welcome to have a look at the commented code.<br />
The code relies also on a utility function from <em>Stephen Lebans</em> used to calculate the size of of text. I have made some minor modification to that code so I would refer you to his original implementation if you are interested in calculating TextBox sizes for forms or reports.</p>

<p>In the code for the <code>FormDialog</code>, I re-implement some of the expected functionalities of the <code>MsgBox</code>: proper arrangement of the buttons, displaying of the appropriate icon, etc.<br />
Once this is done, we calculate the size of the textbox needed to display the whole of the message.<br />
In the case of RichText, we first use <code>Application.PlainText()</code> to convert the HTML into properly formatted plain text. We then calculate the Textbox size using a slightly larger font than needed as a way to ensure that the content of the RichText message will fit the box in most cases.<br />
Once we know the size of the TextBox, we can easily resize the form to properly display the TextBox.<br />
If there is too much text, we resize the form to its maximum permissible (70% or screen width and 90% of screen height) and change some of the visual cues to let the user know the text is overflowing.</p>

<p>One thing of note is the way the form is kept modal.<br />
Rather than using <code>DoCmd.OpenForm</code> and <code>DoCmd.Close</code> I use the form as a class and create an instance manually (see the code in <code>Dialog.Box</code> and <code>Dialog.Richbox</code>). I keep this instance alive until I got the form&#8217;s result back.<br />
If you are interested in knowing how the form is made modal, this is the code in <code>FormDialog.ShowModal()</code> what keeps the form open until the user clicks a button:<br />
<textarea name="code" class="vb">
Public Function ShowModal() As VbMsgBoxResult
   ...
    ' Here we reset the result for the clicked button such as vbOK, vbYes, etc
    ' This is set in each Button's Click event
    m_Result = -1
    ' Wait for the user to click a button
    Do While (m_Result = -1)
        DoEvents
        Sleep 50
    Loop
    ShowModal = m_Result
End Function</textarea>
The <code>Sleep()</code> function is a Win32 API that stops the current process for the given number of milliseconds. This in effects hands back the control to the Operating System for a short time. That way the system is still responsive and does not consume resources when it&#8217;s just waiting for user input.</p>

<h3>Sample database</h3>

<p>You can download a sample database containing all the necessary code as well as a number of tests.<br />
This version only contains the database in Microsoft Access 2007 accdb format.
<center><img src="/wp-content/uploads/2008/05/sshot-77.png" alt="Sample database testing form" /></center></p>

<p><a href='http://blog.nkadesign.com/wp-content/uploads/2008/05/EnhancedMsgBox01.zip' title='Sample database'><img src="/wp-content/uploads/2008/05/download.png" alt="Download" /></a>Download the <a href='http://blog.nkadesign.com/wp-content/uploads/2008/05/EnhancedMsgBox01.zip' title='Test database'>EnhancedMsgBox01.zip (116KB), v1.3</a> containing the ACCDB database.</p>

<h3>Code Updates</h3>

<p><em>v1.3: 17MAR2009</em><br />
Thanks to Henry of <a href="http://www.access-pro.de/">Access-Pro.de</a> for proposing a correction to the default buttons behaviour.</p>

<ul>
<li>Updated behaviour for the default buttons. They are now focused in a way that matches that of the standard msgbox.</li>
<li>Reversed the naming of the buttons on the form to make it a bit more consistent with the standard box.</li>
</ul>

<p><em>v1.2: 07SEP2008</em><br />
Thanks to Andy Colonna (<a href="http://www.pcesoft.com">http://www.pcesoft.com</a>) for uncovering the following bugs (check out his <a href="http://www.pcesoft.com/Access-Spell-Checker-Tool-Source-Code.html">free Spell Checker with source code</a>!):</p>

<ul>
<li>Corrected bug in <code>Form_FormDialog.FilenameSanitize()</code> function that would 
fail to remove all invalid characters for a file name.</li>
<li>File name for the saved text message will be truncated to first 32 characters 
of message box title in <code>Form_FormDialog.MakeFriendlyFileName()</code>.</li>
<li>Changed the use of <code>FollowHyperlink</code> to <code>ShellExecute</code> to avoid security warning
in some instances in <code>Form_FormDialog.btCopyToFile_Click()</code></li>
<li>Corrected twips to pixel conversion bug in <code>API_GetTextMetrics.fTextWidthOrHeight()</code> that 
would result in an improperly sized dialog box when the text message was too 
wide.</li>
</ul>

<p><em>v1.1: 08AUG2008</em></p>

<ul>
<li>Corrected code for <code>DefaultButtonDelay</code> (thanks to Geoffrey) (was referencing
wrong variable, causing self-referencing code).</li>
<li>Corrected code for <code>Box</code> and <code>RichBox</code> to take the <code>DefaultSavedTextFileFolder</code>
into account (the path was previously not passed onto the dialog boxes and 
the text file would always be created in the application folder instead of 
the one specified by <code>DefaultSavedTextFileFolder</code>)</li>
<li>Added license notice at top of source code.</li>
</ul>

<p><em>v1.0: 20MAY2008</em></p>

<ul>
<li>Original version</li>
</ul>

<h3>Resources</h3>

<ul>
<li><a href="http://www.codeproject.com/KB/dialog/MessageBoxEx.aspx">Dissecting the MessageBox</a> article on <a href="http://www.codeproject.com/">CodeProject</a></li>
<li><a href="http://www.codeproject.com/KB/dialog/xmessagebox.aspx">XMessageBox -- A reverse-engineered MessageBox()</a> article on <a href="http://www.codeproject.com/">CodeProject</a></li>
<li><a href="http://www.lebans.com/textwidth-height.htm">TextWidth-Height code demo</a> from <a href="http://www.lebans.com/">Stephen Lebans</a> (great resource, check it out!).</li>
<li><a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;210590">Pixel to Twips conversion</a> from MSDN.</li>
<li><a href="http://www.mvps.org/access/api/api0049.htm">Copy Text to Clipboard</a> from the excellent site <a href="http://www.mvps.org/access/">The Access Web</a>.</li>
<li><a href="http://www.thevbzone.com/l_res.htm">Getting Resource Strings and more</a> from DLLs.</li>
</ul>

<p><!--- Code source license -->
<a rel="license" href="http://creativecommons.org/licenses/by/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by/3.0/80x15.png"/></a><br/>This <span xmlns:dc="http://purl.org/dc/elements/1.1/" href="http://purl.org/dc/dcmitype/Text" rel="dc:type">work</span> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 Unported License</a>.<br />
Free for re-use in any application or tutorial providing clear credit is made about the origin of the code and a link to this site is prominently displayed where end-users can easily access it.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2008/ms-access-enhanced-message-box-replacement/feed/</wfw:commentRss>
		<slash:comments>67</slash:comments>
		</item>
		<item>
		<title>MS Access: Restarting and compacting the database programmatically</title>
		<link>http://blog.nkadesign.com/2008/ms-access-restarting-the-database-programmatically/</link>
		<comments>http://blog.nkadesign.com/2008/ms-access-restarting-the-database-programmatically/#comments</comments>
		<pubDate>Tue, 06 May 2008 03:06:19 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[MSAccess]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[Web Design]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=73</guid>
		<description><![CDATA[In my previous article about changing the MS Access colour scheme I had the need to allow the user to restart the database after the colour scheme was changed. (Article and Code Updated 13FEB2009.) Being able to cleanly restart and compact the application is also useful in other instances: Changes made to the environment Recovering [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/access.png" alt="Microsoft Access" title="Microsoft Access" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />
In my previous article about <a href="http://blog.nkadesign.com/2008/ms-access-changing-the-color-scheme-programmatically/">changing the MS Access colour scheme</a> I had the need to allow the user to restart the database after the colour scheme was changed.<br />
(<strong>Article and Code Updated 13FEB2009.</strong>)</p>

<p>Being able to cleanly restart and compact the application is also useful in other instances:</p>

<ul>
<li>Changes made to the environment</li>
<li>Recovering from errors (for instance after a network disconnection)</li>
<li>Forcing the user to re-log cleanly into the application</li>
<li>Automatically restarting a long-running application (for instance so that it may automatically compact on close and restart afresh with or without user intervention).</li>
</ul>

<p>The problem is that you cannot -to the best of my knowledge- close and open again the same database from within MS Access itself.<br />
Most executables cannot do that and the way to solve the issue is usually to pass the control to another boostrap programme, close the main application and let the bootstrap programme re-open the main application again.<br />
I wanted a simple and clean way of using it. One that would not require shipping external dependencies.</p>

<h3>How to use it</h3>

<p>Download the sample database below, copy the <code>Utilities</code> module or just the <code>Restart</code> sub defined in it into your own application.</p>

<p>To use it, just call the <code>Restart</code> sub and the application will close and re-open.<br />
If you supply the optional <code>Compact:=true</code> parameter, the database will also be compacted during the restart process.<br />
This will work for normal databases (mdb/accdb) and also compiled (mde/accde) and runtime (accdr) databases as well.</p>

<h3>Important note</h3>

<p>If you want to use this code do not enable the <em>Compact on Close</em> option in Access for your database as the code doesn&#8217;t pick that up yet.<br />
Instead, you can either simply call <code>restart Compact:=true</code> on user action (for instance from a menu) or on other triggers, for instance when the database is being open and hasn&#8217;t been compacted for more than a week.</p>

<h3>How it works</h3>

<p>If you&#8217;re curious about the technical details, here is how it was put together.<br />
The main idea is that the MS Access database application has to be self-sufficient and restart itself by performing these steps:</p>

<ul>
<li>create a small batch file</li>
<li>run the batch file, passing the path and extension of our database</li>
<li>close the main application</li>
<li>the running batch file would wait for the MS Access lock file to be removed</li>
<li>once the lock file disappears, we open the database after compacting it if required.</li>
</ul>

<p>The key point here is that the batch file cannot just reopen the database right away: if the application is big or if it&#8217;s compacting on close for instance, it may take several seconds to actually close.<br />
The only moment we can be pretty sure that the database is effectively closed is when the lock file is deleted by MS Access.</p>

<p>The batch file is hard-wired in the <code>Restart</code> sub that does all the work:<br />
<textarea name="code" class="bat">
SETLOCAL ENABLEDELAYEDEXPANSION
SET /a counter=0
:CHECKLOCKFILE
ping 0.0.0.255 -n 1 -w 100 > nul
SET /a counter+=1
IF "!counter!"=="60" GOTO CLEANUP
IF EXIST "%~f2.%4" GOTO CHECKLOCKFILE
"%~f1" "%~f2.%3" /compact
start " " "%~f2.%3"
:CLEANUP
del %0
</textarea>
When the application runs the batch file, it passes 4 arguments:</p>

<ul>
<li>the full path to the MSAccess.exe executable (used for compacting the database)</li>
<li>the full path to the database without the extension</li>
<li>the database file extension without the leading &#8220;.&#8221;</li>
<li>the appropriate database lock file extension (<code>laccdb</code> or <code>ldb</code>).</li>
</ul>

<p>This allows us to easily construct the path to either the database or the lock file at line 07 and 09.<br />
Line 08 is actually only inserted if we need to compact the database: it simply launches MSAccess.exe with the <code>/compact</code> command line switch.</p>

<p>The funny use of <code>PING</code> is actually a simple way to wait for some time before we check if the lock file is still there or not. There is no <code>SLEEP</code> or <code>WAIT</code> function provided by default in Windows so we have to be a bit creative and use the time-out option of the <code>PING</code> command trying to ping an nonexistent, but valid, IP address.<br />
Once the lock file has disappeared, we open the database at line 09 and then delete the batch file itself so we leave no leftovers.</p>

<p>The other thing of note is that we now use a counter to keep track of the number of times we checked the existence of the lock file.<br />
Once this counter reaches a pre-determined amount (60 by default, ~ 45 seconds) we consider that there is a problem and the database application didn&#8217;t close, so we just exit and delete the batch file.</p>

<p><a href='http://blog.nkadesign.com/wp-content/uploads/2008/05/DatabaseRestart.zip' title='Sample database'><img src='http://blog.nkadesign.com/wp-content/uploads/2008/05/download.png' align="left" alt='Download' /></a>Download the <a href='http://blog.nkadesign.com/wp-content/uploads/2008/05/DatabaseRestart.zip' title='Test database'>DatabaseRestart.zip (48KB)</a> containing both an Access 2007 ACCDB and Access 2000 MDB test databases.</p>

<h3>Other implementations</h3>

<ul>
<li><a href="http://www.rogersaccesslibrary.com/">Roger&#8217;s Access Library</a> (MVP) has a <a href="http://www.rogersaccesslibrary.com/forum/forum_posts.asp?TID=377">different implementation on offer</a>.</li>
</ul>

<h3>Code Updates</h3>

<p><strong>v1.2: 13FEB2009</strong></p>

<ul>
<li>Added optional parameter to compact the database during restart.</li>
</ul>

<p><strong>v1.1: 09AUG2008</strong></p>

<ul>
<li>Now a separate test database (used to be bundled with the Colour Scheme sample).</li>
<li>Added support for older Access versions (an Access2000 MDB is now included).</li>
<li>Corrected wrong lock file extension for accd* files.</li>
<li>Added a time-out feature after which the batch file will delete itself 
after a while if the Access lock file wasn&#8217;t released 
(for instance following a crash).</li>
<li>Added checks to delete the batch file if it has not deleted itself for some
reason (for instance after a reboot).</li>
<li>The batch file now has a unique name based on the name of the database, 
allowing multiple databases to be restarted from the same directory.</li>
<li>Added license notice at top of source code.</li>
<li>Updated the article to reflect the changes.</li>
</ul>

<p><strong>v1.0: 06MAY2008</strong></p>

<ul>
<li>Original version</li>
</ul>

<p><!--- Code source license -->
<a rel="license" href="http://creativecommons.org/licenses/by/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by/3.0/80x15.png"/></a><br/>This <span xmlns:dc="http://purl.org/dc/elements/1.1/" href="http://purl.org/dc/dcmitype/Text" rel="dc:type">work</span> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 Unported License</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2008/ms-access-restarting-the-database-programmatically/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>MS Access: Changing the Color Scheme programmatically</title>
		<link>http://blog.nkadesign.com/2008/ms-access-changing-the-color-scheme-programmatically/</link>
		<comments>http://blog.nkadesign.com/2008/ms-access-changing-the-color-scheme-programmatically/#comments</comments>
		<pubDate>Sat, 03 May 2008 13:20:43 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[MSAccess]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=72</guid>
		<description><![CDATA[Microsoft Office 2007/2010 comes with 3 colour (color) schemes. Users can easily change it but when you deploy an Access application under the Runtime your users have no way to set the colour scheme as the application&#8217;s options are not available. (Article and Code Updated 31MAY2011.) Luckily for us, Office 2007 stores the global colour [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/access.png" alt="Microsoft Access" title="Microsoft Access" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />
Microsoft Office 2007/2010 comes with 3 colour (color) schemes.
Users can easily change it but when you deploy an Access application under the <a href="http://www.microsoft.com/downloads/en/details.aspx?familyid=57a350cd-5250-4df6-bfd1-6ced700a6715">Runtime</a> your users have no way to set the colour scheme as the application&#8217;s options are not available.<br />
(<strong>Article and Code Updated 31MAY2011.</strong>)</p>

<p>Luckily for us, Office 2007 stores the global colour scheme setting in the registry under:<br />
<code>HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Common\Theme</code><br />
and Office 2010 in:<br />
<code>HKEY_CURRENT_USER\Software\Microsoft\Office\14.0\Common\Theme</code></p>

<p>The values being stored under that key are:</p>

<ol>
<li>Blue scheme</li>
<li>Silver scheme</li>
<li>Black scheme</li>
</ol>

<p>With this information, we can easily both read and set the colour scheme.
The only caveat is that I could not find a way to notify Access to reload the setting automatically once it is changed, so users will have to restart the application before the change becomes active.
A small price to pay but if anyone has a better idea, please let me know.</p>

<p>To write the new value to the registry I use a set of WIN 32 APIs that are more flexible than the default ones provided in VBA.</p>

<p><img src="/wp-content/uploads/2008/05/colorschemes.png" alt="Office 2007 Colour Schemes" title="Office 2007 Colour Schemes" width="560" height="263" hspace="0" vspace="5" border="0" /></p>

<p>You can download the sample database as it contains all necessary files, including the definition for the Win32 API functions.</p>

<p><a href='http://blog.nkadesign.com/wp-content/uploads/2008/05/ColorScheme.zip' title='Sample database'><img src='http://blog.nkadesign.com/wp-content/uploads/2008/05/download.png' align="left" alt='Download' /></a>Download the <a href='http://blog.nkadesign.com/wp-content/uploads/2008/05/ColorSchemeV1.3.zip' title='Test database'>ColorSchemeV1.3.zip (31KB)</a> containing the ACCDB database.</p>

<p>The sample also contains some code to restart the database. This is the subject of another post: <a href="/2008/ms-access-restarting-the-database-programmatically/">Restarting and compacting the database programmatically</a>.</p>

<h3>Improvements/uses:</h3>

<ul>
<li>Find a way for Access to reload the settings without having to restart the application.</li>
<li>Use the knowledge about the current scheme to change the other colour settings in the application (or even adapt the form&#8217;s theme).</li>
</ul>

<h3>Updates:</h3>

<ul>
<li>31MAY2011: added support for Office 2010.</li>
</ul>

<h3>References:</h3>

<ul>
<li><a href="http://blogs.msdn.com/eric_carter/archive/2008/04/11/setting-the-backcolor-to-match-the-office-2007-color-scheme.aspx">Setting the BackColor to match the Office 2007 color scheme</a></li>
<li>API <a href="http://www.arcatapet.net/vbregget.cfm">Get</a> / <a href="http://www.arcatapet.net/vbregset.cfm">Set</a> Registry functions from <a href="http://www.arcatapet.net/">http://www.arcatapet.net/</a>.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2008/ms-access-changing-the-color-scheme-programmatically/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>MS Access: Modal Dialogs with Transparent Backgrounds (redux)</title>
		<link>http://blog.nkadesign.com/2008/ms-access-modal-dialogs-with-transparent-backgrounds/</link>
		<comments>http://blog.nkadesign.com/2008/ms-access-modal-dialogs-with-transparent-backgrounds/#comments</comments>
		<pubDate>Thu, 01 May 2008 11:36:36 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[MSAccess]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/2008/ms-access-modal-dialogs-with-transparent-backgrounds/</guid>
		<description><![CDATA[Microsoft Access Team made an interesting post and a follow-up on how to add a transparent layer that cover the screen to focus the attention of the user to a login form or other important popup window. The trick is to use some WIN 32 API calls to modify the transparency of a standard MS [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/access.png" alt="Microsoft Access" title="Microsoft Access" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />
Microsoft Access Team </a>made an <a href="http://blogs.msdn.com/access/archive/2008/04/28/modal-dialogs-with-transparent-backgrounds.aspx">interesting post </a> and a <a href="http://blogs.msdn.com/access/archive/2008/05/05/follow-up-to-transparency-forms.aspx">follow-up</a> on how to add a transparent layer that cover the screen to focus the attention of the user to a login form or other important popup window.</p>

<p>The trick is to use some WIN 32 API calls to modify the transparency of a standard MS Access form made to cover the screen.</p>

<p>The effect is quite neat and I thought I would try it and make a sample database for others to tinker with it.<br />
My version allows you to chose between covering the whole screen or just the main Access window and it will test if it&#8217;s running under a Remote Desktop Terminal and disable the layer in that case.</p>

<p><a rel="lightbox" href="/wp-content/uploads/2008/05/sshot-70.png"><img width="250" vspace="5" hspace="5" height="189" border="0" alt="The transparent layer covering the main Window only" title="The transparent layer covering the main Window only" src="/wp-content/uploads/2008/05/sshot-70sm.png" /></a><a rel="lightbox" href="/wp-content/uploads/2008/05/sshot-73.png"><img width="250" vspace="5" hspace="5" height="189" border="0" alt="The transparent layer covering the full screen" title="The transparent layer covering the full screen" src="/wp-content/uploads/2008/05/sshot-73sm.png" /></a></p>

<h3>Update 07MAY2008</h3>

<p>Following Rob&#8217;s improvements I made another sample database that incorporates his code with a few improvements:</p>

<ul>
<li>I added the <code>LightBoxForm.LayerToFullScreen</code> property so users can choose explicitly how they want the layer to be shown.</li>
<li>I moved the code to hide the layer into a Hide() sub so you can just show/hide the layer using <code>LightboxForm.Show</code> and <code>LightboxForm.Hide</code>.</li>
<li>I changed the Form&#8217;s <code>Resize </code>event code in the <code>LightBoxForm</code> class to avoid flickering: resizing the form within its <code>Resize</code> event actually trigger the <code>Resize</code> event again a second time which causes flickering.<br />
I simply modified the code to make the form totally transparent (opacity of 0) the first time the event is fired and assign it the expected opacity when the event handler in re-entered.  </li>
</ul>

<p><textarea name="code" class="vb">
'-----------------------------------------------------------------------------
' Handle the Layer Form Resize event
'-----------------------------------------------------------------------------
Private Sub m_objForm_Resize()
    Static busyResizing As Boolean
    Dim lngStyle As Long
    Dim r        As RECT

    ' disable screen updates
    m_objForm.Painting = False

    ' When the form opens initially, we make it totally transparent to avoid flickering
    lngStyle = GetWindowLong(m_objForm.hWnd, GWL_EXSTYLE)
    SetWindowLong m_objForm.hWnd, GWL_EXSTYLE, lngStyle Or WS_EX_LAYERED
    SetLayeredWindowAttributes m_objForm.hWnd, 0, 0, LWA_ALPHA
    
    ' If the Access window is maximized, then maximize the lightbox form.
    ' If the Access window is not maximized, then
    ' position the lightbox form so that it covers the Access window
    If IsZoomed(hWndAccessApp()) Or m_bLayerToFullScreen Then
        DoCmd.Maximize
    Else
        GetWindowRect Application.hWndAccessApp(), r
        MoveWindow m_objForm.hWnd, r.x1, r.y1, (r.x2 - r.x1), (r.y2 - r.y1), True
    End If
    
    If busyResizing Then
        ' Get the current window style, then set transparency
        lngStyle = GetWindowLong(m_objForm.hWnd, GWL_EXSTYLE)
        SetWindowLong m_objForm.hWnd, GWL_EXSTYLE, lngStyle Or WS_EX_LAYERED
        SetLayeredWindowAttributes m_objForm.hWnd, 0, (m_sngOpacity * 255), LWA_ALPHA
        ' enable screen updates
        m_objForm.Painting = True
        ' Back to normal
        busyResizing = False
    Else
        busyResizing = True
    End If
End Sub
</textarea></p>

<h3>Samples</h3>

<p>There are now 2 sample databases. Ech zip contains a Microsoft Access 2007 ACCDB file and its conversion to Access 2000<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup> and Access 2002-2003 MDB but please note that I have not been been able to test those in older version of Access and that form transparency doesn&#8217;t work in Operating Systems older than Windows 2000.</p>

<p><a href='http://blog.nkadesign.com/wp-content/uploads/2008/05/transparentlayer02b.zip' title='Test database'><img src='http://blog.nkadesign.com/wp-content/uploads/2008/05/download.png' align="left" alt='Download' /></a>Download <a href='http://blog.nkadesign.com/wp-content/uploads/2008/05/transparentlayer02b.zip' title='Test database'>TransparentLayer02b.zip (138KB)</a>, recommended version<br />(improved, more flexible version, based on <a href="http://blogs.msdn.com/access/archive/2008/05/05/follow-up-to-transparency-forms.aspx">Rob&#8217;s updated article</a>).</p>

<p><a href='http://blog.nkadesign.com/wp-content/uploads/2008/05/transparentlayer01b.zip' title='Test database'><img src='http://blog.nkadesign.com/wp-content/uploads/2008/05/download.png' align="left" alt='Download' /></a>Download <a href='http://blog.nkadesign.com/wp-content/uploads/2008/05/transparentlayer01b.zip' title='Test database'>TransparentLayer01b.zip (122KB)</a>, original version<br />(simple code, based <a href="http://blogs.msdn.com/access/archive/2008/04/28/modal-dialogs-with-transparent-backgrounds.aspx">Rob&#8217;s original article</a>).</p>

<h3>Troubleshooting</h3>

<ul>
<li><em>If you are getting security warnings:</em> make sure that you open the database from a Trusted Location or you will receive a security prompt.
If you don&#8217;t know how to do that, <a href="http://office.microsoft.com/en-us/help/HA100319991033.aspx#11">check these steps</a>.</li>
<li><em>If the layer appears on top of the login form instead of behind:</em> make sure that the top-most form has ist <code>Modal </code>properties set to <code>Yes</code> and the <code>frmLightBox</code> form has its modal property set to <code>No</code>.<br />
If you improve on it, please let me know and I&#8217;ll post it here for all to find.</li>
</ul>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>A specific version for Access 2000 now included in the archive (updated 25JUL2008).&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2008/ms-access-modal-dialogs-with-transparent-backgrounds/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>&#8220;Apple&#8217;s OS Edge Is a Threat to Microsoft&#8221;. Really?</title>
		<link>http://blog.nkadesign.com/2008/apples-os-edge-is-a-threat-to-microsoft-really/</link>
		<comments>http://blog.nkadesign.com/2008/apples-os-edge-is-a-threat-to-microsoft-really/#comments</comments>
		<pubDate>Sun, 13 Apr 2008 11:13:18 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Reviews]]></category>
		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/2008/apples-os-edge-is-a-threat-to-microsoft-really/</guid>
		<description><![CDATA[Business Week has a recent article where the author foresee the demise of Windows in favour of Apple&#8217;s OS. Reading it, I couldn&#8217;t help thinking I was reading one of these overenthusiastic 1925 popular-science article promising us that within just a few years we would all use our own flying car to get to work. [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/money01.png" alt="Business" title="Business" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />Business Week has a recent article where the author foresee the <a href="http://www.businessweek.com/technology/content/apr2008/tc20080410_206881.htm">demise of Windows</a> in favour of Apple&#8217;s OS.<br />
Reading it, I couldn&#8217;t help thinking I was reading one of these overenthusiastic 1925 popular-science article  promising us that within just a few years we would all use our own flying car to get to work.<br />
Yeah, right, mine is parked right under my window.</p>

<p>The basic premise of the article is that Apple will attack the corporate market through the back-door, using the iPhone and its forthcoming development platform.<br />
The author contend that development to the iPhone will drive interest in the Mac and allow Apple to displace Windows by offering more business-related applications that would eventually not require Microsoft&#8217;s OS running side-by-side in your Mac, freeing you of the dominance of the evil empire.<br />
Please <a href="http://www.businessweek.com/technology/content/apr2008/tc20080410_206881.htm">read the article first</a>.
Done?<br />
Hmmm&#8230;<br />
Ok, let&#8217;s see&#8230;</p>

<p>First, let&#8217;s be nice: if Apple want to eat at Microsoft&#8217;s dominance of the OS market, then all the better: more competition will drive innovation and choice, which is always nice.<br />
There is certainly some truth to the idea that Apple could offer some useful tools and technologies to the corporate world.</p>

<p>The problem is that author of the article was a bit too much of a Mc Fanboy(TM) to make his arguments compelling.</p>

<p>Let&#8217;s start direct quotes from the article.</p>

<p>Speaking of the ability of the Mac to quickly switch from a Windows application to a Mac by using a keyboard shortcut:</p>

<blockquote>
  <p><em>&#8220;Windows users, in the very near future, will be free to switch to Apple computers and mobile devices, drawn by a widening array of Mac software, without suffering the pain of giving up critical Windows-based applications right away.&#8221;</em></p>
</blockquote>

<p>Useful as it may be, it&#8217;s forgetting one thing: if you need to be able to run your windows application under a Mac, you will need to give Microsoft money for the Windows license, making the newly found convenience of running the two OS together seamlessly a fairly expensive one, both in terms of computer resources and money.<br />
While it will interest a lot of people and they may use their windows apps on Apple hardware is this really compelling enough to make it a viable migration path?</p>

<p>About the new Mac OS kernel:</p>

<blockquote>
  <p><em>&#8220;That kernel has proved easily adaptable across the entire Apple product line, from highly complex servers all the way down to the relatively simple iPod Touch. Such modularity allows Apple to add whatever functions are necessary for each product environment—all while maintaining cross-product compatibility.<br />
  By contrast, Microsoft has held on to an OS tethered to the 1980s, piling additions upon additions with each upgrade to Windows. With last year&#8217;s arrival of Vista, Windows has swollen to 1 billion bytes (a gigabyte) or more of software code. The &#8220;Mach&#8221; kernel of the Mac OS X, however, requires less than 1 million bytes (a megabyte) of data in its smallest configuration, expanding modestly with the sophistication of the application.&#8221;</em></p>
</blockquote>

<p>All this is so silly and skewed that I wonder where to start.<br />
First, kernel size is irrelevant: a basic kernel functionality does not make an operating system. Additionally, I doubt that we&#8217;re comparing the same functionality and for desktop or server applications this is utterly irrelevant.<br />
For small devices Windows has its own flavours and they can <a href="http://channel9.msdn.com/ShowPost.aspx?PostID=15615">quickly be deployed to almost any hardware with minimal effort</a>.<br />
Applications built for Windows built for mobile devices can be ported to Windows <a href="http://en.wikipedia.org/wiki/.NET_Compact_Framework">without too much trouble</a>, and vice versa. Whatever platform you&#8217;re developing on, applications for small hardware are always an exercise in compromise: there is no way that you can just recompile an app for a different target and have it just work beautifully in any device. A mobile app must take care of power requirements, limited screen estate, memory and CPU limitations and specific usability issues like the presence of a touch-screen instead of a keyboard and mouse.<br />
The point is that you have to take the platform into consideration when crafting software.
Besides, using .Net makes it fairly easy to develop applications for any flavour of Windows.
Additionally, whether the OS under the XBox is different or not from the desktop version of Windows is also irrelevant: you can develop games under the <a href="http://en.wikipedia.org/wiki/Microsoft_XNA">XNA platform </a>that compile and work just the same under Windows as they do on the Xbox.</p>

<p>Now, for the argument regarding the <em>&#8220;additions upon additions&#8221;</em> made upon Windows that contribute to its bloat, it&#8217;s an easy shot to make and an unfair one: Apple has had no regards for its legacy applications and since its primary market was consumers, it could get away with making each of its major OS release incompatible with the previous one.<br />
We can argue whether it was a good thing for Microsoft to keep all the quirks from previous releases of its operating system alive but we must not forget that in the corporate world, <a href="http://www.microsoft-watch.com/content/operating_systems/windows_a_monopoly_shakes.html">Windows has close to 100% market </a>share on the desktop.<br />
What that means is that Microsoft could not afford not supporting business applications across versions. it would have been suicidal to even envisage dropping compatibility.<br />
If Apple ever get into that corporate market above a few percent it will have to guarantee compatibility between versions of its OS and programming tools if it wants to have any chance at being taken seriously at all.<br />
When companies spend money developing an application that is critical to their business, they don&#8217;t want to hear about its supporting OS becoming incompatible every couple of years.<br />
Apple would have to support and maintain compatibility for at least 10 years for every major OS version. So far Apple hasn&#8217;t shown that it was capable of that type of commitment.</p>

<p><a href='http://blog.nkadesign.com/wp-content/uploads/2008/04/amipro.png' title='Amipro 3.1 on my computer'><img src='http://blog.nkadesign.com/wp-content/uploads/2008/04/amiprosm.png' alt='Amipro 3.1 on my computer'  style="float:right;margin-left:10px;margin-bottom:5px"/></a>A small digression.<br />
A couple of weeks ago I found some old files of mine on a floppy.<br />
They were Ami Pro files, made at a time when <a href="http://en.wikipedia.org/wiki/AmiPro">Ami Pro 3.1</a> was the best word processor around.<br />
Problem was that I could not safely open these files any longer: filters for various word processors would mangle the complex layout of the pages, making them un-usable.
Out of curiosity, I found a full version of the original Amipro 3.1.<br />
I had no expectations of being able to run that setup package. After all, Ami Pro 3.1 came out in 1994, before Windows 95 was even released!<br />
Well, I clicked on that setup.exe file and watched the installation process go through&#8230;
Everything went fine.<br />
Surely, I thought, there is no way this is going to run under Windows XP. It&#8217;s going to crash for sure.<br />
I double-clicked on the 16 colour icon and lo and behold, the whole thing actually ran! Flawlessly!<br />
I was able to open my old files without any issue, save them under another format.
Everything worked, miraculously.<br />
That application was written at a time the Internet didn&#8217;t even exist yet I was able to install and run it without problem on a current operating system.<br />
Back to our regular schedule.</p>

<blockquote>
  <p><em>&#8220;Despite Apple&#8217;s relative scarcity on corporate desktops, Mac laptops are already well accepted within the enterprise, with a market share of more than 20% and growing. For business travellers, the new MacBook Air, some three pounds lighter than comparable Windows-based laptops, already offers one huge advantage.&#8221;</em></p>
</blockquote>

<p>First, Apple has a almost 20% market share on overall laptops sales only, not corporate sales.<br />
Second, that <a href="http://www.macworld.com/article/59616/2007/08/appleshare.html">figure is for the US only</a>. Apple&#8217;s laptop market share in the world is certainly not bad, but it&#8217;s a <a href="http://www.macnn.com/articles/08/03/05/apple.ninth.in.laptops/">quarter of that figure</a>, making adoption of Apple laptops outside the US very small indeed.<br />
Third, while Apple laptops are certainly sexy, they bring their own issues to businesses: lack of in-house serviceable parts, issues with making them fit into a complex infrastructure, hardware and software compatibility problems.<br />
Bringing Macs into your organisation can be painful. Of course, it&#8217;s never impossible, but beyond simple setups, it takes time, energy and money to make stuff work seamlessly.<br />
So I contend that, unless you have a serious commitment to Apple, most of the Macs getting into companies are for simple usage: fetching emails, browsing, making presentations and maybe Photoshop, although it seems that the application that was once the sole reason for some to use macs is now <a href="http://arstechnica.com/staff/fatbits.ars/2008/04/02/rhapsody-and-blues">going to switch side</a>, at least for a little while.<br />
For Macs to become a first-class corporate platform would require that Apple makes a very serious commitment to cross-platform development to make applications work on Windows as well.<br />
I seriously don&#8217;t think that the ability of Macs to run Windows side-by-side will do much: as mentioned above, the expense incurred offers no real benefit to businesses and having to support both platforms would increase the cost of ownership because of the upfront cost of buying and installing multiple OS, 15% higher average cost of Apple laptops compared to other similarly specified laptops and the cost of maintaining and supporting multiple hardware and OS stacks.<br />
Slickness can only get you so far I suppose.</p>

<blockquote>
  <p><em>&#8220;While Mac desktops offer a growing number of superior features over Windows desktops&#8221;</em></p>
</blockquote>

<p>Seriously dude, what superior features?</p>

<blockquote>
  <p><em>&#8220;Apple&#8217;s recently introduced Leopard servers compete in a market of unhappy Vista server buyers where Microsoft&#8217;s market share is only 40%. Leopard has a decent chance to expand from its small beachhead.&#8221;</em></p>
</blockquote>

<p>Huh? Vista servers?<br />
WTF is that?<br />
You can&#8217;t be talking about Windows 2003 because it&#8217;s actually a rock-solid platform and there isn&#8217;t much to complain about.<br />
Windows 2008 is just coming out and it looks just as promising.<br />
Apple has some seriously nice server hardware, it&#8217;s so beautiful to look at all this engineering that it gets me all hot and bothered.<br />
Seriously though, on the server side, Leopard would not be in competition with Windows but with *nix.<br />
Server-side applications like ASP, Exchange, Sharepoint, SQL Server and the myriad other Microsoft-only server software will only work on Windows.<br />
Apple is not going to compete as a platform for hosting these which means it will host services traditionally found on Linux/Unix/BSD systems.<br />
In that *nix camp Apple would certainly be a good contender, although it would have to prove that it can compete with the low license and hardware cost of its competitors and offer more.</p>

<p>One more thing to remember: Apple is in the hardware business: it uses software to lock people into its hardware business.<br />
I&#8217;m all for competition but at least using Linux or Microsoft products doesn&#8217;t lock me into a single hardware/software platform pair: I have orders of magnitude more choices when it comes to my servers, desktops and laptops than what Apple can offer me.<br />
Apple products may be slick and beautifully engineered but they certainly don&#8217;t offer more freedom: chose an iPhone and get stuck with a single network provider, buy an iPod and get stuck with iTune, buy a mac and get stuck with Apple, limited software offerings, no serious games and limited hardware support.</p>

<p>One other thing to keep in mind is that Microsoft has acquired a huge weight in terms of software development power: new technologies have been pouring out of Redmond at a pace that is impossible to follow.<br />
The number of developers and companies able to develop software for Windows platforms is wayyy above what Apple can dream of at the moment (we&#8217;re talking about millions of developer making a living off Windows).<br />
Apple will need to make serious efforts to woo the huge amounts of developers it needs to bring enough business and non-business applications to its platforms before it can become a serious competitor to Windows in the corporate world.<br />
Whether Apple has the capacity and will to do that instead of remaining a consumer-oriented company remains to be seen.</p>

<p>That being said I wouldn&#8217;t mind developing software for Apple platforms. I would love to be able to use a generic &#8220;surface laptop&#8221;, a sort of larger iPhone that could be used by sales people for taking orders and showing off new products.</p>

<p>Anyway, the point of all this was simply to offer a modest reality-check to an article that should have been a bit more measured and balanced in its fanboy-ish enthusiasm.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2008/apples-os-edge-is-a-threat-to-microsoft-really/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>WPF and Silverlight: it will take a while&#8230;</title>
		<link>http://blog.nkadesign.com/2008/wpf-and-silverlight-it-will-take-a-while/</link>
		<comments>http://blog.nkadesign.com/2008/wpf-and-silverlight-it-will-take-a-while/#comments</comments>
		<pubDate>Sun, 10 Feb 2008 08:45:07 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Musing]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/2008/wpf-and-silverlight-it-will-take-a-while/</guid>
		<description><![CDATA[Decoupling the User Interface from the underlying code has been one of the holy grails of application development. Layers of indirection and new patterns have been invented over time to try to separate what the user does from the back-end data. It&#8217;s been a long and difficult journey but WPF is the last attempt at [...]]]></description>
			<content:encoded><![CDATA[<p><img width="64" vspace="5" hspace="5" height="64" border="0" align="left" title="technology01.png" alt="technology01.png" src="/wp-content/uploads/technology01.png"/>Decoupling the User Interface from the underlying code has been one of the holy grails of application development.
Layers of indirection and new patterns have been invented over time to try to separate what the user does from the back-end data. It&#8217;s been a long and difficult journey but WPF is the last attempt at completely separating the user interface from the gut of an application, leaving graphic designer do what they do best and programmers do what they do best.<br />
I think this disconnect has actually hindered the adoption of WPF to a great extent.<br />
I also believe that Silverlight, while showing great promises, is going to take a long time to get off the ground.</p>

<p><img src='http://blog.nkadesign.com/wp-content/uploads/2008/02/silverlight1.png' alt='Silverlight' align="right" />Good graphic designers who work on User Interfaces are too few and far between, and large organisations will take time to get staff with a sufficient level of expertise to be useful in developing meaningful WPF/Silverlight applications.<br />
Until now, the bulk of the development effort was done by developers. Most ISV only have developers onboard.</p>

<p>As far as I can tell, it seems that main reason behind this slow adoption is that WPF/Silverlight has only been noticed by developers and they don&#8217;t know what to make with it.<br />
WPF/Silverlight are not really developer-friendly: the development infrastructure is there but we&#8217;re left with a blank canvas and nothing to drag and drop onto it.</p>

<p>There will be a great gap, probably lasting a few years, before there are enough experiments in these new user interfaces that some useful lowest common denominator can be exploited by non-designers.<br />
We&#8217;ll have to wait for tool vendors to provide the bulk of user interface blocks and for a few new patterns to appear before all the designer-challenged developers like me can make decent interfaces without requiring a professional graphic designer in their midst.<br />
In the mean time, we&#8217;ll probably have useless, but pretty, applications, some useful, but ugly ones and a lot of people scratching their head trying to couple the designers and the developers in a working relationship.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2008/wpf-and-silverlight-it-will-take-a-while/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>MS SQL Server Express: a good choice?</title>
		<link>http://blog.nkadesign.com/2008/ms-sql-server-express-a-good-choice/</link>
		<comments>http://blog.nkadesign.com/2008/ms-sql-server-express-a-good-choice/#comments</comments>
		<pubDate>Wed, 30 Jan 2008 07:03:09 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/2008/ms-sql-server-express-a-good-choice/</guid>
		<description><![CDATA[Microsoft SQL Server comes in many editions, ranging from completely free to use and distribute to versions costing tens of thousands of dollars. For small businesses, or when you can live with the limits imposed, the Express edition is one option to consider. Here are some reasons why SQL Server Express may be a good [...]]]></description>
			<content:encoded><![CDATA[<p><img width="64" vspace="5" hspace="5" height="64" border="0" align="left" title="technology02.png" alt="technology02.png" src="/wp-content/uploads/technology02.png"/>Microsoft SQL Server comes in many editions, ranging from completely free to use and distribute to versions costing tens of thousands of dollars.<br />
For small businesses, or when you can live with the limits imposed, the Express edition is one option to consider.</p>

<p><img src='http://blog.nkadesign.com/wp-content/uploads/2008/01/sql_server_2005.gif' alt='SQL Server logo' style="float:right;margin-left:10px;margin-bottom:5px;" />Here are some reasons why SQL Server Express may be a good choice:</p>

<h3>You&#8217;re upsizing an Access database</h3>

<p>SQL Server is the natural extension of upsizing  an existing Access database. It work automagically with minimum effort providing that you followed some simple good-design rules from the start.</p>

<h3>You&#8217;re future-proofing your needs</h3>

<p>Because SQL Server comes in many flavours, you know you -or your customers- can upgrade to a more capable (albeit more expensive) version in the future if needed.</p>

<h3>Very flexible</h3>

<p>As usual with a lot of Microsoft development tools, SQL Server will happily let you shoot yourself in the foot by providing you with a fairly easy way to treat your database as a complete development platform.<br />
It&#8217;s good in the sense that you have interesting tools and capabilities included in the server, and it&#8217;s bad for the exact same reasons.<br />
I tend to prefer database servers to be just that: data repositories, and I&#8217;m not too fond of relying on specific, non-standard features of a particular database system, but what do I know.</p>

<h3>Excellent out-of-the-box development support</h3>

<p>Deep integration with .Net and Visual Studio, without any effort, Microsoft saw to that of course.<br />
In some cases, such as <a href="http://msdn2.microsoft.com/en-us/library/bb425822.aspx">LINQ to SQL</a>, it&#8217;s almost the only real choice, although the other database vendors are working hard at the necessary providers, so that lead should be short-lived.<br />
There is something to be said about developer productivity: you have to give credit to Microsoft for making their tools well integrated and usable from each-other. What it means is that for small developer shops there is much to gain in surrendering to this &#8220;ease of the default&#8221;.<br />
Of course, it&#8217;s a double-edged sword, but having a complete development infrastructure work out of the box is certainly a big help, and if you don&#8217;t like it, you&#8217;re still free to chose something else.</p>

<h3>Lots of tools</h3>

<p>With SQL Server Advanced Services, you also get Server Management and Reporting Services. These are great tools made available for free.<br />
The only missing one for SQL Server is the Reporting designer. While the reporting service means that you can use existing reports, only SQL Server Standard and Enterprise have it.<br />
There is an option for developers though: the (nearly free) SQL Server Developer edition is in fact the same as SQL Server Enterprise, without the license to use in non-developer or tester environment. This means that as a developer, you can create and distribute your reports to be used by your customers who will be using SQL Server Express.</p>

<h3>Did I mention it&#8217;s free?</h3>

<p><img src='http://blog.nkadesign.com/wp-content/uploads/2008/01/db_status.png' alt='db_status.png' style="float:right;margin-left:10px;margin-bottom:5px;" />All this is free, as in beer, not as in liberty though.<br />
For commercial applications targeted at small businesses, SQL Server Express is a really good choice: you can distribute it without problem, the customer gets all the tools, can easily find outside support, and they can always migrate to a more beefy version if their needs grow, all that without having to depend on you.<br />
So it sort of offers customers a <em>kind</em> of freedom that they wouldn&#8217;t have with other choices.</p>

<p>Of course you can get that with other database systems, although you have to be careful which Open Source one you choose: I recently decided not to use MySQL any longer for the simple reason that it&#8217;s too expensive and restrictive in a business environment, at least for the kind of work I do.</p>

<p>Why would you <em>not</em> want to use SQL Server Express?</p>

<h3>You don&#8217;t want to depend on Microsoft</h3>

<p>That can be a good reason enough sometimes. There is nothing preventing Microsoft from crippling SQL Server Express in the future to force users to move to a paying version early.<br />
I suppose that whatever database system you use, even Open Source ones, there is always the possibility that the company supporting its development goes bankrupt, the Open Source projects goes dead or decides to go in a direction that doesn&#8217;t suit you..</p>

<h3>It&#8217;s only supported on Microsoft OS</h3>

<p>True, and that&#8217;s a good reason to chose something else.<br />
There is a hidden cost in SQL Server Express: it needs to run on a Windows machine, and that&#8217;s not free, although SQL Server will work on older Windows 2000 machines and Windows XP which are arguably not expensive.</p>

<h3>Your database needs will exceed SQL Server Express specifications</h3>

<p>If you think any of your databases will grow beyond 4GB or that it will get busy and you need all the RAM and CPU you can get, then SQL Server Express is probably not for you as it will only use 1 CPU and 1GB of RAM at most.<br />
If your needs go beyond that, then you&#8217;ll have to move to a paying version.</p>

<h3>Upgrading can be expensive</h3>

<p>It&#8217;s true that moving to the next cheapest upgrade of SQL Server Workgroup will cost you about US$700 for a 5 user license. The limits imposed on the database are much higher (2 processors, 3GB RAM and no size limit) but if you need more clients / or higher limits, then the expense will grow quite fast, and you&#8217;ll have to manage those hateful client access licenses.</p>

<h3>Your needs are more modest</h3>

<p>We haven&#8217;t talked here about single-file/single-user database systems.
These databases don&#8217;t user resident services and are usually meant for more limited needs, sometimes allowing only a single user to be connected.<br />
The footprint of these non-server databases is a lot smaller, typically only requiring a single dll or a handful of files to be installed.<br />
They are extremely useful for desktop application that do not really require multi-user support or advanced security features.<br />
Here again, Microsoft offers SQL Server Compact, which, despite the name, doesn&#8217;t have much to do with the other SQL Server editions. This one is also free, but has a limited feature set and only allow single-user access as it is meant to be a lightweight database and works well in limited memory environments such as those found on mobile devices.<br />
<img src='http://blog.nkadesign.com/wp-content/uploads/2008/01/sqlite.gif' alt='SQLite logo' style="float:right;margin-left:10px;margin-bottom:5px;" />Of course, here again there is a lot of competition: Thunderbird, SQLite, MS Access and VistaDB (for embedding into .Net applications, not free) to name a few.</p>

<p>These are pretty good times when it comes to databases: we get more choices now than we ever had.<br />
As usual, choosing a database as a back-end for your products isn&#8217;t easy: you need to consider cost, licensing, support and the future.<br />
There isn&#8217;t a single database system that will meet everyone&#8217;s needs for all types of use, so choose carefully.<br />
SQL Server Express is a very good contender in that market. It should not be dismissed out of hand because it&#8217;s from Microsoft, in the same way that PostgreSQL shouldn&#8217;t be dismissed because it&#8217;s Open Source.<br />
Just use the tool that best answers your needs for your particular circumstances.</p>

<h3>References:</h3>

<ul>
<li>SQL Server Express main page<br />
<a href="http://www.microsoft.com/sql/editions/express/default.mspx">www.microsoft.com/sql/editions/express/</a></li>
<li>Compare SQL Server editions<br />
<a href="http://www.microsoft.com/sql/prodinfo/features/compare-features.mspx">www.microsoft.com/sql/prodinfo/features/compare-features.mspx </a></li>
<li>System Requirements for SQL Server Express<br />
<a href="http://www.microsoft.com/sql/editions/express/sysreqs.mspx">www.microsoft.com/sql/editions/express/sysreqs.mspx</a></li>
<li>SQL Server Compact (single-user, small footprint database)<br />
<a href="http://www.microsoft.com/sql/editions/compact/default.mspx">www.microsoft.com/sql/editions/compact/</a></li></li>
<li>The VistaDB database, commercial embeddable database for .Net applications<br />
<a href="http://www.vistadb.net/">www.vistadb.net/</a></li>
<li>SQLite database, public domain, flexible file-database system<br />
<a href="http://www.sqlite.org/">www.sqlite.org/</a></li>
<li>The Firebird DB (based on <em>Interbase 6</em> from Borland)<br />
<a href="http://www.firebirdsql.org/">http://www.firebirdsql.org/</a></li>
<li>PostgreSQL Open Source database server<br />
<a href="http://www.postgresql.org/">http://www.postgresql.org/</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2008/ms-sql-server-express-a-good-choice/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>People, mind your dates&#8230; plz?</title>
		<link>http://blog.nkadesign.com/2007/people-mind-your-dates-plz/</link>
		<comments>http://blog.nkadesign.com/2007/people-mind-your-dates-plz/#comments</comments>
		<pubDate>Sat, 15 Dec 2007 15:34:46 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Musing]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/2007/people-mind-your-dates-plz/</guid>
		<description><![CDATA[What does 04/05/01 mean to you? Let&#8217;s make it easy: is that date in 2001 or 2004? And if I write it like 04/05/2001, is it really better? are we in April or May? And the answer is&#8230; If you are from North America and a handful other countries 04/05/01 would mean 5th of April [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/technology02.png" alt="technology02.png" title="technology02.png" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />What does 04/05/01 mean to you?<br />
Let&#8217;s make it easy: is that date in 2001 or 2004?<br />
And if I write it like 04/05/2001, is it really better? are we in April or May?<br />
And the answer is&#8230;</p>

<p><img src='/wp-content/uploads/2007/12/chcal.gif' alt='Chinese Calendar' style="float:right;margin-left:10px;margin-bottom:5px;" /> If you are from North America and a handful other countries 04/05/01 would mean 5th of April 2001.<br />
If you&#8217;re in Asia or some eastern countries, if could be 1st of May 2004.<br />
For the rest of the world, it would look like 4th of May 2001.</p>

<p>We cannot ignore any longer the importance of writing dates in a format that is understandable by everyone.<br />
Still too often, <a href="http://www.dnrtv.com/default.aspx?showNum=13">web sites</a> -even big <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=18b1d59d-f4d8-4213-8d17-2f6dde7d7aac&#038;DisplayLang=en">companies</a>- with a global audience state dates in a format that is probably obvious where they live but not consistently so to everyone else.</p>

<p>Developers are sometimes guilty of this sin, as can be seen in the format chosen to <a href="http://msdn2.microsoft.com/en-us/library/bb221200.aspx">specify dates in Microsoft Access SQL</a>, which requires that hard-coded dates be formatted in the US rather than the more neutral <a href="http://en.wikipedia.org/wiki/ISO_8601">ISO8601</a> format.<br />
I wonder how many bugs that little egocentric feature caused in business applications that where <a href="http://www.vbforums.com/showthread.php?t=297258">developed by foreign coders</a>&#8230;<br />
I know it also happened to me at least once&#8230;</p>

<p><img src='/wp-content/uploads/2007/12/russcal.gif' alt='Russian Calendar' style='float:left;margin-right:10px;margin-bottom:5px;' />The worst thing is that when you write 04/05/06, you may very well have thought about the rest of the world and meant DD/MM/YY; alas, unless the context grants us some clarification or the actual date is unequivocal, there is sometimes no way for a lot of us to know for sure what you really meant.</p>

<p>We should ban the use of the short date format in communications that may be read by more than 3 people, in today&#8217;s world, that&#8217;s pretty much all communication.</p>

<p>Instead a simple format such as 05MAY2006 is clear an unequivocal: it&#8217;s easy to read and understand, regardless of where you live.<br />
You&#8217;re free to add spaces, dashes, dots, comas or slashes to it if you want, you can use 2006MAY05 if you prefer or even MAY05,2006, whatever pleases you: it still remains readable.</p>

<p>The rule is simple:<em>write the year in full and never write the month as a two-digit number, that&#8217;s reserved for the day</em></p>

<p>The point is that you, me and the rest of the world can read it and understand exactly what was meant; it&#8217;s an easy problem to solve.<br />
Surely that means something to you?</p>

<h3>References</h3>

<ul>
<li><a href="http://en.wikipedia.org/wiki/Date_format">http://en.wikipedia.org/wiki/Date_format</a></li>
<li><a href="http://www.moserware.com/2008/02/does-your-code-pass-turkey-test.html">Does you code pass the Turkey test?</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2007/people-mind-your-dates-plz/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Thank you spammers&#8230;</title>
		<link>http://blog.nkadesign.com/2007/thank-you-spammers/</link>
		<comments>http://blog.nkadesign.com/2007/thank-you-spammers/#comments</comments>
		<pubDate>Thu, 31 May 2007 06:06:48 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Fun]]></category>
		<category><![CDATA[Musing]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/2007/thank-you-spammers/</guid>
		<description><![CDATA[I&#8217;ve been tired of spam on my websites. The few hundreds messages spammers leave everyday are a bit of a nuisance. Now though, I&#8217;ve decided to make them work harder to get their messages ignored. Last week, reCAPTCHA came online. It&#8217;s an effort inspired by none other than Luis Von Ahn, so you know it&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/security01.png" alt="security01.png" title="security01.png" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />I&#8217;ve been tired of spam on my websites. The few hundreds messages spammers leave everyday are a bit of a nuisance.
Now though, I&#8217;ve decided to make them work harder to get their messages ignored.<br />
Last week, <a href="http://recaptcha.net/"><em>reCAPTCHA</em></a> came online. It&#8217;s an effort inspired by none other than <a href="http://en.wikipedia.org/wiki/Luis_von_Ahn">Luis Von Ahn</a>, so you know it&#8217;s good.</p>

<p><a title="Professor Luis Von Ahn   [Photo by Robin Rombach, Post-Gazette]" style="border:0;" href="/wp-content/uploads/images/LuisVonAhn.jpg" rel="lightbox"><img title="Professor Luis Von Ahn" src="/wp-content/uploads/images/LuisVonAhnSM.jpg" style="float:right;margin-left:10px;margin-bottom:5px;" /></a>If you don&#8217;t know him then he&#8217;s the mastermind being similar projects that centre around a simple premise: make humans do the work that computers can&#8217;t do.<br />
One of his on-going projects is the <em><a href="http://www.espgame.org/">ESP Game</a></em> where 2 online players are trying to come up with a common description of a random picture. It&#8217;s apparently an addictive game and it helps solve a problem that computers are terrible at today: describing accurately the content of photographs.<br />
<a href="http://images.google.com/imagelabeler/">Google</a> is using his research to make image search more useful by returning content more relevant to your queries.</p>

<p>So, what&#8217;s the relevance with the <a href="http://en.wikipedia.org/wiki/Captcha">CAPCTHA</a>?<br />
CAPTCHASs were invented to resolve a simple problem: stopping computers from automatically filling-in web forms to create accounts on popular free services that they would use to send spam from.<br />
They are a visual version of the <a href="http://en.wikipedia.org/wiki/Turing_test">Turing Test</a>, elaborated by the WWII genius cryptanalyst <a href="http://en.wikipedia.org/wiki/Alan_Turing">Alan Turing</a> as a way to test how far machines could behave like humans: not knowing who she was interacting with, if a person could not tell the difference between a human and a machine, then the machine passes the test. It&#8217;s a measure of the success -or lack of-  of artificial intelligence and the idea spawned many others, including CAPTCHAs.</p>

<p><img src="/wp-content/uploads/images/captcha-example.gif" width="116" height="57" style="float:left;margin-right:10px;margin-bottom:5px" />CAPTCHAs simply require that small problem be solved before a web form can be submitted. Typical problems include blurry and distorted images of text or numbers that would be very hard for computers alone to decipher, but that our brain has no problem solving.<br />
There are an estimated 60 millions of CAPTCHAs being solved by human beings every single day. That&#8217;s a huge amount of lost brain power as nothing really useful comes out of it (apart from preventing spam, of course).</p>

<p><img src="/wp-content/uploads/images/recpatcha_logo2_nobottom.gif" style="float:right;margin-left:10px;margin-bottom:5px" /><a href="http://recaptcha.net/"><em>reCAPTCHA</em></a>&#8216;s genius idea is to use that brain power to solve a problem that we would actually like computers to solve: digitizing books.<br />
There are millions of books that were printed in the days before computers became ubiquitous, and there exist no electronic version of them except scanned images of their pages.<br />
<em>Optical Character Recognition</em> software is getting very good, but when the scan is of poor quality or the book is old, many words cannot be automatically recognised.<br />
Humans on the other hand are quite good at reading words, even if they are badly distorted and barely recognisable.<br />
Instead of making up a distorted image that you would have to recognise, reCaptcha simply presents you with 2 words: one it knows and one it doesn&#8217;t and you&#8217;re asked to guess both.<br />
Every unknown word is checked multiple times by different people and you thus end-up with a very accurate interpretation of the word that can be fed back into the electronic version of the book being scanned.</p>

<p>CAPTCHA do not entirely solve the problem of spamming, but they are an financial issue to spammers: automated electronic system cannot solve good CAPTCHAs, so some <a href="http://petmail.lothar.com/design.html#auto34">spammer rely on low-paid humans</a> to do the dirty work for them.</p>

<p>It&#8217;s fine by me: poor people are getting paid to do something useful (help digitise books) and spammers are wasting their money doing so. In my case, they lose even more, because I use moderation to read comments before they are visible and <a href="http://akismet.com/">Askimet</a> to detect spam, which means that however hard they try, their spam never gets anywhere anyway.</p>

<p>In the fight against spammers, it makes me happy to know I&#8217;m costing them <em>something</em> for a change&#8230;</p>

<h3>References:</h3>

<ul>
<li>Breaking visual CAPTCHA<br />
<a href="http://www.cs.sfu.ca/~mori/research/gimpy/">http://www.cs.sfu.ca/~mori/research/gimpy/</a></li>
<li>Vulnerabilities of some CAPTCHA implementations (<a href="http://groups.google.com/group/recaptcha/browse_frm/thread/fd2dc5d846b0530d?">reCAPTCHA isn&#8217;t</a>)<br />
<a href="http://www.puremango.co.uk/cm_breaking_captcha_115.php">http://www.puremango.co.uk/cm_breaking_captcha_115.php</a></li>
<li>Luis Von Ahn&#8217;s website<br />
<a href="http://www.cs.cmu.edu/~biglou/">http://www.cs.cmu.edu/~biglou/</a></li>
<li>Lecture on Human computation by Luis von Ahn (technical, but very inspiring)<br />
<a href="http://video.google.com/videoplay?docid=-8246463980976635143">http://video.google.com/videoplay?docid=-8246463980976635143</a></li>
<li>The Internet Archive, benefiting from solving ReCAPTCHA, also a incommensurable source of free books<br />
<a href="http://www.archive.org/details/texts">http://www.archive.org/details/texts</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2007/thank-you-spammers/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>MediaWiki: Formating and colouring Code</title>
		<link>http://blog.nkadesign.com/2007/mediawiki-formating-and-colouring-code/</link>
		<comments>http://blog.nkadesign.com/2007/mediawiki-formating-and-colouring-code/#comments</comments>
		<pubDate>Tue, 20 Feb 2007 07:57:37 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[Web Design]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=39</guid>
		<description><![CDATA[MediaWiki is the wiki software behind WikiPedia. The issue, when using it as a software development tool, is formatting code in a pretty way. As we did with WordPress before, here are some details to make dp.SyntaxHighlighter work fairly seamlessly with MediaWiki. Install the client-side highlighter Download dp.SyntaxHighlighter. Uncompress its content under a new /skins/common/SyntaxHighlighter [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/technology01.png" alt="technology01.png" title="technology01.png" align="left" width="64" height="64" hspace="5" vspace="5" border="0" /><a href="http://www.mediawiki.org">MediaWiki </a>is the wiki software behind <a href="http://www.wikipedia.org">WikiPedia</a>.<br />
The issue, when using it as a software development tool, is formatting code in a pretty way.
<a href="http://blog.nkadesign.com/?p=30">As we did with WordPress before</a>, here are some details to make <a href="http://www.dreamprojections.com/syntaxhighlighter/">dp.SyntaxHighlighter</a> work fairly seamlessly with MediaWiki.</p>

<h3>Install the client-side highlighter</h3>

<p>Download <a href="http://www.dreamprojections.com/syntaxhighlighter/">dp.SyntaxHighlighter</a>.
Uncompress its content under a new <code>/skins/common/SyntaxHighlighter</code> folder in your MediaWiki installation (don&#8217;t forget to make sure the files can be read by the web server; for instance, on Linux you may use <code>chown apache.apache -R *</code>).</p>

<p>In the skin template you are using for your MediaWiki site, insert the necessary code as required. In my example, I use the default <code>/skins/MonoBook.php</code> template into which I added the following:</p>

<p>Just before the closing <code>&lt;/head&gt;</code> tag:<br />
<textarea name="code" class="xml:nogutter:nocontrols">
<!-- http://www.dreamprojections.com/syntaxhighlighter/ -->
<link type="text/css" rel="stylesheet" href="/skins/common/SyntaxHighlighter/Styles/SyntaxHighlighter.css"></link></textarea>Just before the closing <code>&lt;/body&gt;</code> tag:<textarea name="code" class="xml:nogutter:nocontrols"><!-- http://www.dreamprojections.com/syntaxhighlighter/ -->
<script language="javascript" src="/skins/common/SyntaxHighlighter/Scripts/shCore.js"></script>
<script language="javascript" src="/skins/common/SyntaxHighlighter/Scripts/shBrushCSharp.js"></script>
<script language="javascript" src="/skins/common/SyntaxHighlighter/Scripts/shBrushXml.js"></script>
<script language="javascript" src="/skins/common/SyntaxHighlighter/Scripts/shBrushSql.js"></script>
<script language="javascript" src="/skins/common/SyntaxHighlighter/Scripts/shBrushJScript.js"></script>
<script language="javascript" src="/skins/common/SyntaxHighlighter/Scripts/shBrushPhp.js"></script>
<script language="javascript">
    dp.SyntaxHighlighter.HighlightAll('code');
</script></textarea></p>

<blockquote>
  <p><em>Note that you must include a reference to each source file corresponding to the type of programming language you want to highlight.<br />
  Have a look under the <code>/skins/common/SyntaxHighlighter/Scripts/</code> folder to see which languages you can highlight; there are a lot more than the few I use on my site.</em></p>
</blockquote>

<h3>Install the WikiMedia extension</h3>

<p>I&#8217;ve created a small extension to WikiMedia to allow us to enclose any source code in a new <code>&lt;codesyntax&gt;</code> tag.
Click on the <em>View Plain</em> option below and copy-paste the following code into a new file that you will save under <code>/extensions/syntaxhighlighter.php</code> (again, make sure this is readable by the webserver).<br />
<textarea name="code" class="php:nogutter">&lt;?php
/************************************************************
** Simple WikiMedia extension to create a new &lt;codesyntax&gt; tag that renders 
** syntax highlighted through the dp.SyntaxHighlighter javascript helper
** See http://www.dreamprojections.com/syntaxhighlighter/
** See http://meta.wikimedia.org/wiki/Extending_wiki_markup
** (c) Renaud Bompuis, 2007
** ------------------------------------------------------------------------------
** v1.0 - 20EFB2007 : first version. Uses the &lt;pre&gt; tag to ensure that the content of 
** the &lt;textarea&gt; containing the source code will not be messed up by WikiMedia.
** There are certainly better ways to do this, but they seem more complicated than this 
** (registering hooks, recording content before it is expanded and then replacing 
**  messed up content with the original)
************************************************************/
$wgExtensionFunctions[] = "wfSyntaxHighlighterExtension";

function wfSyntaxHighlighterExtension() {
    global $wgParser;
    $wgParser->setHook( "codesyntax", "renderCodeSyntax" );
}

// The callback function for converting the input text to HTML output
function renderCodeSyntax( $input, $argv, &$parser ) {
	$output = "&lt;pre style='border:0;padding:0;margin:0;'&gt;"
			  ."&lt;textarea name='code' class='".$argv["lang"]."'&gt;"
			  .Xml::escapeTagsOnly($input)
			  ."&lt;/textarea&gt;&lt;/pre&gt;" ;
    return $output;
}
?&gt;</textarea><br />
Add the following line to the end of your <code>LocalSettings.php</code> file, right before the closing <code>?&gt;</code> tag.<br />
<textarea name="code" class="php:nogutter:nocontrols">
require_once 'extensions/syntaxhighlighter.php';
</textarea></p>

<h3>Usage</h3>

<p>To highlight code in your MediaWiki pages, just enclose your source code with the new <code>&lt;codesyntax&gt;</code> tag. This tag takes a <code>lang</code> attribute to specify the options that normally would be listed in the <code>class</code> attribute in the <em>dp.SyntaxHighlighter</em> documentation.</p>

<p>For example:<br />
<textarea name="code" class="php:nogutter:nocontrols">
&lt;codesyntax lang="c#"&gt;
string url = "&lt;a href=\"" + someObj.getUrl() + "\" target=\"_blank\"&gtl;";
// single line comments
// second single line
override protected void OnLoad(EventArgs e)
{
	if(Attributes["class"] != null)
	{
		//_year.CssClass = Attributes["class"];
	}
//	base.OnLoad(e);
}
&lt;/codesyntax&gt;
</textarea><br />
Will display as:<br />
<textarea name="code" class="c#">string url = "&lt;a href=\"" + someObj.getUrl() + "\" target=\"_blank\"&gt;";
// single line comments
// second single line
override protected void OnLoad(EventArgs e)
{
	if(Attributes["class"] != null)
	{
		//_year.CssClass = Attributes["class"];
	}
//	base.OnLoad(e);
}
</textarea></p>

<p>For more information on using <em>dp.SyntaxHighlighter</em> see:<br />
<a href="http://www.dreamprojections.com/syntaxhighlighter/Usage.aspx">http://www.dreamprojections.com/syntaxhighlighter/Usage.aspx</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2007/mediawiki-formating-and-colouring-code/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Chosing a development platform</title>
		<link>http://blog.nkadesign.com/2006/chosing-a-development-platform/</link>
		<comments>http://blog.nkadesign.com/2006/chosing-a-development-platform/#comments</comments>
		<pubDate>Sun, 01 Oct 2006 08:39:54 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Musing]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web Design]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=33</guid>
		<description><![CDATA[LAMP, Zend, .Net, Struts, Ruby on Rails, Catalyst, and a hundred other development platforms all compete for you attention, all pretending to be the only thing you&#8217;ll ever need to satisfy your every needs in web or UI development. Making a decision is really hard: you want the best for your new project and want [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/technology02.png" alt="technology02.png" title="technology02.png" align="left" width="64" height="64" hspace="5" vspace="5" border="0" /><a href="http://en.wikipedia.org/wiki/LAMP_%28software_bundle%29">LAMP</a>, Zend, .Net, <a href="http://struts.apache.org/">Struts</a>, <a href="http://www.rubyonrails.org/">Ruby on Rails</a>, <a href="http://www.catalystframework.org/">Catalyst</a>, and a hundred other development platforms all compete for you attention, all pretending to be the only thing you&#8217;ll ever need to satisfy your every needs in web or UI development.<br />
Making a decision is really hard: you want the best for your new project and want to make the right decision. In most cases, that means not cursing yourself down the line for a choice that didn&#8217;t turn out as expected.</p>

<p>When you start looking into all these platforms you can be blown away by the ease of implementation and elegance of some; your head spins at all the features and claims being made and it becomes hard to achieve a rational decision.</p>

<p>I&#8217;ve been faced with that very issue recently and it sucks. Actually, the time spent investigating all these possibilities is really what is being sucked away.<br />
Of course, learning about new technologies is not just fun, it&#8217;s also essential: you have to keep on top of what&#8217;s new and decide if you want to join in on the fun or just stay comfortably where you are.</p>

<p>I also realized that you need to get away from the coolness factor of each these much touted technologies and actually <em>try</em> to be objective.<br />
During my investigation, I tried to decide what were the really important factors that I should consider to make a rational choice.</p>

<p>I came up with the list of the following 10 questions that I think everyone should ask themselves when choosing a platform for an important project.</p>

<h3>1- Is the platform wide enough?</h3>

<p>New technologies that can show amazing productivity get all the buzz. After all, that&#8217;s what we developer want: enough with the nuts &amp; bolts! Give us a toolbox with all new shinny power tools!
The problem is that often these technologies are impressive, but looking beyond the sample projects into what actual users get confronted to, you start noticing discussion threads that should obviously signal that the platform is not wide enough.<br />
Choosing a technology that hasn&#8217;t achieved its goals can be a huge problem down the line: you implement 80% of your project in record time, only to realise that the platform you chose doesn&#8217;t support proper cross-browser detection, or that its implementation of security is way too lax, or that it only support XML for data storage and now you actually need a real database for performance reasons&#8230;<br />
In those cases, you can of course develop those areas yourself and contribute to the project, but doing so supposes that you planed it all along and you factored that in your schedule, both in time and in cost.</p>

<h3>2- Is it popular?</h3>

<p>In other words: are other professional people actually using that platform in real life?
I&#8217;m not talking about Joe Developer using it for his local community church website. I&#8217;m talking about businesses or large organisations actually using that software platform successfully.<br />
If all you need is a simple 3 page website, then professional popularity amongst the Top 500 business companies is probably not that important. On the other hand, if you plan to build a large project, or you know that your project could grow large in the future, then you probably want to ensure that others have taken it there before you.</p>

<h3>3- Is it mature?</h3>

<p>Has the platform existed for long enough that it went through enough abuse to withstand almost anything you can throw at it?<br />
A technology that is only a couple year old may be too young to have evolved to the point where it actually can solve most common and not-so-common problems. Technology evolves through iterations: each one is a good long hard look at what didn&#8217;t work and tries to fix, improve and extend.<br />
A young technology may be more cutting-edge and exciting, but when you need to commit to it for a big project, its age may quickly come as an issue; its shinny surface may blind you to the black holes waiting below&#8230;</p>

<h3>4- Are local developers available?</h3>

<p>Always think about the future. When you&#8217;re gone from the project, who is going to look after it?
Getting a web project entirely in <a href="href=&quot;http://www.rebol.com/">Rebol</a> may be cool and fun, but how many people in your city actually use that thing anyway?<br />
Aren&#8217;t you creating a liability if you&#8217;re dead-set on choosing a platform that cannot be maintained?</p>

<h3>5- Is it scalable?</h3>

<p>Most projects start small but dream of ending-up big.<br />
It&#8217;s usually fine at the beginning when the number of users and visitors is manageable, but what happens when you start to be successful?<br />
After all, that&#8217;s why we craft our projects: we want them to succeed, we want the world to see them. When the world starts coming though, will the terrific platform we&#8217;ve chosen break at the seams?<br />
How much overhead does the platform create? It is flexible in its database support? Is there a way to implement clustering or persisting sessions accross multiple servers?<br />
What&#8217;s the cost in memory and CPU resources? How many simultaneous connections can you get?   What are the bottlenecks? What do you need to do to compensate for them? How much would it cost?</p>

<h3>6- Do you have control?</h3>

<p>Some frameworks work hard for you and can make you really productive. Sometime though, they try too hard and hide too much from you.<br />
When a feature doesn&#8217;t exactly work the way you want you have to dig deep into the entrails of the beast to make sense of it and change its behaviour.<br />
A platform that was all nice and pretty can get very dirty and complex inside, making it difficult to adapt to your needs.<br />
A platform should do most of the hard work but still allow you to redefine its default behaviour without much hassle. It should be built with extensibility in mind, making easy thing easy and difficult things possible.<br />
A case in point are <a href="http://en.wikipedia.org/wiki/Fourth-generation_programming_language">4G</a> development platforms: they usually have a fairly narrow field of expertise and tend to use graphics and nice simple paradigms to quickly build complex tasks but when you are faced with a specific issue that hasn&#8217;t been solved by the platform, you often have to resort to ugly hacks to get around their limitations.</p>

<h3>7- Does it satisfies the essential constraints for your project?</h3>

<p>When being blinded by something cool, we often become skewed in our judgement and guilty of lowering the importance of constraints that are actually critical for our project.<br />
In all honesty, I really wanted to use Ruby on Rail, and I liked the principle and elegance of it so much that I came to seriously consider it, that is, until I came to my senses and looked into something that is critical to my project: support for complex Asian languages.<br />
Ruby is being developed in Japan, so you could think that it should be able to handle complex ideographic characters well.<br />
Turns out that the Japanese are not terribly fond of Unicode and, unless I&#8217;m mistaken, prefer to use <a href="http://en.wikipedia.org/wiki/Code_page">Code Pages</a> instead. The result is that Ruby doesn&#8217;t have great support for Unicode, and that sucks.<br />
That&#8217;s why Unicode was created: to attempt to simplify all this patchwork of implementations that are not compatible with each other.<br />
Because I needed to be able to handle English, Mandarin, Cantonese and probably any other language out there, Unicode is the only viable option to abstract the issue of language enough that it becomes manageable.<br />
So because of Ruby&#8217;s poor support for Unicode, it would not be rational to use Ruby on Rails for my particular project as it would probably greatly increase the complexity and hacks necessary to manage complex Asian languages in a unified and simple way.</p>

<h3>8- Documentation?</h3>

<p>All framework have a more or less steep learning curve: you need to think differently to adapt to the particular framework&#8217;s frame of mind, so to speak.<br />
Make sure that the framework has a lively community, that it has more documentation than you can swallow and that documentation is well organised.<br />
Make sure also that there are samples, tutorials, webcasts, videos or whatever that cover the principle aspects of it.<br />
A beautiful framework no-one talks about means that no-one will answer when you have a question. A beautiful framework without documentation is useless. A beautiful framework with lots of disorganised docs means that you&#8217;re going to waste a lot of time experimenting instead of building your project.</p>

<h3>9- Support?</h3>

<p>Here I mean support in the wide sense of the word: who is behind the framework. Are they likely to stay in business long after your project has been completed?<br />
Are they commercial or Open Source? In either case there are issues for and against: a commercial venture backed by a small company may falter and disappear overnight. Similarly, an exciting open source project managed by only 2 people can suffer the same fate when they decide to move on. 
Support also includes what help is available to you when you encounter issues. Is there any guarantee that you could have your important technical questions answered?<br />
If you encounter a large issue, is there someone to help you?<br />
I would contend that the best and most serious projects should have professional help available: you can always fall back on paying someone to help you through, whether it&#8217;s the original developers, a paid-for support hotline or a third-party specialist, it&#8217;s important that you know you can get your answers when you&#8217;re stuck.<br />
Developing for an important project without safety net is dangerous: you can waste a lot of time and effort, endangering the very project you are undertaking, if you stumble on a problem you cannot solve yourself.<br />
Large frameworks like .Net or big Open Source projects usually have enough users and support groups and specialists that it&#8217;s likely any question you may have has already been answered somewhere or that you can pay someone to help you out when you need it most.</p>

<h3>10- What do you know best?</h3>

<p>Every framework is based around a particular data-management model. Every framework is built with a particular programming language in mind. Every framework demands that you learn something new.
How comfortable are you with the requirements? how long is it going to take you to start to get really productive?<br />
Like their real-world counterpart, it can take very little time to learn a new language&#8217;s words and syntax but it takes years to become proficient in it. A framework adds another layer of abstraction that you will need to get experienced at.<br />
If you need to both learn a new language and a new framework, chances are that you are at best months away from being able to churn code without having to look into the documentation every 5 minutes.<br />
Learning new languages and concepts is necessary, but again, if you chose that route you must be sure that your project has that learning curve built-in, otherwise you&#8217;re going to move at the pace of a turtle when in fact you chose that particular framework because you though you would be more productive and faster than a sparrow.<br />
If you chose a new framework, make sure that you already possess most of the knowledge it requires: in my particular instance, I chose .Net and C# because I have already worked in that framework and I know it can tackle the project without me having to waste too much time on learning the platform rather than implementing the project.</p>

<p>We all should seize any opportunity to learn something new. Learning is often more exciting than doing the same old thing over and over again and it&#8217;s a necessary part of staying in business. Curiosity is an excellent quality that must be nurtured and indulged.<br />
The issue is <em>when</em> to do it.</p>

<p>Choosing a new development framework is not easy. The best way to tackle the problem is to pose it as a <em>risk analysis</em> study.</p>

<p>The framework you chose should simply be the one that poses the least risk to you succeeding your project.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2006/chosing-a-development-platform/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SysAdmin: When your computer becomes forgetful</title>
		<link>http://blog.nkadesign.com/2006/sysadmin-when-your-computer-becomes-forgetful/</link>
		<comments>http://blog.nkadesign.com/2006/sysadmin-when-your-computer-becomes-forgetful/#comments</comments>
		<pubDate>Wed, 20 Sep 2006 13:37:02 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=34</guid>
		<description><![CDATA[Sometimes your computer crashes without reason. It happens at any time, for no particular reason. Other times you&#8217;re trying to install a new OS on a brand new PC and at some point, it fails, reboot itself or just hangs. A couple years ago I had this really depressing experience with a brand new system [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/terror01.png" alt="Business" title="Business" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />Sometimes your computer crashes without reason. It happens at any time, for no particular reason.<br />
Other times you&#8217;re trying to install a new OS on a brand new PC and at some point, it fails, reboot itself or just hangs.</p>

<p>A couple years ago I had this really depressing experience with a brand new system I was building. All the components were newly bought, but installing the OS (a Linux distro) used to fail almost at the end of the process.<br />
No matter how many times I tried, I could never get to the end of it.<br />
By clever subterfuge I managed to get it installed only to have it crash on a regular basis.<br />
It was unstable, unreliable and after two days wasted banging my head against the walls, I gave up&#8230;</p>

<p><img id="image35" src="/wp-content/uploads/2006/09/memt_210.jpg" alt="Memtest86" align="right"/>
Well, no for too long. A flash of inspiration came to me and I popped in the install CD and ran the only utility that was available at the prompt: <a href="http://www.memtest86.com/">memtest86</a>.<br />
That simple tool is a godsend (if I may appropriate the word from the believers. I promise to give it back).
After running its various memory tests for 10 minutes it reported errors in one of the RAM sticks installed on the motherboard.<br />
All that aggravation for a puny bit that was not remembering its state&#8230;<br />
I promptly returned the RAM and tested the new one for a few hours until I was confident there was no issue with its chips and went my merry way to install the OS I so desperately needed. All went without a hitch.</p>

<p>So my advice is: go to the <a href="http://www.memtest86.com/">memtest86</a> website. Burn the bootable ISO and test your PC from time to time, especially if you have strange intermittent issues that you can&#8217;t pin down to a simple software problem.<br />
You&#8217;d be amazed at the number of times I had to ditch a stick of RAM&#8230; memtest86 saved by sanity countless times.<br />
By the way, consider <a href="http://www.memtest86.com/#donations">donating</a> a little bit if it helped you too. That&#8217;s always cheaper than a session with a shrink&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2006/sysadmin-when-your-computer-becomes-forgetful/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Software: Cheap Microsoft Licenses</title>
		<link>http://blog.nkadesign.com/2006/software-cheap-microsoft-licenses/</link>
		<comments>http://blog.nkadesign.com/2006/software-cheap-microsoft-licenses/#comments</comments>
		<pubDate>Mon, 18 Sep 2006 14:31:13 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=32</guid>
		<description><![CDATA[I&#8217;m not particularly pro -Microsoft but I&#8217;m not against it either. I love Linux, got my RHCE (Red Hat Certified Engineer) a bit more than a year ago and I love Open Source, Linux and all things GNU. The only thing I really dislike about Microsoft is its marketing, its pricing, its Genuine (Dis)Advantage that [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/money01.png" alt="Business" title="Business" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />I&#8217;m not particularly pro -Microsoft but I&#8217;m not against it either.<br />
I love Linux, got my <a href="http://etc.nkadesign.com/Linux/RedHatCertifications">RHCE</a> (Red Hat Certified Engineer) a bit more than a year ago and I love Open Source, Linux and all things <a href="http://gnu.org/">GNU</a>.</p>

<p>The only thing I really dislike about Microsoft is its marketing, its pricing, its <a href="http://www.securityfocus.com/columnists/409">Genuine (Dis)Advantage</a> that nags me every time I need to install something and its lack of openness when it comes to inter-operability with other competing implementations (here I&#8217;m particularly thinking about its network protocols that the <a href="http://samba.org/">Samba</a> team tries to decipher and re-implement as an Open Source platform).<br />
On the other hand, Microsoft is made of great programmers, great minds that you can watch on <a href="http://channel9.msdn.com/">Channel 9</a> and read on their insightful <a href="http://blogs.msdn.com/Bloggers.aspx">blogs</a>.</p>

<p>Microsoft is really (I mean REALLY) <a href="http://youtube.com/results?search_query=ballmer+developer">pro-developer</a>: they understand that the Operating System alone is nothing without lots of applications sitting on top of it, and they offer developers a lot of goodies.<br />
One such useful programme is +Microsoft Empower for ISV_. It&#8217;s a simple membership that allows a small software company (ISV meaning <em>Independent Software Developer</em>) to own a number of licenses for its internal use at a fraction of the price it would normally cost.<br />
What you get is pretty wide for a small business: 5 licenses for Windows XP (whatever version), 5 licenses for Microsoft Office, 1 license for Windows 2003 Server and Exchange, SQL Server, SharePoint Portal, a MSDN Premium Subscription that covers almost anything else, including 5 licenses for Visual Studio 2005 Pro.<br />
You also get access to MSDN downloads, beta software and tons of libraries, SDK, etc.
A MSDN subscription alone is about US$2000&#8230;<br />
The Empower ISV programme is quite cheap and depend on the country you are in.<br />
I paid mine HK$4,260 about US$530.</p>

<p>To get all this you need to register as a <a href="http://partner.microsoft.com/">Microsoft Partner</a> (that&#8217;s free), then apply for the <a href="https://partner.microsoft.com/global/40011351">Empower for ISV programme</a> by making a promise to release a commercial software within 2 year at most. You need to give some details and pay your due. After a few days, you get confirmation if your application is accepted or not.<br />
As far as I know, you need to be a company and have a company website, but that may not be mandatory in all regions.<br />
The software you get is the normal US version plus whatever local version there are for your region. My bunch of DVD came in Japanese, Cantonese, Mandarin, some in Korea and Thai too.<br />
At least, the English version is supplied. For some software, you also get the multilingual version that include European languages as well.<br />
You manage your licenses by login under your MSDN account.</p>

<p>Really, it&#8217;s a nice touch from Microsoft to give us poor developers access to all this for such a reasonable price. I can only encourage other small software companies and independent developers to do the same.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2006/software-cheap-microsoft-licenses/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>.Net: The limits of using Reflection</title>
		<link>http://blog.nkadesign.com/2006/net-the-limits-of-using-reflection/</link>
		<comments>http://blog.nkadesign.com/2006/net-the-limits-of-using-reflection/#comments</comments>
		<pubDate>Tue, 13 Jun 2006 00:00:27 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=29</guid>
		<description><![CDATA[Reflection is a hugely useful technology: it allows you to get inside objects and get their intimate details, modify their values and even rewrite part of their code. Today I wanted to build a simple treeview control that would display the hierarchical structure of an arbitrary object by going through its properties and building a [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/technology02.png" alt="technology02.png" title="technology02.png" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />Reflection is a hugely useful technology: it allows you to get inside objects and get their intimate details, modify their values and even rewrite part of their code.<br />
Today I wanted to build a simple treeview control that would display the hierarchical structure of an arbitrary object by going through its properties and building a tree-like structure. Useful to visualise the internals of an object and see changes at runtime.</p>

<p>Using PropertyInfo you get enough information about a particular property to decide if you want to display it or recurse into it if it&#8217;s a complex type that contain other properties.</p>

<p>The only big issue I faced was when dealing with <a href="http://msdn2.microsoft.com/en-us/6x16t2tx.aspx">indexers</a>.</p>

<h3>The issue with Indexers</h3>

<p>Indexers are defined in code like that:<br />
<textarea name="code" class="c#:nogutter:nocontrols" cols="50" rows="10">
using System;
using System.Collections;

public class DayPlanner
{
    // We store our indexer values in here 
    Hashtable _meetings = new System.Collections.Hashtable();

    // First indexer
    public string this[DateTime date] {
        get {
            return _meetings[date] as string;
        }
        set {
            _meetings[date] = value;
        }
    }

    // Second indexer, overloads the first
    public string this[string datestr] {
        get {
            return this[DateTime.Parse(datestr)] as string; 
        }
        set {
            this[DateTime.Parse(datestr)] = value;
        }
    }
}
</textarea>We&#8217;ve defined an overloaded indexer: one takes a <code>DateTime</code>, the other just a string representation of a date.</p>

<p>We could use them like that for instance:<br />
<textarea name="code" class="c#:nogutter:nocontrols" cols="50" rows="10">
DayPlanner myDay = new DayPlanner();
myDay[DateTime.Parse("2006/02/03")] = "Lunch";
...
string whatNow = myDay["2006/06/26"]; 
</textarea>
Now, let&#8217;s say we want to print all property names and their values for an arbitrary object.<br />
Let&#8217;s try on our <code>myDay</code> intance:<br />
<textarea name="code" class="c#:nocontrols" cols="50" rows="10">
Type type = myDay.GetType();
PropertyInfo[] picoll;
picoll = type.GetProperties( BindingFlags.Public 
          | BindingFlags.Instance | BindingFlags.Static);

foreach (PropertyInfo pi in picoll) {
    object val;
    val = pi.GetValue(myDay, null);
    Debug.WriteLine(pi.Name+"="+val) );
}
</textarea>So, that part is easy: we iterate through all properties of <code>myDay</code> and print their <code>Name</code> and they value.<br />
Problem is, when we reach the indexer property, we get a <code>TargetParameterCountException</code> on line&nbsp;8.</p>

<p>We need to detect the indexer before attempting to get its value.<br />
To do that, we need to modify our <code>foreach</code> loop to:<br />
<textarea name="code" class="c#:nocontrols"  cols="50" rows="10">
foreach (PropertyInfo pi in picoll) {
    object val;
    ParameterInfo[] parcoll = pi.GetIndexParameters();
    if (parcoll.Length == 0) {
        val = pi.GetValue(o, null);
        Debug.WriteLine(pi.Name+"="+val) );
    }
}
</textarea>
Here we attempt to get the indexer parameters for every property. If we&#8217;re dealing with an indexer, the <code>parcoll</code> array will contain a list of <code>ParameterInfo</code> related to that particular indexer.</p>

<p>So what really is this <code>parcoll</code> and its <code>ParameterInfo</code>s?</p>

<p>A <code>ParameterInfo</code> contain information about the parameter of an indexer property.<br />
The <code>parcoll</code> array will contain one entry for each overloaded indexer.<br />
In our concrete example this is what we get:</p>

<ul>
<li><code>pi.Name</code> will be <em>Items</em>, this is standard for all indexer properties.</li>
<li><code>pi.PropertyType</code> is the type of the returned class of our indexer, in our case, a <em>System.String</em>.</li>
<li><code>parcoll.Length</code> will be equal to 2 because we have 2 overloaded indexers.</li>
<li><code>parcoll[0].Name</code> will be <em>date</em>.</li>
<li><code>parcoll[1].Name</code> will be <em>datestr</em>.</li>
<li><code>parcoll[0].ParameterType</code> will be <em>System.DateTime</em>.</li>
<li><code>parcoll[1].ParameterType</code> <em>System.String</em>.</li>
<li><code>parcoll[0].Member</code> and <code>parcoll[1].Member</code> are in fact references to <code>pi</code> itself</li>
</ul>

<p>That&#8217;s a lot of nice information about our indexer, but what if we want to get a value from it?
Consider the definition for <code>GetValue</code>:<br />
<textarea name="code" class="c#:nogutter:nocontrols"  cols="50" rows="10">
PropertyInfo.GetValue(object o, object[]{} index).
</textarea>
That second parameter is used to get a value from the indexer.</p>

<h3>So, how do we use it?</h3>

<p>If you know valid keys that you can feed to the indexer, then you just do that (assuming that <code>pi</code> is the <code>PropertyInfo</code> for the indexer).<br />
<textarea name="code" class="c#:nogutter:nocontrols"  cols="50" rows="10">
string meeting;
meeting = pi.GetValue(myDay, new string[]{"2006/02/25"}) as string;
</textarea>
Or, if you prefer to use a <code>DateTime</code>:
<textarea name="code" class="c#:nogutter:nocontrols"  cols="50" rows="10">
string meeting;
meeting = pi.GetValue(myDay, new DateTime[]{DateTime.Now}) as string;
</textarea>
But what if you don&#8217;t know anything about the values contained by the indexer?<br />
Well, unless you use attributes to decorate the indexer or the underlying storage field with specific custom information, you&#8217;re basically screwed.</p>

<p>To understand why, just consider how the indexer is implemented:<br />
When you pass it a <code>DateTime</code> or a <code>string</code> as a parameter, it just passes it on to the getter/setter as the <code>value</code>.<br />
What is done with that is up to the implementer.<br />
If you want to maintain a collection of some kind, then you need to use private fields to hold the keys and their values.<br />
.Net doesn&#8217;t store the values passed to the indexer or the values returned by it anywhere.</p>

<p>Consider how .Net doesn&#8217;t give you any means of iterating through the keys and values of an indexer.<br />
You can&#8217;t do a <code>for(;;)</code> or a <code>foreach()</code> loop, you can&#8217;t even know how many items are maintained through the indexer by directly questioning it.<br />
So, it certainly is normal that you cannot get anything out of the indexer without knowing exactly how to access it.</p>

<h3>The Observer Effect</h3>

<p>In many fields of science, the act of measuring something, whether it&#8217;s an electronic circuit or a psychological experiment, can actually influence the observed phenomenon.<br />
This is unsurprisingly called the <a href="http://en.wikipedia.org/wiki/Observer_effect">Observer Effect</a>.</p>

<p>In .Net, Reflecting on object can be very much the same.</p>

<p>Consider the use of Reflection when it comes to getting information about an object:<br />
You use metadata describing the object to get more meta data information about its members
You can use that meta data to direcly query the state of an object.</p>

<p>If you limit yourself to getting metada, then no harm is done: you&#8217;re not querying the object instance itself but the metadata about its class.</p>

<p>If you start querying an actual object instance for its values then you are actively interacting with it.<br />
In most cases, if you&#8217;re just getting the value of Fields or Properties defined as follow, then it&#8217;s fine:<br />
<textarea name="code" class="c#:nogutter:nocontrols"  cols="50" rows="10">
class GetMe {
    private string _meeting;
    public string Meeting {
        get { return _meeting; }
        set {
            _meeting = value;
        }
    }
}</textarea>
Using reflection, we can get the values of both <code>_meeting</code> and <code>Meeting</code> without any side-effect to the object.</p>

<p>Now consider this:<br />
<textarea name="code" class="c#:nogutter:nocontrols"  cols="50" rows="10">
class GetMeNot {
    private int _collection = null;
    public int Collection {
        get { 
            if ( _collection == null ) {
                OpenDatabaseConnection();
                _collection = FetchAllData();
            }
            return _collection; 
        }
    }
}</textarea>
Now what we&#8217;ve got here is a case of lazy loading or <a href="http://en.wikipedia.org/wiki/Lazy_initialization">lazy initialization</a>.<br />
The consequence is that by querying the Collection property we&#8217;re actually creating it, with a potential for a lot of side-effects, like the change of other properties, here maybe related to opening the database connection for instance.</p>

<p>So, when getting values of the properties of an object instance, we can actually completely change its state.<br />
Whether this is a concern or not really depends on what you&#8217;re trying to achieve: you may not be able to achieve being a passive observer using Reflection unless you know about the construction of the particular class you&#8217;re dealing with.<br />
Using Attributes, you could give hints about which Property not to query and which Field to get instead. In our case, we could add a custom attribute like <code>[ImplementedBy("_collection")]</code> to our <code>Collection</code> property for instance.</p>

<p>If you want to do something generic, then you&#8217;re out of luck it and have to deal with that fact.<br />
One possible way to minimize the effect would be to not query Properties that only have a getter and no setter, but that&#8217;s not a guarantee that all properties that implement a getter/setter are going to play nice.<br />
Then there is also the -probably rarer- case of the Property that only has a setter.<br />
Then there is also the case of the property getter that has some in-build security and will return different things depending on who&#8217;s calling&#8230;</p>

<p>All this seems pretty obvious once you understand the whole picture but it&#8217;s easy to get so impressed and dazzled by the power of Reflection that you don&#8217;t realise its natural limits.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2006/net-the-limits-of-using-reflection/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>WordPress: Formating and colouring Code</title>
		<link>http://blog.nkadesign.com/2006/wordpress-formating-and-colouring-code/</link>
		<comments>http://blog.nkadesign.com/2006/wordpress-formating-and-colouring-code/#comments</comments>
		<pubDate>Sun, 11 Jun 2006 12:00:28 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Web Design]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=30</guid>
		<description><![CDATA[WordPress is pretty good, but it comes with no code formatting tool, yet colouring facilities. I like the simplicity of dp.SyntaxHighlighter for displaying source code in web pages: it works with major browsers and degrades fairly well. Its particularity is that is does its painting magic on the client side. This can be a drawback [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/technology01.png" alt="technology01.png" title="technology01.png" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />WordPress is pretty good, but it comes with no code formatting tool, yet colouring facilities.
I like the simplicity of <a href="http://www.dreamprojections.com/syntaxhighlighter/">dp.SyntaxHighlighter</a> for displaying source code in web pages: it works with major browsers and degrades fairly well.</p>

<p>Its particularity is that is does its painting magic on the client side. This can be a drawback in some instances, where the client browser has JavaScript disabled for instance, but since the code to paint is located within <code>&lt;textarea&gt;</code> tags, it will still display no matter what.</p>

<p>Configuring _dp.SyntaxHighlighter_to work in WordPress is pretty easy: just add the relevant code in your WordPress templates for header and footer according to the instructions found on the website and you&#8217;re done.</p>

<p>The issue though is making it possible to insert code when writing a post.<br />
First of all, I doubt that there is any elegant way to make one of the rich HTML editors work well, so you&#8217;ll have to go back to basics and edit in HTML (WordPress at least hides the <code>&lt;br&gt;</code> and <code>&lt;p&gt;</code> tags so its&#8217; not too bad).<br />
Then there is the issue of WP adding the <code>&lt;br&gt;</code> and <code>&lt;p&gt;</code> to replace linefeeds, and this is where it becomes annoying: if you insert <code>&lt;textarea&gt;</code> tags, everything in it will have the extraneous formatting code that will display verbatim on screen, sprinkling your nice source code with ugly html tags.</p>

<p>The solution I found was to use a small WordPress plug-in called <code>codeautoescape</code> and available from:<br />
<a href="http://priyadi.net/archives/2005/09/27/wordpress-plugin-code-autoescape/">http://priyadi.net/archives/2005/09/27/wordpress-plugin-code-autoescape/</a></p>

<p>I then modified it a bit to take care of the <code>&lt;textarea&gt;</code> tag and the fact that we needed to take the attributes of the tag into account (<em>dp.SyntaxHighlighter</em> uses the <em>class</em> attribute to configure options for how to display the block of code).</p>

<p>You can download the modified version of the script: <a href="/wp-content/uploads/2006/06/codeautoescape.txt">codeautoescape</a></p>

<p>To install it, just right-click and download from the link, rename it to <code>codeautoescapte.php</code> then install it in your <code>/wp-content/plugins</code> folder and activate it within the <em>Plugins</em> menu of WordPress.</p>

<hr />

<p>Some examples of <a href="http://www.dreamprojections.com/syntaxhighlighter/">dp.SyntaxHighlighter</a> in action:</p>

<h3>C#</h3>

<p><textarea name="code" class="c#:firstline[42]">
1	2	3	4	5	6	7	8	9
string		path			= "";
string		safeReferrer	= null;
FileInfo	fileInfo		= new FileInfo(string.Format("{0}/{1}", path, image));
int			index			= 0;
</textarea></p>

<p><textarea name="code" class="c#:collapse">
// single line comments
// second single line
override protected void OnLoad(EventArgs e)
{
	if(Attributes["class"] != null)
	{
		//_year.CssClass = _month.CssClass = _day.CssClass = Attributes["class"];
	}
//	base.OnLoad(e);
}

/***********************************
 ** Multiline block comments
 **********************************/

/// <summary>
///		Gets or sets currently selected date of birth or <see cref="DateTime.MinValue"/> if selection is incomplete or invalid.
/// </summary>
public DateTime Date
{
	String stringWithUrl = "http://blog.dreamprojections.com";
	
	get
	{
		#region Hello world
		try
		{
			/*
			DateTime result = new DateTime(
				int.Parse(_year.SelectedItem.Value),
				int.Parse(_month.SelectedItem.Value),
				int.Parse(_day.SelectedItem.Value)
				);
			
			i *= 2;
			*/
			return result;
		}
		catch
		{
			/* return _minDate; */
		}
		#endregion
	}
	set
	{
		Day		= value.Day;
		Month	= value.Month;
		Year	= value.Year;
	}
}
</textarea></p>

<h3>JavaScript</h3>

<p><textarea name="code" class="javascript">
/***********************************
 ** Multiline block comments
 **********************************/

var stringWithUrl1 = "http://blog.dreamprojections.com";
var stringWithUrl2 = 'http://www.dreamprojections.com';

// callback for the match sorting
dpSyntaxHighlighter.prototype.SortCallback = function(m1, m2)
{
	// sort matches by index first
	if(m1.index < m2.index)
		return -1;
	else if(m1.index > m2.index)
		return 1;
	else
	{
		/*
		// if index is the same, sort by length
		if(m1.length < m2.length)
			return -1;
		else if(m1.length > m2.length)
			return 1;
		*/
	}
	
	alert('hello // world');
	return 0;
}
</textarea></p>

<h3>XML / HTML</h3>

<p><textarea name="code" class="xml">
<?xml version="1.0" encoding="utf-8" ?> 

<!-- comments -->
<rootNode>
	<childNodes>
		<childNode attribute = "value" attribute='value' attribute=/>
		<childNode />
		<childNode />
		<childNode />
		<childNode attribute="value"></childNode>
		<childNode>
			&lt;![CDATA[
				this is some CDATA content
				<!-- comments inside cdata -->
				<b alert='false'>tags inside cdata</b>
			]]&gt;
		</childNode>
	</childNodes>
</rootNode>

<!--
  -- Multiline comments <b>tag</b>
  -->
</textarea></p>

<h3>PHP</h3>

<p><textarea name="code" class="php">
/***********************************
 ** Multiline block comments
 **********************************/

$stringWithUrl = "http://blog.dreamprojections.com";
$stringWithUrl = 'http://www.dreamprojections.com';

ob_start("parseOutputBuffer");		// Start Code Buffering
session_start();

function parseOutputBuffer($buf) {
	global $portal_small_code, $portal_gzcompress;
	global $PHP_SELF, $HTTP_ACCEPT_ENCODING;

	// cleaning out the code.
	if($portal_small_code && !$portal_gzcompress) {
		$buf = str_replace("	", "", $buf);
		$buf = str_replace("\n", "", $buf);
		$buf = str_replace(chr(13), "", $buf);
	}
}
</textarea></p>

<h3>SQL</h3>

<p><textarea name="code" class="sql">
SELECT TOP 10
	FirstName,
	LastName,
	Email,
	--SUBSTRING(Phone, 2, 3) AS CityCode,
	SUBSTRING(Phone, 7, 8) AS PhoneNumber,
	upper(LanguagePref) AS Language,
	Address1,
	UpdatedOn AS CreatedOn
FROM
	profiles
WHERE
	-- Exclude all test emails
	Email NOT LIKE '%test%'
	AND Email NOT LIKE '%asdf%'
ORDER BY
	UpdatedOn DESC

</textarea></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2006/wordpress-formating-and-colouring-code/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>XPO: eXpress Persistent Objects</title>
		<link>http://blog.nkadesign.com/2006/xpo-express-persistent-objects/</link>
		<comments>http://blog.nkadesign.com/2006/xpo-express-persistent-objects/#comments</comments>
		<pubDate>Fri, 09 Jun 2006 04:00:31 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[XPO]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=28</guid>
		<description><![CDATA[<img src="/wp-content/uploads/technology02.png" alt="technology02.png" title="technology02.png" align="left" width="64" height="64" hspace="5" vspace="5" border="0" /><a href="http://www.devexpress.com/Products/NET/XPO/">XPO </a>is an Object Relational Mapping .Net product from <a href="http://www.devexpress.com">Developer Express</a>, a cool company designing cool tools.
It's a programming component whose job is to abstract access to database while allowing the developer to concentrate on a simple object-oriented interface instead.]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/technology02.png" alt="technology02.png" title="technology02.png" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />
<a href="http://www.devexpress.com/Products/NET/XPO/">XPO</a> is an Object Relational Mapping .Net product from <a href="http://www.devexpress.com">Developer Express</a>, a cool company designing cool tools.<br />
It&#8217;s a programming component whose job is to abstract access to database while allowing the developer to concentrate on a simple object-oriented interface instead.<br />
<span id="more-28"></span></p>

<p>There is an impedance mismatch between the usual programming technology and the database worlds. 
The mismatch occurs because most development is object-oriented and most database systems are query-based.<br />
Getting data from the database into your objects and back is tricky and difficult to maintain: any modification in either camp needs to be reflected to the other.</p>

<p>One solution is to use an intermediate layer to take care of the impedance mismatch for us: that&#8217;s the job of he ORM.</p>

<p>When I initially took the decision to use an ORM I tried and reviewed a few. Each have a different way of doing their job and place emphasis on different things, depending on the school of thought they belong to.<br />
Most still require a database-centric view and either abstract the whole and let you deal with meta-data that used to modify both code and database or they just let you modify the database and then update automatically the code.<br />
Then there was XPO.<br />
This one was a bit different: it really completely abstracted the database. It would create and update it automatically (whenever possible) without you having to ever deal with how the data is stored: it would work in the exact same way regardless of the underlying chosen database.<br />
You could even use it on an already existing database and it would be happy to talk to it.</p>

<p>So I chose XPO.<br />
It didn&#8217;t have fancy designers but it offers a simple, reliable and flexible way to persist my objects in the database of my choosing.<br />
One thing to note too is that you can get it with full source code (not commented though).<br />
I find it reassuring when a company doesn&#8217;t mind its code to be scrutinised by its customers. It&#8217;s also proven invaluable in finding out XPO&#8217;s inner working (not that I understand a lot though).</p>

<p>I&#8217;ll be blogging a few articles in the future on various aspects of XPO that I think may be of interest to those already working with it. I&#8217;m not going to re-state what&#8217;s in the documentation or on the Developer Express (DX) community website and official pages, there is a lot of information available out there, it&#8217;s just sometimes hard to get to know the fundamentals because it&#8217;s sometime buried deep.
Whenever possible (depending on time and complexity) I&#8217;ll make a sample project. I&#8217;m even thinking about building a repository of samples showcasing various aspects of XPO.</p>

<p>Let&#8217;s see if I can hold the load for long&#8230;. I&#8217;ve also committed myself to DXCore recently&#8230; but that&#8217;s something for another post altogether&#8230;</p>

<h3>References:</h3>

<ul>
<li>Official XPO product page<br />
<a href="http://www.devexpress.com/Products/NET/XPO/">http://www.devexpress.com/Products/NET/XPO/</a></li>
<li>XPO articles on the DX Community blog<br />
<a href="http://community.devexpress.com/blogs/xpo/">http://community.devexpress.com/blogs/xpo/</a></li>
<li>DX Peer Support newsgroups<br />
<a href="http://www.devexpress.com/Support/Newsgroups.xml">http://www.devexpress.com/Support/Newsgroups.xml</a></li>
<li>DX Knowledge base articles<br />
<a href="http://devexpress.com/Support/KnowledgeBase/">http://devexpress.com/Support/KnowledgeBase/</a></li>
<li>DX Support center where additional information, tips and bug reports can be found.<br />
<a href="https://www.devexpress.com/support/center/">https://www.devexpress.com/support/center/</a></li>
<li>An extensive list and description of available ORM for .Net<br />
<a href="http://www.howtoselectguides.com/dotnet/ormapping/">http://www.howtoselectguides.com/dotnet/ormapping/</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2006/xpo-express-persistent-objects/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>What&#8217;s your Star Trek profile?</title>
		<link>http://blog.nkadesign.com/2006/whats-your-star-trek-profile/</link>
		<comments>http://blog.nkadesign.com/2006/whats-your-star-trek-profile/#comments</comments>
		<pubDate>Sun, 04 Jun 2006 23:45:04 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Fun]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=27</guid>
		<description><![CDATA[<img src="/wp-content/uploads/mood02.png" alt="mood02.png" title="mood02.png" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />I was visiting <a href="http://www.paraesthesia.com/blog/weblog.php">http://www.paraesthesia.com/</a> for the latest version of a VS Studio add-in and Travis, the owner of the site, had his <em>"Star Trek profile"</em>. I suppose most people working in technical fields turn out to be the same...]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/mood02.png" alt="mood02.png" title="mood02.png" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />I was visiting <a href="http://www.paraesthesia.com/blog/weblog.php">http://www.paraesthesia.com/</a> for the latest version of a VS Studio add-in and Travis, the owner of the site, had his <em>&#8220;Star Trek profile&#8221;</em>. 
I suppose most people working in technical fields turn out to be the same&#8230;
<center>Your results:<br />You are <span style="text-size:larger;"><strong>Geordi LaForge</strong></span></center></p>

<table style="text-align:left;margin-top:0;padding-top:0;"><tr><td><table><tr><td>Geordi LaForge</td>
<td><hr ALIGN=LEFT NOSHADE SIZE=4 WIDTH=70/></td><td> 70%</td>
</tr><tr><td>Spock</td>
<td><hr ALIGN=LEFT NOSHADE SIZE=4 WIDTH=52/></td><td> 52%</td>
</tr><tr><td>Jean-Luc Picard</td>
<td><hr ALIGN=LEFT NOSHADE SIZE=4 WIDTH=50/></td><td> 50%</td>
</tr><tr><td>Mr. Scott</td>
<td><hr ALIGN=LEFT NOSHADE SIZE=4 WIDTH=50/></td><td> 50%</td>
</tr><tr><td>An Expendable Character (Redshirt)</td>
<td><hr ALIGN=LEFT NOSHADE SIZE=4 WIDTH=45/></td><td> 45%</td>
</tr><tr><td>Deanna Troi</td>
<td><hr ALIGN=LEFT NOSHADE SIZE=4 WIDTH=45/></td><td> 45%</td>
</tr><tr><td>Mr. Sulu</td>
<td><hr ALIGN=LEFT NOSHADE SIZE=4 WIDTH=45/></td><td> 45%</td>
</tr><tr><td>James T. Kirk (Captain)</td>
<td><hr ALIGN=LEFT NOSHADE SIZE=4 WIDTH=45/></td><td> 45%</td>
</tr><tr><td>Will Riker</td>
<td><hr ALIGN=LEFT NOSHADE SIZE=4 WIDTH=40/></td><td> 40%</td>
</tr><tr><td>Data</td>
<td><hr ALIGN=LEFT NOSHADE SIZE=4 WIDTH=37/></td><td> 37%</td>
</tr><tr><td>Chekov</td>
<td><hr ALIGN=LEFT NOSHADE SIZE=4 WIDTH=35/></td><td> 35%</td>
</tr><tr><td>Leonard McCoy (Bones)</td>
<td><hr ALIGN=LEFT NOSHADE SIZE=4 WIDTH=35/></td><td> 35%</td>
</tr><tr><td>Beverly Crusher</td>
<td><hr ALIGN=LEFT NOSHADE SIZE=4 WIDTH=30/></td><td> 30%</td>
</tr><tr><td>Worf</td>
<td><hr ALIGN=LEFT NOSHADE SIZE=4 WIDTH=20/></td><td> 20%</td>
</tr><tr><td>Uhura</td>
<td><hr ALIGN=LEFT NOSHADE SIZE=4 WIDTH=20/></td><td> 20%</td>
</tr></table></td>
<td>You work well with others and often<br />  fix problems quickly. Your romantic<br />  relationships are often bungled.<br /> 
<img SRC="http://www.seabreezecomputers.com/startrek/pics/geordi.jpg"/></td>
</tr></table>

<p><a HREF="http://www.seabreezecomputers.com/startrek">
Click here to take the Star Trek Personality Test</a><br /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2006/whats-your-star-trek-profile/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The Importance of Conditions of Sales</title>
		<link>http://blog.nkadesign.com/2006/the-importance-of-conditions-of-sales/</link>
		<comments>http://blog.nkadesign.com/2006/the-importance-of-conditions-of-sales/#comments</comments>
		<pubDate>Fri, 02 Jun 2006 23:00:59 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Musing]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=26</guid>
		<description><![CDATA[<img src="/wp-content/uploads/money01.png" alt="Business" title="Business" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />In a past life, working as a project manager for a manufacturer of railway equipment, I had to deal with detailed specifications and conditions of contract that would be big thick documents of hundred of pages each.]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/money01.png" alt="Business" title="Business" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />
In a past life, working as a project manager for a manufacturer of railway equipment, I had to deal with detailed specifications and conditions of contract that would be big thick documents of hundred of pages each.
<span id="more-26"></span></p>

<p>I used to love/hate these. I would hate them when they were clearly biased in the favour of the customer (for these kind of large multi-million dollar contracts, the customer imposes his rules), and I would love them -or at least appreciate them- when they were fair and balanced as they would clarify every party&#8217;s duties and responsibilities.<br />
After leaving that world and starting my own IT business I wanted the relationship with my customers to be as non-threatening and amicable as possible.</p>

<p>I decided -stupidly- not to have stringent legal documents defining the terms of the sales. What I would do instead was spend time making sure that the customer understood everything by explaining at length what they were getting and ensuring that they were no misunderstanding. In my written offers, I would painstakingly describe the technical part of their project and clearly mention what they were getting, when and at what cost.<br />
My rationale was not to scare customers away and instil trust by being verbose and friendly.</p>

<p>Well, that worked for a little while until a particular customer ordered a server as part of a larger web-site project.<br />
Once she confirmed her order to me I promptly ordered the hardware from Dell and paid for it in advance (their requirement for processing the order). A few days later, she phones and calls the whole project off, a project we&#8217;ve been spending time on for nearly 2 months.<br />
She just happened to realise that she wouldn&#8217;t have time to build the content for it.</p>

<p>Well, that&#8217;s where not having stringent sales conditions bit me in the arse. When I told her I already ordered the hardware and couldn&#8217;t refund her until I got my own refund from Dell she started to spin her own fantasies and self-indulged delusions and started to treat me like a common criminal.
She became a complete lunatic and I really didn&#8217;t know how to handle her any longer. I even gave her copies of my correspondence with Dell, bank account statements to show that the server was paid for&#8230;<br />
In the end, I tried to explain where her assumptions were wrong and told her she would get her refund at the latest on a certain date, based on what Dell told me would be the longest waiting period.
Turned out that it took 6 weeks to get my refund, just in time for hers.</p>

<p>The morale of this story is that:</p>

<ul>
<li>you shouldn&#8217;t be naively stupid and think you can base your relationship with a client on trust only.</li>
<li>you should have conditions of sales accessible on your website and refer to them in all your correspondence with your clients.  </li>
<li>you shouldn&#8217;t work with people who can have a propensity for confabulation. That particular customer was a provider of dubious alternative medicines and was clearly a lost cause to reason. My first instinct and moral judgment of not working for her was right and I should have listened to it instead of just thinking about the much-needed cash it could get me&#8230;</li>
</ul>

<p>&#8230;which bring me to the last lesson: don&#8217;t sell your ideals for money, however bad you need it.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2006/the-importance-of-conditions-of-sales/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>You Aren&#8217;t Gonna Need It</title>
		<link>http://blog.nkadesign.com/2006/you-arent-gonna-need-it/</link>
		<comments>http://blog.nkadesign.com/2006/you-arent-gonna-need-it/#comments</comments>
		<pubDate>Thu, 01 Jun 2006 01:00:03 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Musing]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=14</guid>
		<description><![CDATA[<img src="/wp-content/uploads/technology02.png" alt="technology02.png" title="technology02.png" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />Refactoring code is a necessary thing. Unless you work in some very specific environment where casual refactoring is not allowed (like in some safety-critical applications where the most minute change has to be pondered upon by teams and committees for weeks), you cannot code perfectly on the first shot.
More often, you end-up reviewing code and making it clearer, merging parts that are too similar, removing what turned out not to be useful, cleaning up the names, moving things around, etc... there are dozen of refactoring cases that usually help <a href="http://www.codinghorror.com/blog/archives/000589.html" target="_blank">remove the stink out of it</a>.]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/technology02.png" alt="technology02.png" title="technology02.png" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />
Refactoring code is a necessary thing. Unless you work in some very specific environment where casual refactoring is not allowed (like in some safety-critical applications where the most minute change has to be pondered upon by teams and committees for weeks), you cannot code perfectly on the first shot.<br />
More often, you end-up reviewing code and making it clearer, merging parts that are too similar, removing what turned out not to be useful, cleaning up the names, moving things around, etc&#8230; there are dozen of refactoring cases that usually help <a href="http://www.codinghorror.com/blog/archives/000589.html">remove the stink out of it</a>.
<span id="more-14"></span></p>

<p>One self-inflicting problem I&#8217;ve often been confronted to is <em>over-engineering</em>: I tend to <em>over-think</em>, <em>over-design</em> and <em>over-anticipate</em>.<br />
Sometimes it&#8217;s good to just spend time trying to make your code more modular and as future-proof as you can, but often, it leads to code that has no real use <em>right-now</em>, and that ends up having to be modified because when you need it, it&#8217;s not in the form you&#8217;ve implemented it originally.<br />
This is an <em>Extreme Programming</em> practice aptly named <a href="http://xp.c2.com/YouArentGonnaNeedIt.html">You Aren&#8217;t Gonna Need It</a>.</p>

<p>A classic example of <a href="http://xp.c2.com/YouArentGonnaNeedIt.html">YagNi</a> that I am paying dearly is a large application I&#8217;m working on at the moment (at least large from the perspective a single developer).<br />
It&#8217;s a fairly complex database application with an equally demanding winform GUI layer in C# on top.<br />
I built the GUI in a very modular fashion: each bit of information that could be grouped has its own <a href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.usercontrol.aspx">User Control</a>, sealing its particularities.<br />
Then each of these controls is used in panels that embody another layer of functionality.<br />
Each panel is then loaded as needed into a form that display the panels on demand.<br />
The issue is that I now have to make major changes to the application and there are too many layers in these controls, making code hard to change.<br />
I had built it this way for re-use, thinking that it could be useful to have independent specialized controls, say for entering addresses, or customer details, etc.</p>

<p>Well, each of these controls took me a lot of time to craft, trying to make them as independent upon my particular implementation as I could. It turns out though that I&#8217;ve used each control no more than once -maybe twice for a couple- in the whole of the application, and I now realize that it&#8217;s unlikely that I would get another job that would require the exact same user-interface broken down the exact same way.<br />
So my uber-GUI controls are mostly a waste of time and complexity.</p>

<p>I should have simply created the forms directly, using <a href="http://www.devx.com/dotnet/Article/22603">partial classes</a> (a new .Net 2 feature) to separate each logical part into something manageable.<br />
My application would have been faster to develop and faster to run, with a lot less of unnecessary layers of abstraction.</p>

<p>I&#8217;m having a hard time with that, but I&#8217;m getting better, hopefully&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2006/you-arent-gonna-need-it/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>All sites won&#8217;t work with IE7</title>
		<link>http://blog.nkadesign.com/2006/ie7-wont-work-with-all-sites/</link>
		<comments>http://blog.nkadesign.com/2006/ie7-wont-work-with-all-sites/#comments</comments>
		<pubDate>Wed, 31 May 2006 01:00:42 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Musing]]></category>
		<category><![CDATA[Reviews]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=12</guid>
		<description><![CDATA[<img src="/wp-content/uploads/technology01.png" alt="technology01.png" title="technology01.png" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />I installed a <a href="http://www.microsoft.com/windows/ie/" target="_blank">beta of IE7</a> last week and was quite pleased at the new interface and tabbed browsing, which has been available to <a href="http://www.opera.com/" target="_blank">Opera</a> and <a href="http://www.mozilla.org/"  target="_blank">Mozilla</a> used and many other browsers for years.
However, looking good and being slick and more standard-compliant hasn't been enough to keep it on my machines.]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/technology01.png" alt="technology01.png" title="technology01.png" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />I installed a <a href="http://www.microsoft.com/windows/ie/" target="_blank">beta of IE7</a> last week and was quite pleased at the new interface and tabbed browsing, which has been available to <a href="http://www.opera.com/" target="_blank">Opera</a> and <a href="http://www.mozilla.org/"  target="_blank">Mozilla</a> used and many other browsers for years.<br />
However, looking good and being slick and more standard-compliant hasn&#8217;t been enough to keep it on my machines.
<span id="more-12"></span></p>

<p>The main issue is that IE7 is now yet-another browser that web designers have to test and include support for.<br />
It may not be a huge deal for most sites, but some do rely on specific browser versions. In my case the problem arose when I tried to connect to my company&#8217;s online bank account. For security reasons (?!) it only supports IE6, not even Firefox so it&#8217;s one of the few sites that requires Internet Explorer.
Problem is that IE7 replaces IE6 entirely, with the unfortunate result that I now can&#8217;t connect to my bank accounts (company accounts only, the portal for personal accounts supports Firefox).<br />
So I&#8217;ve had to remove that beta.</p>

<p>That is certainly a specific issue, but it will be interesting to see how fast websites that rely on specific versions of browsers, be it for security reasons (because they want to simplify their development to a manageable level and support well a single browser) or because they rely heavily on CSS and JavaScript, how fast these websites will adapt.<br />
Early adopters of Vista will now doubt have a few -temporary I&#8217;m sure- surprises.</p>

<p>I think Microsoft made a big mistake when they decided to stop development of IE6 and not incorporate any more improvements into it.<br />
Maybe the company was under too much legal spotlight at the time and leaving the scene for a while was a move to appease those who were concerned about its monopoly on internet browsing.<br />
The unfortunate side-effect was that the browser millions relied-on had still some important flaws. Its User Interface and usability has now been overtaken by Firefox and Opera which benefited from the development interrruption of IE.</p>

<p>I am not sure if IE can become better than Firefox in terms of extensibility: Firefox sports thousands of extensions and themes to customize it. I&#8217;ve got quite a few useful ones that are certainly particular to my way of browsing the net. How is MS going to integrate that into IE7?<br />
What made Firefox popular was its focus on carrying-on where IE6 had left and offering a better browsing environment that could be customized with all the widgets and utilities that you wanted.<br />
If MS doesn&#8217;t incorporate the same level of extensibility, it will carry-on losing a big share of its browser market to Firefox, at least in the personal user world.</p>

<p>But Maybe Microsoft doesn&#8217;t care too much about browser wars any longer.<br />
When you approach perfect standard compliance, which browser you use to render the content isn&#8217;t important any longer. Since MS failed in the past to tie revenues to the browser itself (remember the ill-fated channels that would bring commercial content to your browsers back in the days of IE4? No?, well I&#8217;m not surprised&#8230;) the incentive for building a better browser is elsewhere.</p>

<p>One of the reasons that may be motivating MS is that a lot of its other products are increasingly dependent on the Internet. In a corporate environment, almost all business-oriented services are accessed through a web interface of some kind.<br />
Microsoft must ensure that it retains the monopoly on these implementations to keep control of the complete user experience.<br />
If MS wasn&#8217;t pursuing its IE development, more companies would start to look at alternatives, not only to IE, but also to larger expensive products like Exchange: once you accept that IE isn&#8217;t needed to offer rich client-side user interfaces, and that you don&#8217;t need Exchange either, you&#8217;re endangering Microsoft hold on the corporate market somewhat.<br />
So going further and ensuring tight integration of its products together is paramount.</p>

<p>IE7 is also terribly important to MS on the home user-front: making sure that users use the same browser both at home and at work ensures that they are more likely to stay with what they know rather than accept using a new browser, that may require retraining for some.<br />
That reason may seem feeble, but it ensures that the vast majority of people is not exposed to other alternative technologies.<br />
Without IE7, that risk becomes real as more and more savvy users and corporations are turning to Firefox for its increased security (or at least for the fact that it is a lesser target to malware).</p>

<p>That factor alone may obviously not be sufficient to force a company to move away from MS, but it may be sufficient to poison the mind by making people to consider alternatives they would otherwise be somewhat reluctant to contemplate by fear of the unknown; a fear that MS has not shied away from exacerbing through its <a href="http://lxer.com/module/newswire/view/57261/index.html" target="_blank">FUD campaigns</a>.</p>

<p>Of course, all this requires a few grains of salt, I may be completely wrong&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2006/ie7-wont-work-with-all-sites/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WordPress: Fixing PNG transparency issues in IE</title>
		<link>http://blog.nkadesign.com/2006/wordpress-fixing-png-transparency-issues-in-ie/</link>
		<comments>http://blog.nkadesign.com/2006/wordpress-fixing-png-transparency-issues-in-ie/#comments</comments>
		<pubDate>Tue, 30 May 2006 06:27:15 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Web Design]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=13</guid>
		<description><![CDATA[<img src="/wp-content/uploads/technology01.png" alt="technology01.png" title="technology01.png" align="left" width="64" height="64" hspace="5" vspace="5" border="0" /> I'm using <a href="http://wordpress.org/" target="_blank">WordPress </a>to blog this. I usually prefer to use PNG images over GIF for their ability to have variable alpha-channel transparency that makes them look good over any background. 
PNGs are a much greater improvement over the old GIF's single-colour transparency mask.]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/technology01.png" alt="technology01.png" title="technology01.png" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />
I&#8217;m using <a href="http://wordpress.org/">WordPress</a>to blog this. I usually prefer to use PNG images over GIF for their ability to have variable alpha-channel transparency that makes them look good over any background. 
PNGs are a much greater improvement over the old GIF&#8217;s single-colour transparency mask.<br />
<span id="more-13"></span>
The issue is that while 8-bit PNG are similar to GIF images and display well in Internet Explorer 5.5 and 6, full-colour PNG with transparency do not: they are drawn with an opaque grey or coloured background where they should be transparent.</p>

<p>This has been a major pain for web designers trying to make their site look nice and a lot of hacks have been invented to get around the problem.</p>

<p style="border:solid 1px #FEC42D;background:#FEF2DA;color:#C48000;padding:5px;">Note: Before implementing the solution described here, have a look at the references added on 31AUG2008 to the bottom of the article as they may offer more modern alternatives.<br />
If they don&#8217;t work for you, then use the one described below.
</p>

<p></p>

<h3>A solution</h3>

<p>The one I like best is using <a href="http://msdn.microsoft.com/library/default.asp?url=/workshop/author/behaviors/overview.asp">DHTM Behaviors</a>, a Microsoft-only CSS extension that allows a programmer to extend the IE&#8217;s capabilities using JavaScript.</p>

<p>The behavior is loaded using a directive in your normal style sheet. Since it&#8217;s an IE-specific extension, it&#8217;s safely ignored by all other browsers. Similarly, you don&#8217;t need to change your HTML at all.<br />
All that&#8217;s required is that you download a 1&#215;1 pixel blank GIF image, the PNGbehavior script and add a couple of lines to the style sheet used in your site.</p>

<p>I&#8217;ve described <a href="http://etc.nkadesign.com/Programming/PmWikiCSS">a specific implementation for PmWiki</a> before, this one is targeted to WordPress users.</p>

<ul>
<li>Get the <a href="/wp-content/themes/blank.gif">blank.gif</a> and <a href="/wp-content/themes/pngbehavior.htc">pngbehavior.htc</a> files and save them in your 
WordPress&#8217; <code>/wp-content/themes/</code> folder.</li>
<li>Modify your theme&#8217;s stylesheet (for the <em>default</em> WordPress theme, it&#8217;s in 
<code>/wp-content/themes/default/style.css</code>) by adding the following anywhere in its file:</li>
</ul>

<pre><code>/* Fix for PNG alpha channel display in IE6 */
img {
  behavior: url("/wp-content/themes/pngbehavior.htc");
}
</code></pre>

<p>That&#8217;s all!</p>

<p>If you&#8217;re saving the behavior file or the blank GIF in another location, you will have to change the paths in the pngbehavior.htc file.</p>

<p>Make sure that the PNG images in your pages have their proper <code>width</code> and <code>height</code> set, otherwise if these attributes are missing from the <code>&lt;img&gt;</code> tag the images will appear as single pixel dots in Internet Explorer.</p>

<p>Note that I&#8217;ve modified the behavior file to make sure it can be used with the excellent <a href="http://www.huddletogether.com/projects/lightbox2/">LightBox JS 2.0</a> image display overlay script.</p>

<p>The original PNG hack comes from the impressive <a href="http://webfx.eae.net/">WebFX</a>  website.</p>

<h3>Resources</h3>

<ul>
<li><a href="http://webfx.eae.net/dhtml/pngbehavior/pngbehavior.html">http://webfx.eae.net/dhtml/pngbehavior/pngbehavior.html</a></li>
<li><a href="http://www.huddletogether.com/projects/lightbox2/">http://www.huddletogether.com/projects/lightbox2/</a></li>
<li><a href="http://msdn.microsoft.com/workshop/author/behaviors/overview.asp">http://msdn.microsoft.com/workshop/author/behaviors/overview.asp</a></li>
</ul>

<h3>Modification on 30NOV2006</h3>

<p>Corrected the pngbehavior script to only work in IE5.5 and IE6 as IE7 now correctly displays transparent PNG images.</p>

<h3>Modification on 17FEB2007</h3>

<p>Another reference to a slightly different implementation: <a href="http://homepage.ntlworld.com/bobosola/index.htm">http://homepage.ntlworld.com/bobosola/index.htm</a></p>

<h3>Modification on 31AUG2008</h3>

<p>A few of more comprehensive references:</p>

<ul>
<li><a href="http://24ways.org/2007/supersleight-transparent-png-in-ie6">http://24ways.org/2007/supersleight-transparent-png-in-ie6</a></li>
<li><a href="http://www.alistapart.com/stories/pngopacity/">http://www.alistapart.com/stories/pngopacity/</a></li>
<li><a href="http://labs.unitinteractive.com/unitpngfix.php">http://labs.unitinteractive.com/unitpngfix.php</a></li>
<li><a href="http://code.google.com/p/ie7-js/">http://code.google.com/p/ie7-js/</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2006/wordpress-fixing-png-transparency-issues-in-ie/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>SlickRun: Desktop command-line launcher</title>
		<link>http://blog.nkadesign.com/2006/slickrun/</link>
		<comments>http://blog.nkadesign.com/2006/slickrun/#comments</comments>
		<pubDate>Sun, 28 May 2006 07:31:59 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Reviews]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=6</guid>
		<description><![CDATA[<img width="64" vspace="5" hspace="5" height="64" border="0" align="left" title="technology02.png" alt="technology02.png" src="http://blog.nkadesign.com/wp-content/uploads/technology02.png" />If you feel you often have to interrupt your typing to move your mouse around and click on it to open applications or websites, the SlickRun is the perfect power toy for you.

It's just a small application that can either stay in your tray until you call for it or that can display a small semi-transparent prompt where you can type in configurable commands that it will launch.]]></description>
			<content:encoded><![CDATA[<p><img width="64" vspace="5" hspace="5" height="64" border="0" align="left" alt="technology02.png" title="technology02.png" src="http://blog.nkadesign.com/wp-content/uploads/technology02.png" />
If you feel you often have to interrupt your typing to move your mouse around and click on it to open applications or websites, then SlickRun is the perfect power toy for you.<br />
It&#8217;s just a small application that can either stay in your tray until you call for it or that can display a small semi-transparent prompt where you can type in configurable commands that it will launch.
<span id="more-6"></span>
<center><img src="/wp-content/uploads/2006/05/SlickRun01.png" alt="SlickRun prompt" /></center><br />
Options include the ability to open the SlickRun prompt wherever your mouse cursor is at the moment you invoke it with its keyboard shortcut (by default the Windows key + Q, but it&#8217;s configurable).<br />
I just love it.<br />
You can chain commands together, easily add complex commands to open specific folders or websites, the list is endless.</p>

<p>To help you type less, it has built-in autocompletion, meaning that usually only the first 2-3 letters of a command are enough.<br />
<center><img src="/wp-content/uploads/2006/05/SlickRun02.png" alt="SlickRun in action" /></center><br />
For instance, I have created commands for opening <em>Visual Studio</em> with various projects preloaded, to open the <em>Add Remove Programs</em> control panel (just create a command that runs appwiz.cpl) and even one to open TrueCrypt so it just has to ask me my password to mount the encrypted password file that I have on my USB memory key (passing to truecyrpt.exe the options <code>/lz /q /e /v "E:\Crypt\Passwords.crypt"</code>).</p>

<p>Give it a shot, it&#8217;s free, but if you use and like it please consider a small offering to the developer so he gets the motivation to carry on working on it.</p>

<p>Get it from <a href="http://www.bayden.com/SlickRun/">http://www.bayden.com/SlickRun/</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2006/slickrun/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Microsoft Office 2007 beta 2</title>
		<link>http://blog.nkadesign.com/2006/microsoft-office-2007-beta-2/</link>
		<comments>http://blog.nkadesign.com/2006/microsoft-office-2007-beta-2/#comments</comments>
		<pubDate>Sat, 27 May 2006 12:05:32 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Reviews]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=3</guid>
		<description><![CDATA[<img width="64" vspace="5" hspace="5" height="64" border="0" align="left" title="technology02.png" alt="technology02.png" src="/wp-content/uploads/technology02.png" />I received an email from Microsoft updates this morning and there awas a link to download the latest beta of Office 2007.<br />
After registering, I got a few files including the <em>Microsoft Office Professional Plus</em> package at about 440MB and proceeded to installing the beast.]]></description>
			<content:encoded><![CDATA[<p><img width="64" vspace="5" hspace="5" height="64" border="0" align="left" title="technology02.png" alt="technology02.png" src="/wp-content/uploads/technology02.png" />I received an email from Microsoft updates this morning and there was a link to download the latest beta of Office 2007.
After registering, I got a few files including the <em>Microsoft Office Professional Plus</em> package at about 440MB and proceeded to installing the beast.</p>

<p>I must say that my first impression is that a lot of effort has been put in the interface. It&#8217;s simply magnificient, with subtle colours and a very pleasing responsiveness.</p>

<p><a rel="lightbox" href="/wp-content/uploads/images/office2007beta01.png"><img width="250" vspace="5" hspace="5" height="215" border="0" align="right" alt="Office 2007 User Interface" title="Office 2007 User Interface" src="/wp-content/uploads/images/office2007beta01tn.png" /></a> Now for all those Microsoft bashers who can&#8217;t see anything out of Redmond without scorn and disdain should look again. MS is often criticised for not being inovative, but they are taking a fairly big risk with Office 2007: the user interface of classic drop-down menus has now been changed for Ribbons, a large band of actions and functions that coherently group actions together, as buttons, menus and drop-downs.</p>

<p>While it&#8217;s easy to move around the interface, I can&#8217;t really comment yet on how quickly you get used to it or if it&#8217;s really a major improvement to usability.
No doubt that legions of corporate users will have to be re-trained to familiarize themselves with the new interface, and that cost is going to make businesses think twice in upgrading the already over-the-top Office 2003 into something that does not really add any must-have features for the average user.</p>

<p>Sure, some large corporations will integrate reviewing and document exchange into their overall Microsoft-supplied architecture and no doubt that MS will find the marketing and commercial pressure points to <em>&#8220;encourage</em>&#8221; users into upgrading, but let&#8217;s face it: what do you need a word processor, a spreadsheet or a presentation package to do?</p>

<p>I&#8217;d say that close to 100% of the features you&#8217;ll ever need from an office suite have already been implemented years ago, so the pressure to keep you upgrading is now focused on improvements that most of us will never use anyway and, of course&#8230; eye-candy.
Microsoft is taking a gamble but they have to: after Office 2003 there is not really anything significant to accomplish in the realm of office suites.
Microsoft is trying to pull the rug under eveyone&#8217;s feet to make sure it still has the lead in some ways: between a demure-looking <a title="Open Office Org, free Office Suite" href="http://www.openoffice.org/">OpenOffice</a> and the latest itration of MS Office, it&#8217;s going to be hard not to consider OO outdated, and I&#8217;m sure Microsoft will exploit that very feeling.
Apple has demonstrated that User Interface is <em>everything</em>.
I mean it!
Apple&#8217;s hardware and software have polished, beautiful UIs.
They have made of eye-candy and ease of use their driving marketing force.
Everyone just assumes that an iPod is vastly superior in quality to anything else, but that&#8217;s not true. Everyone just want an iPod because they easy to use and are beautiful objects to own, like affordable jewelry that actually has a function. That has made them cool.
Microsoft is now selling us improved software that we don&#8217;t really need, but that they need to shove down our throat to keep themselves in business.
To achieve that and attract us like flies to dung, they have polished their products and made them <em>very </em>shinny.</p>

<p>I&#8217;m sure we won&#8217;t be able to resist&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2006/microsoft-office-2007-beta-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>China Telecom blocking email access?</title>
		<link>http://blog.nkadesign.com/2006/china-telecom-blocking-email-access/</link>
		<comments>http://blog.nkadesign.com/2006/china-telecom-blocking-email-access/#comments</comments>
		<pubDate>Sat, 27 May 2006 03:00:48 +0000</pubDate>
		<dc:creator>Renaud Bompuis</dc:creator>
				<category><![CDATA[Privacy]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://blog.nkadesign.com/?p=4</guid>
		<description><![CDATA[<img src="/wp-content/uploads/security01.png" alt="security01.png" title="security01.png" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />For months, every time more than a handful of connections were made between my ex-employer's office in Shanghai and their email server in Hong Kong, the latter would become unreachable, not just for email but for web access as well. The strange thing was that access to the rest of the Internet would be untouched.<br />
This prompted me to experiment with ways to circumvent the ISP's port blocking restrictions.<br />
The fight was on!]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/security01.png" alt="security01.png" title="security01.png" align="left" width="64" height="64" hspace="5" vspace="5" border="0" />
I sometimes -although not often- work for my previous employer, a railway equipment manufacturer, to set up Linux servers.</p>

<p>They called me earlier this week to help them find a solution to a problem they had with getting their email off the company server, located in Hong Kong, from their office in Shanghai.<br />
<span id="more-4"></span>
For months, every time more than a handful of connections were  made, the server in Hong Kong would become unreachable, not just for email but for web access as well. The strange thing was that access to the rest of the Internet would be untouched.<br />
Only that server would become impossible to access after a little while.</p>

<p>The office in Shanghai uses an ADSL connection provided by China Telecom. It&#8217;s a standard broadband service with a dynamic IP allocated every time they reconnect to the network. Nothing special there except that they block port 25 -used to send email-.<br />
A lot of ISP do that in an effort to block spammers and worms infecting desktop PC: they require you to use their own SMTP servers to send email.<br />
If it was only port 25, it would have been fine, but other ports to <em>collect</em> email would trigger the blocking behaviour as well: getting your email through IMAP or simple POP3 on ports 143 and 110 would result in everyone in the office being unable to connect to fetch their email.<br />
When this occurred, the ADSL modem had to be physically disconnected. Everything would be fine again for a short while after reconnecting and getting a new IP.</p>

<p>So that was the situation when I started to think about ways to circumvent all that.</p>

<p>First thing I did was to open some randomly chosen ports on the mail server and redirect all traffic from those ports to their corresponding local ports: you would now access email on port 523 instead or the normal 143 for IMAP, etc.<br />
Well, this didn&#8217;t work for long. After just a few hours it seem that <em>they</em> caught up with us again and we were back to square one.</p>

<p>Whatever was blocking the connection was more clever than just blindly blocking a few designated ports, it was also analysing the content of network packets to specially detect email activity.<br />
The second solution was to again use 3 non-specific ports on the server for SMTP, IMAP and POP3, but this time use secure encryption (SSL) to ensure that the packets could not be analysed.</p>

<p>So far this seems to have worked. The only instance of blocking the office suffered so far was due to a laptop that was still using the original ports to send/receive email. Once its mail client was reconfigured, things went back to normal.</p>

<p>This spurred me add a couple of technical articles to my long and extensive <a href="http://etc.nkadesign.com/EmailServer/EmailServer">email server how-to</a> on <etc.nkadesign.com>: <a href="http://etc.nkadesign.com/EmailServer/SecureAccess">SecureAccess</a>, <a href="http://etc.nkadesign.com/EmailServer/AlternateAccess">AlternateAccess</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nkadesign.com/2006/china-telecom-blocking-email-access/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

