Skip navigation

Monthly Archives: May 2007

Author: Jeff Noble

I have run into a problem while trying to deal with exceptions in the Composite UI Application Block (CAB). It seems that while in the IDE in debug mode, everything works as expected. However, when running without debugging (or running the .exe directly) unexpected behavior occurs.

Reproducing the unexpected

  1. Create a new CAB project (I use the Guidance package to do this). I am calling mine CABSample
  2. Add a foundational Module. I called mine SampleFoundation.
  3. Create a View in the Foundational Model. I called mine SampleView.
  4. Add the following Code in the load event of the Module.cs file in the SampleView project:

    SampleView view = _rootWorkItem.SmartParts.Get<SampleView>(“SampleView”);

    if (view == null)
    {
    view = _rootWorkItem.SmartParts.AddNew<SampleView>();
    }

    view.Dock = DockStyle.Fill;
    _rootWorkItem.Workspaces[WorkspaceNames.RightWorkspace].Show(view);

  5. Drag a button onto the SampleView control. I will be bypassing the whole MVP model for this example to keep things simple.
  6. Double click the button and add the following into the click event (yes I know it’s a divide by zero error):

    int a = 1;
    int b = 2;
    int c = 0;
    int d = a + b / c;

  7. Set the project to Release Mode and Run the project (without debugging) , and click the button.

You now see an error instead of the expected dialog box. The reason that this is not the expected behavior is that there is code in the shell application to handle unexpected errors. The code looks like this (and it should already be in place in your project):

In Shellapplication.cs – RunInReleaseMode():

AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AppDomainUnhandledException);

In Shellapplication.cs – AppDomainUnhandledException():

private static void AppDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
HandleException(e.ExceptionObject as Exception);
}

private static void HandleException(Exception ex)
{
if (ex == null)
return;

THIS LINE WILL FAIL WITHOUT AN EXCEPTION POLICY SO COMMENT IT OUT IF YOU HAVE NOT SET ONE UP
//ExceptionPolicy.HandleException(ex, “Default Policy”);
MessageBox.Show(“An unhandled exception occurred, and the application is terminating. For more information, see your Application event log.”);
Application.Exit();
}

So why if we have our unhandled exceptions handled does the event NOT fire? You would expect to see a nice dialog box, but instead it just blows up.

The Fix

The fix was a mediocre band in the 80′s, oh sorry, I digress… <grin>. The fix is to replace the  AppDomain.CurrentDomain.UnhandledException code with other code that actually will do what we want. Here is how to implement the changes. If you want you can add these changes to the SCSF guidance that builds your projects, but I have not done that so I leave that to you. I may post that code in another article if I feel up to it.

Delete the nasty code

Remove the following from ShellApplication.cs in the RunInReleaseMode():

AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AppDomainUnhandledException);

Also, remove the try catch block in the RunInReleaseMode() method. (I show it here commented, but you should remove the commented lines).

//try
//{
new ShellApplication().Run();
//}
//catch (Exception ex)
//{
//HandleException(ex);
//}

Add the Fixed Code

Instead add in it’s place in RunInReleaseMode():

Application.ThreadException +=
new ThreadExceptionEventHandler(AppDomainUnhandledException);

Then you need to make one more change. Make the following changes to AppDomainUnhandledException():

private static void AppDomainUnhandledException(object sender, ThreadExceptionEventArgs e)
{
HandleException(e.Exception);
}

Now if you run the application in Release mode, you will see that you get the results you expect. A nice dialog box. This took me a long time to figure out, so I hope it helps everyone on the planet. Ok, not that many people, but congrats for finding this on my remote little blog.

-Jeff

Author: Jeff Noble

I was so excited that the P&P team released Enterprise Library 3.0. I first want to congratulate them on a fine product. Nice Job! Ok, so I installed the 3.0, Enterprise Library 3 and then the new Guidance Automation Extensions (which had errors, see this post if you get them) and the New Guidance Automation Toolkit both from May 2007. Then I installed the new Smart Client Software Factory. AWSOME!

I opened my CAB project and BOOM! 44 errors to fix. It took a LOT of time to diagnose what the problem is, but I will skip telling you how great of a programmer I am and how well I can diagnose a problem (ok, maybe not).

Missed Version Tick OOPS

The Object Builder has been moved into it’s own project space on Codeplex. You can find it here (but don’t find it there now): http://www.Codeplex.com/ObjectBuilder. If you were to d/l the project and build it, it builds version 1.0.51206.0

CAB has not been updated to a new Production release at this time and so it was built with an older version of the Microsoft.Practices.ObjectBuilder.dll. CAB was built with 1.0.51205.0. I assumed that I could just rebuild the CAB solution with a reference to the latest ObjectBuilder and I would be fine. THAT DOES NOT WORK AS EXPLAINED BELOW.

Remember in the title of this article I also included Enterprise Library. Like the SCSF, and new Guidance extensions and toolkit, they are all compiled against the 1.0.5.2106.0 ObjectBuilder.

Here is the problem. Somewhere along the line, the Microsoft.Practices.ObjectBuilder.dll was changed and the version was not ticked to the next minor. Here is a picture of the Microsoft.Practices.ObjectBuilder.dll as it sits in explorer after being built from the Codeplex download from the ObjectBuilder project space:

 objectbuilder1.png

Here is an image of the SAME dll as it sits in the Enterprise Library 3.0 bin folder, see if you can see the difference:
 objectbuilder2.png

In the statusbar (footer) of the explorer window, you can see that both Microsoft.Practices.ObjectBuilder.dll files are the SAME version, but the size of the files in the properties window is quite DIFFERENT. O-O-P-S!

Fortunately the fix is quite easy. The one in the Enterprise Library 3.0′s bin folder is the correct file. I opened the CAB project and removed the ObjectBuilder project from the CAB Solution, and referenced instead the Microsoft.Practices.ObjectBuilder.dll in the Enterprise Library folder.

Ok, CAB Builds, But My Project Is Still Broken

First, make sure you remove ALL of the references to CAB and replace them with the new one we just built. Then remove any ObjectBuilder References and use the ones from the Enterprise Library 3.0. You can also replace the Enterprise Library references while you are at it.

The next thing to do is to change your app.config to reflect the changes to your Enterprise Library Data, Logging and Exception Handling.

Normally you just change the lines which name the versions in your app.config (this file may be in the Constants folder in your shell project if you used the Guidance package).

<section name=”loggingConfiguration” type=”Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null” />

In our case, the Enterprise Library is now strong named so we need to change the PublicKeyToken to the actual strong name key. I changed the above line to the following:

<section name=”loggingConfiguration” type=”Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a” />

You will need to find EVERY mention of ANY type from the Enterprise Library and change these two values. They all use the same PublicKeyToken and are all version 3.0.0.0, so you can just blanket change them. Just make sure what you change IS part of the Enterprise Library. It is possible that you have other referenced dll’s in your app.config.

Your project with the new (fixed) CAB and the latest Guidance Packages and Toolkits installed, using the correct Object Builder are all set. You should be able to build your project once again all upgraded.

Painless! – NOT <grin>

Follow

Get every new post delivered to your Inbox.