SMS MessageInterceptor Class Leaves Registry Clutter Behind

You Can Take it With You

Syndication

News

  • Don't miss the next Windows Mobile Webcast... Unit Testing for Mobile Devices: http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032382824&EventCategory=4&culture=en-US&CountryCode=US.

I was doing some work with the MessageInterceptor class yesterday - as I was doing some tests, I was checking the registry to be sure that my program wasn't leaving any registry clutter behind. Much to my surprise, I found a substantial amount of clutter in the registry ... but not from my program's direct-registry work ... rather it was from the MessageInterceptor class.

Note: The issue discussed in the post relate to transient message interceptors (begin and end with a program) not persistent message interceptors. Persistent message interceptors explicitly remove their registry entries by calling DisableApplicationLauncher.

Why does it happen?

As you know, the MessageInterceptor class cooperates with the Windows Mobile messaging sub-system. The MessageInterceptor class creates a new registry key under HKLM\Software\Microsoft\Inbox\Rules along with some sub-keys and values to identify the MessageInterceptor's characteristics (interception condition, whether message should be deleted, etc.) to the messaging sub-system.

The MessageInterceptor is supposed to automatically remove these registry entries when the MessageInterceptor is no longer in use. The problem is that it doesn't do this cleanup consistently. The problem is that the code to cleanup the registry entries is in the class' Finalizer method but not in the class' Dispose method ... and ... when you call the Dispose method, the Dispose method calls GC.SuppressFinalizer which prevents the Finalizer method from running (which is what you normally want a Dispose method to do).

One possible solution would be to not call Dispose - but saying "I know MessageInterceptor implements IDisposable but don't call the Dispose method" just doesn't feel right and not calling Dispose is kind'a bad style.

Also... if you create the MessageInterceptor to handle events on a non-UI thread (pass false to the useFormThread constructor parameter), you must call Dispose to shutdown the event handler thread. If you don't call Dispose, your application will hang when you try to exit.

The MessageInterceptor registry entries are volatile and are therefore automatically removed when you soft-reset the device. That said, I wouldn't want to be the one to tell a user that my application requires them to reset their device on a regular basis (especially if that user was my boss).

How to fix it

The MessageInterceptor class doesn't immediately create the registry entries at construction but rather waits until you attach an event handler to the MessageInterceptor.MessageReceived event. Well, just as attaching an event handler to the MessageReceived event creates the registry entries, removing the event handler from the MessageReceived event will delete the corresponding registry entries. Just as you'd expect, when you associate multiple handlers with the MessageReceived event, it waits until the last event handler is removed before deleting the registry entries

So the bottom line is... you should always explicitly remove all MessageInterceptor.MessageReceived event handlers prior to exiting your program so as to avoid leaving registry clutter.  Here's a short example....

C#

MessageInterceptor _smsInterceptor = null;
private void Form1_Load (object sender, EventArgs e)
{
    // Create MessageInterceptor Normally
    _smsInterceptor = new MessageInterceptor();
    _smsInterceptor.MessageCondition = new MessageCondition(MessageProperty.Sender,
        MessagePropertyComparisonType.Contains, "Smith, John", false);
    _smsInterceptor.MessageReceived += SmsInterceptor_MessageReceived;
}

private void Form1_Closed(object sender, EventArgs e)
{
    if (_smsInterceptor != null)
    {
        // explicitly remove event handler before exiting
        _smsInterceptor.MessageReceived -= SmsInterceptor_MessageReceived;
        _smsInterceptor.Dispose();
    }
}

Visual Basic .NET

Private _smsInterceptor As MessageInterceptor = Nothing
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuEx1.Click
    ' Create MessageInterceptor Normally
    _smsInterceptor = New MessageInterceptor()
    _smsInterceptor.MessageCondition = New MessageCondition(MessageProperty.Sender, _
        MessagePropertyComparisonType.Contains, "Smith, John", False)
    AddHandler _smsInterceptor.MessageReceived, AddressOf SmsInterceptor_MessageReceived
End Sub

Private Sub Form1_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Closed
    If Not _smsInterceptor Is Nothing Then
        RemoveHandler _smsInterceptor.MessageReceived, AddressOf SmsInterceptor_MessageReceived
        _smsInterceptor.Dispose()
    End If
End Sub

One last point... I have not performed explicit tests on the effects of the excess registry entries, but my casual observation is that the process of routing messages to active MessageInterceptor instances appears to be slowed by the existence of these extraneous registry  entries.


Posted Oct 26 2007, 09:36 AM by jim-wilson

Comments

Hayes Haugen wrote re: SMS MessageInterceptor Class Leaves Registry Clutter Behind
on 12-04-2007 3:30 PM
Nice find. I knew that orphaned reg keys caused interception problems and failures but had no idea the system classes were the cause of some of those orphans. It definitely stops working in an app instance at some point.

I've had nothing but trouble from the SMS classes in the CF. They just don't work consistently across all devices. It's burned a lot of dev time and we eventually had to do our own native solution.

Add a Comment

(required)  
(optional)
(required)  
Remember Me?