<?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 &#187; .Net</title>
	<atom:link href="http://blog.nkadesign.com/category/programming/net/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.nkadesign.com</link>
	<description>Renaud Bompuis on the interwebs!</description>
	<lastBuildDate>Sat, 14 Jan 2012 06:30:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>.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>23</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>73</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>64</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>.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>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>
	</channel>
</rss>

