August 08, 2008

Catching exceptions thrown from dialogs inside AutoCAD using .NET

How can I throw an exception from within a modal form on mine inside AutoCAD, and catch it in the calling command? I have tried try/catch, but nothing seems to work.

Here's my command definition:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.Runtime;

using System.Windows.Forms;

using MyApplication;

usingacApp =

Autodesk.AutoCAD.ApplicationServices.Application;

namespace CatchMeIfYouCan

{

publicclassCommands

{

[CommandMethod("CATCH")]

staticpublicvoid CatchDialogException()

{

try

{

MyForm form = newMyForm();

DialogResult res =

acApp.ShowModalDialog(form);

}

catch (System.Exception ex)

{

MessageBox.Show(

"Caught using catch: " +

ex.Message,

"Exception"

);

}

}

}

}

And here's the code that throws an exception from behind button inside my form:

using System;

using System.Windows.Forms;

namespace MyApplication

{

publicpartialclassMyForm : Form

{

public MyForm()

{

InitializeComponent();

}

privatevoid button1_Click(

object sender,

EventArgs e

)

{

thrownewException(

"Something bad happened."

);

}

}

}

The answer, once again, came from our AutoCAD Engineering team, in this case from one of our API Test Engineers based in Singapore...

I was able to catch the exception using the ThreadExceptionEventHandler event. Here is your modified command:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.Windows;

using System.Windows.Forms;

using System.Threading;

using MyApplication;

usingacApp =

Autodesk.AutoCAD.ApplicationServices.Application;

usingsysApp =

System.Windows.Forms.Application;

namespace CatchMeIfYouCan

{

publicclassCommands

{

[CommandMethod("CATCH")]

staticpublicvoid CatchDialogException()

{

try

{

sysApp.ThreadException +=

newThreadExceptionEventHandler(

delegate(

object o,

ThreadExceptionEventArgs args

)

{

MessageBox.Show(

"Caught using event: " +

args.Exception.Message,

"Exception"

);

}

);

MyForm form = newMyForm();

DialogResult res =

acApp.ShowModalDialog(form);

}

catch (System.Exception ex)

{

MessageBox.Show(

"Caught using catch: " +

ex.Message,

"Exception"

);

}

}

}

}

I gave this a try, myself, and saw that when we click the button on the dialog shown by the CATCH command, our event handler picks up the exception and displays it via a MessageBox:

One thing to note: when running this from the debugger, Visual Studio will break, telling us that there's an exception that has gone unhandled:

This can be ignored - and probably disabled inside Visual Studio - but it could be annoying, if you use this technique throughout your code. Perhaps someone who's implemented this approach - or another that works for them - can add a comment on how they handle this scenario?