Author Topic: Why cannot catch exception?  (Read 2374 times)

0 Members and 1 Guest are viewing this topic.

csharpbird

  • Newt
  • Posts: 64
Why cannot catch exception?
« on: November 12, 2011, 12:41:12 AM »
The following code cannot catch the exception raised by setting entity's color.
AutoCAD will crash!
Code: [Select]
        [CommandMethod("Test")]
        public static void Test()
        {
            Document doc=Application.DocumentManager.MdiActiveDocument;
            Database db=doc.Database;
            Editor ed=doc.Editor;
            ObjectId id=ed.GetEntity("Please select en entity").ObjectId;
            using (Transaction trans=db.TransactionManager.StartTransaction())
            {
                try
                {
                    Entity ent=(Entity)trans.GetObject(id, OpenMode.ForRead);
                    ent.ColorIndex = 1;
                    trans.Commit();
                }
                catch (Autodesk.AutoCAD.Runtime.Exception ex)
                {
                    trans.Abort();
                }               
            }
        }

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Re: Why cannot catch exception?
« Reply #1 on: November 12, 2011, 01:18:30 AM »
This isn't a problem with your code. It is a problem with the .NET library or the managed code AutoCAD uses. I worked with Microsoft for months on an issue where an error wasn't caught and it turned out to be a bug in the .NET 4.0 libraries. (It still has not been fixed).

To find the problem, I got the entire .NET 4.0 library source code and debugged through the .NET managed code until I found out where the .NET library was failing to elevate an error raised by unmanaged code. Unfortunately for me, there is still no solution, despite knowing exactly how to correct the bug, I cannot recompile the entire .NET core library and distribute it with an application.
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

LE3

  • Guest
Re: Why cannot catch exception?
« Reply #2 on: November 12, 2011, 12:31:22 PM »
You must use the ForWrite.

csharpbird

  • Newt
  • Posts: 64
Re: Why cannot catch exception?
« Reply #3 on: November 12, 2011, 12:39:39 PM »
You must use the ForWrite.
I know. But I want the try clause catch the exception.

LE3

  • Guest
Re: Why cannot catch exception?
« Reply #4 on: November 12, 2011, 01:43:58 PM »
You must use the ForWrite.
I know. But I want the try clause catch the exception.

AFAIK there is no way to capture the exception like that - Even the ARX route won't work too.

n.yuan

  • Bull Frog
  • Posts: 348
Re: Why cannot catch exception?
« Reply #5 on: November 13, 2011, 11:13:11 AM »
le said is true. It looks like starting a transaction in wrong mode is considered an exception that cannot be recovered. That is, if a programmer (only a programmer will start a transaction in wrong mode from code, isn't it?) starts a transaction in a mode, he/she should never use the transaction in other mode.

It is intereding to know that the catch... clause actually does catches the exception and the code in the catch...clause is executed (well, if the code is still executeable in the context of exception has happed). It is just that even the catch...clause cactches the exception, AutoCAD still buble up the exception to upper level and then even it is caught and handled again, it is still bubles up and eventually shut down AutoCAD. I made a bit change to the code by adding a try..catch.. to wrap up the using... block, so that there are 2 levels of try..cacth... inside and outside using...block, like this:

Code: [Select]
[CommandMethod("MyTran")]
        public static void TestTransaction()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            PromptEntityResult res = ed.GetEntity("\nPick entity:");
           
            if (res.Status != PromptStatus.OK) return;

            ObjectId id = res.ObjectId;

            try
            {
                using (Transaction trans = db.TransactionManager.StartTransaction())
                {
                    try
                    {
                        Entity ent = (Entity)trans.GetObject(id, OpenMode.ForRead);
                        ent.ColorIndex = 1;
                        trans.Commit();
                    }
                    catch
                    {
                        ed.WriteMessage("\nError!!!");
                    }
                }
            }
            catch (System.Exception ex)
            {
                ed.WriteMessage("\nError: " + ex.Message);
            }
        }

If stepping through the code, when ent.ColorIndex=1 is executed, one can see:
1. AutoCAD pops up "AutoCAD Error Aborting" message box with message" Internal Error.....eNotOpenForWrite"
2. AutoCAD then pops up Another message box to offer an option to save changes of current drawing. User can click either yes or no.
3. the catch...clause inside the using... block catches the exception, code inside the catch clause runs.
4. after the inner cacth...clause executed, the catch... clause outside using... block also catches the exception.
5. If there is another try...catch... oudside, the exception would be caught there again.
6. No matter how many try...catch... one wrap up the code, this exception keeps bubling up, even it is catch and handled by each catch...clause, and eventaully shut down AutoCAD.


LE3

  • Guest
Re: Why cannot catch exception?
« Reply #6 on: November 13, 2011, 11:50:18 AM »
^ +1

Wonder the code scenario csharpbird is expecting? or why a wrong code line has to be there?