July 2006 Entries
ZedGraph - open source charting component

Just started using a rather nifty little charting component at home by the name of ZedGraph. It's released under the LGPL which means it can be linked to without "infecting" commerical apps with the license (one of the criticisms oft leveled at the GPL). There's a handy set of tutorials / examples available online and it works better than a lot of commercial components I've tried (built in panning / zooming / save as image, etc).

It's .NET 2.0 only unfortunately but is capable of some fairly impressive visuals (for something that's free) and runs in both WinForms and ASP.NET.

Tracing between AppDomains

Problem :

AppDomain 1 creates a new AppDomain (2) to run tasks within, tracing from AppDomain 2 needs to be conducted in AppDomain 1 to allow external app (NUnit) to access the Console where it's all being written.

Solution :

4 new classes :

  • RemoteAppDomainEventHandlers - serializable class containing the event handling code to run in AppDomain 1
  • RemoteTraceEventArgs - serializable event args used to transport tracing info between AppDomains
  • RemoteTraceListener - sub class of TraceListener, wraps a RemoteTracing instance
  • RemoteTracing - MarshalByRefObject that receives trace messages from RemoteTraceListener and raises events back to AppDomain 1

When AppDomain 2 is created an instance of RemoteTracing is created and unwrapped into AppDomain 1, EstablishRemoteTracing is called which sets up a RemoteTraceListener in AppDomain 2, finally the trace event is wired up to the RemoteTrace handler on an instance of RemoteAppDomainEventHandlers.

// we need to hook in tracing from the app domain back to here
m_remoteTracing = (RemoteTracing)m_appDomain.CreateInstanceAndUnwrap("com.iMeta.ApplicationUpdate","com.iMeta.ApplicationUpdate.Remote.RemoteTracing");
m_remoteTracing.EstablishRemoteTracing();
m_remoteTracing.Trace+=new TraceEventHandler(m_eventHandlers.RemoteTrace);
public void EstablishRemoteTracing()
{
   // clear any existing trace listeners
   System.Diagnostics.Trace.Listeners.Clear();
   // create one of our remote listeners that wraps this RemoteTracing object
   RemoteTraceListener rtl = new RemoteTraceListener(this);
   System.Diagnostics.Trace.Listeners.Add(rtl);
}

Then when a call is made to Trace.Write in AppDomain 2 it hits the following code in the RemoteTraceListener

public override void Write(string message, string category)
{
   m_remote.SendTraceToClient(message,category);
}

Which in turn calls the RemoteTracing instance it was created with:

public void SendTraceToClient(string message, string category)
{
   // create a RemoteTraceEventArgs object and raise event with it
   RemoteTraceEventArgs rtea = new RemoteTraceEventArgs(message,category);
   OnTrace(rtea);
}

An event gets raised in AppDomain 2 and AppDomain 1 handles it by writing the trace in it's domain.

Originally the event handler for AppDomain 1 was on the class that loaded the AppDomain, this didn't seem to work too well as the event handlers were running in AppDomain 2 which caused some fun StackOverflowExceptions!

Add Comment Filed Under [ C# .NET 1.1 ]
Posting images into your blog

Was asked how I got the image into my previous post. Here you go:

  • Add a gallery
  • Add the image to the gallery
  • View the image in the gallery and get the URL
  • Paste the URL in an img tag (watch out for a double slash in the URL).
  • Voila! Images in your blog
Add Comment Filed Under [ General ]
SQL Server 2005 Mirroring and Users

Setting up a SQL Server 2005 mirrored environment outside of a Domain where the client connects using Windows Authentication? We had oddles of fun with this on MiVoice Vote, as the Principal and Mirror servers have no idea about each others users so you need to do a bit of jiggery pokery to get your code to connect to each one succesfully.

Setup your mirroring environment as normal, creating a SQL Login / Database user as normal on the Principal tied to the Windows User the client will connect as. Then fail the mirror over so that the roles are swapped (Principal becomes Mirror and vice versa). Now create another SQL Login / Database user (with a different username) on the new Principal (was the Mirror) tied to the Windows User (you have created the Windows User accounts on the two machines with the same username/password, haven't you?) on that machine.

Fail back and everything should be good to go. The diagram below shows how it ended up on MiVoice Vote:

You'll need to make sure that the two database users have the same access rights as each other.

One Comment Filed Under [ SQL Server 2005 ]
TabPage transparency in WinForm 2.0 apps

Ever noticed that TabPages added to TabControls in WinForms become transparent, effectively making all child controls display with a white background (same as the TabControl itself)?

Ever had it where controls randomly decide that they're not going to play ball and display using the default control colour (that lovely grey)? The TabPage checks the background colour of subcontrols are one of the default colours called Control, and even if that's what's set for the BackColor property on your control it may not be enough. It seems that it has to be the "Default" Control colour which you can reset to by selecting the value of the property and then deleting it.

Voila! The control reverts its' BackColor to the super special "Default" Control colour and everything's groovy again.

 

Add Comment Filed Under [ .NET 2.0 WinForms ]
ASP.NET 2 and NAnts XmlPoke task

ASP.NET 2 includes a default namespace declaration in a default web.config as :

xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"

The XmlPoke / XmlPeek tasks in NAnt really doesn't like this and will fail to find any nodes with an XPath expression. Simple solution is to remove the declaration from the web.config. So far this hasn't broken anything that depends on the web.config (at least for me).