Exception Handling terminates application

Topics: CAB & Smart Client Software Factory
Apr 25, 2007 at 8:31 PM
How do I get the Traditional Windows Forms ThreadException handling the exceptions that come from EventBroker subscriptions?

It seems like they are not actually on the UI thread thus are being handled by AppDomain.Unhandled exception handler.... is there a way to make my app not terminate when an unhandled exception occurs like in a normal winforms app?
Apr 26, 2007 at 12:32 AM
Edited Apr 26, 2007 at 12:10 PM
Yeah, this is the bane of my life at the moment, the dreaded One or more exceptions occurred while firing the topic 'topic://Foo/SomeImportantEvent'

It gives me an almost useless strack trace, I have no idea what went wrong and it could take hours to figure out. It's also very hard to cover in a unit test. What's going on with the exception handling during Event Subscriptions... ?

I'm just looking into this myself, no doubt I will have to get the debugger out and debug CAB code. But what I don't like is that I need to debug CAB code every time this happens. But I suppose that's the way it has to be....

Addendum... I found the problem, I'd stupidly done this (see below). But you have no idea from the stack trace - you just have to run around your code trying to find what might be wrong - CABBY wise.

[CreateNew]
public IProgressManager ProgressManager
{
    set { _progressMgr = value; }
}

Can you spot the likely problem?
Apr 26, 2007 at 2:54 PM
Yep. You can't instantiate an interface. CreateNew doesn't know what to do there.

I feel your pain on the EventBroker exceptions. There's no easy way to get around it that we've found.

What we do (to eliminate the long hours trying to find the source of the error) is go directly to the EventSubscription that the exception is complaining about, wrap the contents of the method in a try/catch, and then run it (either the unit test causing the failure, or the app) to get the real line number and exception. It takes a couple seconds to wrap that line of code and recompile (and yes, that's annoying) but it beats banging your head against the wall.



May 29, 2007 at 1:27 AM

choenes wrote:
How do I get the Traditional Windows Forms ThreadException handling the exceptions that come from EventBroker subscriptions?

It seems like they are not actually on the UI thread thus are being handled by AppDomain.Unhandled exception handler.... is there a way to make my app not terminate when an unhandled exception occurs like in a normal winforms app?


chonenes,
How did you go around this problem? I'm running into the same issue, and have not been able to find a solution.
May 29, 2007 at 8:52 AM
Edited May 29, 2007 at 8:53 AM
I'm doing the following to ease on debugging.
Press ALT-CTRL-E to display the Exception dialog. (Or "Exceptions..." from the debug menu)
In the treeview there's a node "Common Language Runtime Exceptions", Click the "Thrown" checkbox for that node.
When you now start up the app, the debugger will break at every exception as they occur. You will get a few exceptions during loading the CAB, but just F5 over those.


May 29, 2007 at 1:19 PM
I guess, my question is not really related on how to see usefull exception information during debug time. My question is related to choenes original post.
Which is "How do you the Traditional Windows Forms ThreadException handling the exceptions that come from the EventBroker subscriptions".

There has to be a solution for this problem, but I have not been able to find it. I'm sure everyone that has an application written with CAB had to run into this problem at one time or another.

Here is a simple sample code to see what I mean:

Basically I have a View with a button. In the event handler of the button I fire a TestBug Event.

EventPublication(EventTopicNames.TestBug, PublicationScope.Global)
public event EventHandler<EventArgs> TestBug;

private void button1_Click(object sender, EventArgs e)
{
OnTestBug(e);
}

protected virtual void OnTestBug(EventArgs eventArgs)
{
if (TestBug != null)
{
TestBug(this, eventArgs);
}
}

Now, in my ModuleController, I have a subscription to the TestBug event with the ThreadOption of UserInterface. Like so:

EventSubscription(EventTopicNames.TestBug, ThreadOption.UserInterface)
public void OnTestBug(object sender, EventArgs eventArgs)
{

int x = 0;
int y = 3;
int z = y/x; //Division by zero exception will be thrown here.
}

After this code is executed and exception is thrown, I would expect the following code to handle the exception if I'm running in release mode:

private static void RunInReleaseMode()
{
try
{
new ShellApplication().Run();
}
catch (Exception ex)
{
HandleException(ex);
}
}

But that's not happening, I get an unhandled exception error. It almost looks like if the exception was in a different thread and the exception was not handled.
Is anyone else having this issue? The program runs fine if you run it debug mode, but it fails if you run it debug mode with no breakpoints.

Thank you in advance.
May 29, 2007 at 9:27 PM
I may be missing something.
Why not try the following:

private static void RunInReleaseMode()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AppDomainUnhandledException);
Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(ThreadException);
new ShellApplication().Run();
}

Note that you need to remove the try/catch wrapping Run() in order to receive unhandled exceptions.


static void ThreadException(object sender, System.Threading.ThreadExceptionEventArgs ex)
{
HandleException(ex.Exception)
}

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

private static void HandleException(Exception ex)
{
if (ex.Exception is EventTopicException){ // Cast to EventTopicException and loop over the Exceptions collection }
}
May 30, 2007 at 5:11 PM
Edited May 30, 2007 at 7:01 PM
Thanks for your reply. The UnhandledExceptionEventHandler does not work either, that's actually what I tried first because that's how the factory templates have it.

I finally fixed the issue by adding the following code, you can read more about it at:
http://savij.com/2007/05/30/catch-unhandled-exceptions-in-cab/

private static void RunInReleaseMode()
{
Application.ThreadException += new ThreadExceptionEventHandler(AppDomainUnhandledException);


new ShellApplication().Run();
}

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

Jun 8, 2007 at 5:19 AM
I found when you are using the Enterprise Exception Handling block you can configure an exception type in the <exceptionTypes/> element that uses a custom formatter (which gets generated when you first create a CAB using the SCSF) like this:

<add type="Microsoft.Practices.CompositeUI.EventBroker.EventTopicException, Microsoft.Practices.CompositeUI, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" postHandlingAction="NotifyRethrow" name="EventTopicException">
<exceptionHandlers>
<add logCategory="General" eventId="100" severity="Error" title="Enterprise Library Exception Handling" formatterType="YourProjectNamespace.EntLib.EventTopicExceptionFormatter, Infrastructure.Library" priority="0" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" name="Logging Handler" />
</exceptionHandlers>
</add>

This will format all EventTopicExceptions so that the inner Exceptions list is included. eg, in the EventLog if your logging is configured to use Events.

Glenn.

Jun 8, 2007 at 11:04 AM
Nice! Thanks.