Author Topic: AutoCAD.NET | Handling *Exceptions  (Read 21610 times)

0 Members and 1 Guest are viewing this topic.

BlackBox

  • King Gator
  • Posts: 3770
AutoCAD.NET | Handling *Exceptions
« on: April 16, 2012, 12:33:02 PM »
I'm trying to ensure that I am employing a sort of best practices with regard to handling *Exceptions for CommandMethods, and LispFunctions alike.

One recent example came up when I was coding a snippet that incorporates System.IO.Directory.GetParent() Method.

Rather than using If statements to test for valid criteria, I attempted to Catch ArgumentNullException, and ArgumentException, in addition to my normal Autodesk.AutoCAD.Runtime.Exception, yet each instance of my intentionally providing an argument that I thought would trigger one of these GetParent() Method Exceptions resulted in a Fatal Error, rather than hitting the applicable Catch statement.

Any suggestions, or advise would be most helpful.


Pseudo (non-production) code:

Code - C#: [Select]
  1.             try
  2.             {
  3.                 if (args == null)
  4.                 {
  5.                     ed.WriteMessage("\n; error: too few arguments ");
  6.                     return null;
  7.                 }
  8.  
  9.                 Array myArgs = args.AsArray;
  10.                 int i = myArgs.Length;
  11.  
  12.                 if (i > 1)
  13.                 {
  14.                     ed.WriteMessage("\n; error: too many arguments ");
  15.                     return null;
  16.                 }
  17.  
  18.                 if (myArgs(0).TypeCode != LispDataType.Text)
  19.                 {
  20.                     return null;
  21.                 }
  22.  
  23.                 string filePath = ((TypedValue)myArgs.GetValue(0)).Value;
  24.                 DirectoryInfo pathInfo = Directory.GetParent(filePath);
  25.  
  26.                 if (pathInfo.Exists & Directory.Exists(filePath))
  27.                 {
  28.                     return pathInfo.FullName;
  29.                 }
  30.  
  31.             }
  32.             catch (ArgumentNullException ex)
  33.             {
  34.                 ed.WriteMessage("\n; error: " + ex.Message + "\n ");
  35.                 return null;
  36.  
  37.             }
  38.             catch (ArgumentException ex)
  39.             {
  40.                 ed.WriteMessage("\n; error: " + ex.Message + "\n ");
  41.                 return null;
  42.  
  43.             }
  44.             catch (Autodesk.AutoCAD.Runtime.Exception ex)
  45.             {
  46.                 ed.WriteMessage("\n; error: " + ex.Message + "\n ");
  47.                 return null;
  48.  
  49.             }
  50.  
"How we think determines what we do, and what we do determines what we get."

huiz

  • Swamp Rat
  • Posts: 917
  • Certified Prof C3D
Re: AutoCAD.NET | Handling *Exceptions
« Reply #1 on: April 16, 2012, 01:15:20 PM »
The only way to escape from a fatal error is to catch the error as a system.exception. While debugging you can probably see what kind of exception it is.
The conclusion is justified that the initialization of the development of critical subsystem optimizes the probability of success to the development of the technical behavior over a given period.

BlackBox

  • King Gator
  • Posts: 3770
Re: AutoCAD.NET | Handling *Exceptions
« Reply #2 on: April 16, 2012, 01:21:28 PM »
Thanks for the response, Huiz.

Perhaps I am not understanding how the Method specific Exceptions work then... This is the first time I am attempting to incorporate them. I usually just use If statements.

If the GetParent() Method has an ArgumentNullException, and I supply a Null argument to the Method, how/why does this trigger a System.Exception, rather than ArgumentNullException  :? ?

Is there anything wrong with the order (top to bottom) of the Exceptions I am attempting to Catch? I know ArgumentNullException needs to be placed above ArgumentException, for instance.
"How we think determines what we do, and what we do determines what we get."

exmachina

  • Guest
Re: AutoCAD.NET | Handling *Exceptions
« Reply #3 on: April 16, 2012, 01:39:34 PM »
IF you only need to display a message, just use System.Excepcion

Code - C#: [Select]
  1. string path = null;
  2. try {
  3.     Directory.GetParent(path);
  4. } catch (System.Exception ex) {
  5.   MessageBox.Show(ex.Message);
  6. }

If you need to manipulate some specific exceptions you can use something like this (use System.Exception in the last "catch" or just an empty catch block)

Code - C#: [Select]
  1. try {
  2.     Directory.GetParent(path);
  3. } catch (DirectoryNotFoundException ex1) {
  4.     //anything
  5. } catch (ArgumentException ex2) {
  6.     //anything
  7. } catch (System.Exception ex) {
  8.   MessageBox.Show("unhandled exception: " +ex.Message);
  9. }

From MSDN:
Quote
"When an exception occurs in a try block, the system searches the associated catch blocks in the order they appear in application code, until it locates a catch block that handles the exception. A catch block handles an exception of type T if the type filter of the catch block specifies T or any type that T derives from. The system stops searching after it finds the first catch block that handles the exception. For this reason, in application code, a catch block that handles a type must be specified before a catch block that handles its base types, as demonstrated in the example that follows this section. A catch block that handles System.Exception is specified last."

http://msdn.microsoft.com/en-us/library/system.exception.aspx
« Last Edit: April 16, 2012, 02:05:31 PM by exmachina »

Jeff H

  • Needs a day job
  • Posts: 6150
Re: AutoCAD.NET | Handling *Exceptions
« Reply #4 on: April 16, 2012, 09:26:08 PM »
I'm trying to ensure that I am employing a sort of best practices with regard to handling *Exceptions for CommandMethods, and LispFunctions alike.

One recent example came up when I was coding a snippet that incorporates System.IO.Directory.GetParent() Method.

Rather than using If statements to test for valid criteria, I attempted to Catch ArgumentNullException, and ArgumentException, in addition to my normal Autodesk.AutoCAD.Runtime.Exception, yet each instance of my intentionally providing an argument that I thought would trigger one of these GetParent() Method Exceptions resulted in a Fatal Error, rather than hitting the applicable Catch statement.

Any suggestions, or advise would be most helpful.


Pseudo (non-production) code:

Code - C#: [Select]
  1.             try
  2.             {
  3.                 if (args == null)
  4.                 {
  5.                     ed.WriteMessage("\n; error: too few arguments ");
  6.                     return null;
  7.                 }
  8.  
  9.                 Array myArgs = args.AsArray;
  10.                 int i = myArgs.Length;
  11.  
  12.                 if (i > 1)
  13.                 {
  14.                     ed.WriteMessage("\n; error: too many arguments ");
  15.                     return null;
  16.                 }
  17.  
  18.                 if (myArgs(0).TypeCode != LispDataType.Text)
  19.                 {
  20.                     return null;
  21.                 }
  22.  
  23.                 string filePath = ((TypedValue)myArgs.GetValue(0)).Value;
  24.                 DirectoryInfo pathInfo = Directory.GetParent(filePath);
  25.  
  26.                 if (pathInfo.Exists & Directory.Exists(filePath))
  27.                 {
  28.                     return pathInfo.FullName;
  29.                 }
  30.  
  31.             }
  32.             catch (ArgumentNullException ex)
  33.             {
  34.                 ed.WriteMessage("\n; error: " + ex.Message + "\n ");
  35.                 return null;
  36.  
  37.             }
  38.             catch (ArgumentException ex)
  39.             {
  40.                 ed.WriteMessage("\n; error: " + ex.Message + "\n ");
  41.                 return null;
  42.  
  43.             }
  44.             catch (Autodesk.AutoCAD.Runtime.Exception ex)
  45.             {
  46.                 ed.WriteMessage("\n; error: " + ex.Message + "\n ");
  47.                 return null;
  48.  
  49.             }
  50.  

It does not it is null or can't be null until it bubbles back up to calling code.
 
             
Code - C#: [Select]
  1.   if (args == null)
  2.                 {
  3.                     throw new ArgumentNullException();
  4.                 }

BlackBox

  • King Gator
  • Posts: 3770
Re: AutoCAD.NET | Handling *Exceptions
« Reply #5 on: April 16, 2012, 09:44:11 PM »
I didn't realize that I needed to Throw the applicable Exception; I thought that is one of the inherent benefits of using Try... If I must still plan to Throw a particular Exception, the what benefit does Try provide?

** Edit - clearly I have more reading to do on the matter. I'm sure it would help if I went through one of the tutorials too. LoL
« Last Edit: April 16, 2012, 09:55:46 PM by RenderMan »
"How we think determines what we do, and what we do determines what we get."

Jeff H

  • Needs a day job
  • Posts: 6150
Re: AutoCAD.NET | Handling *Exceptions
« Reply #6 on: April 17, 2012, 01:11:16 AM »
Maybe not the best way there but from seeing your small portion of code it is not a good a idea to return null.
 
When it returns null you have no idea the reason why.
The code checks if it is null and if so it returns null and the catch block falls out of scope.

TheMaster

  • Guest
Re: AutoCAD.NET | Handling *Exceptions
« Reply #7 on: April 17, 2012, 04:22:47 PM »
I didn't realize that I needed to Throw the applicable Exception; I thought that is one of the inherent benefits of using Try... If I must still plan to Throw a particular Exception, the what benefit does Try provide?

** Edit - clearly I have more reading to do on the matter. I'm sure it would help if I went through one of the tutorials too. LoL

You use Try when there is a chance that the code that you place in
the Try block will cause an exception that you want to catch. If you
don't catch the exception, it should be caught by AutoCAD's runtime
but perhaps there's something wrong there.

The confusion about using Throw is that you are writing a method
that is called from LISP, so if the arguments passed from the calling
LISP code are wrong, then you can throw an exception, and the
AutoCAD runtime will catch it, and translate it to a LISP error along
with the error message.

Your mistake in that code, is that you are checking arguments passed
from the calling LISP code, and if they're not what you expect, you are
showing a message on the console and returning null, rather than
throwing an exception that triggers a LISP error, which is what should
happen if the arguments are not correct.

That has nothing to do with using Try/Catch to catch an exception that
might be raised by the .NET APIs that you call.

You really don't need to catch argument-related exceptions thrown
by the .NET code you call, you should just let then bubble up and
stop your code. But if there's a fatal error happening, then you only
need to catch System.Exception, and see what the message is. You
can also re-throw the exception back to the calling LISP code as well.

Catching System.Exception is the 'catch-all' case that will catch any
exception, since all exceptions are derived from System.Exception.
E.g., catch( System.Exception ) is like using vl-catch-all-apply, as they
both catch any exception/error thrown.

BlackBox

  • King Gator
  • Posts: 3770
Re: AutoCAD.NET | Handling *Exceptions
« Reply #8 on: April 17, 2012, 04:30:43 PM »
Very informative, Tony... Thank you.
"How we think determines what we do, and what we do determines what we get."

dgorsman

  • Water Moccasin
  • Posts: 2437
Re: AutoCAD.NET | Handling *Exceptions
« Reply #9 on: April 17, 2012, 04:45:47 PM »
There's a few instances I can think of where errors need to be caught, mostly dealing with making sure external resources are properly closed e.g. closing database connections and releasing lock files.
If you are going to fly by the seat of your pants, expect friction burns.

try {GreatPower;}
   catch (notResponsible)
      {NextTime(PlanAhead);}
   finally
      {MasterBasics;}

exmachina

  • Guest
Re: AutoCAD.NET | Handling *Exceptions
« Reply #10 on: April 17, 2012, 05:36:24 PM »
There's a few instances I can think of where errors need to be caught, mostly dealing with making sure external resources are properly closed e.g. closing database connections and releasing lock files.

using Statement ????
http://msdn.microsoft.com/en-us/library/yh598w02.aspx

Any developer should analyze the workflow of your own code and add "catch" blocks  only when needed. Again: here is very well explained
http://msdn.microsoft.com/en-us/library/system.exception.aspx

If you are unsure then use a "clean output"
Code - C#: [Select]
  1. try {
  2.     //anything
  3. } catch {}

It seems that I am the only one who knows reads English ( @ MSDN) :whistle:

TheMaster

  • Guest
Re: AutoCAD.NET | Handling *Exceptions
« Reply #11 on: April 17, 2012, 06:06:30 PM »
There's a few instances I can think of where errors need to be caught, mostly dealing with making sure external resources are properly closed e.g. closing database connections and releasing lock files.

Actually, you don't catch exceptions only to do termination
handling, you use Try/Finally (without Catch), or the Using
construct.
« Last Edit: April 17, 2012, 06:11:01 PM by TheMaster »

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8690
  • AKA Daniel
Re: AutoCAD.NET | Handling *Exceptions
« Reply #12 on: April 17, 2012, 07:35:07 PM »
If you are unsure then use a "clean output"
Code - C#: [Select]
  1. try {
  2.     //anything
  3. } catch {}

This is one snippet of code I truly dislike. I know it's sometimes hard to avoid but it should be used with caution

exmachina

  • Guest
Re: AutoCAD.NET | Handling *Exceptions
« Reply #13 on: April 17, 2012, 08:04:51 PM »
Obviously this must be used in the right environment and with some caution
I use it for "LispFunctions"
Code - C#: [Select]
  1. try {
  2.   //anything
  3. } catch {}
  4.  return null

But this code snippet is present in many more "professional codes" ("commercial" dll's)  than any one could imagine

Jeff H

  • Needs a day job
  • Posts: 6150
Re: AutoCAD.NET | Handling *Exceptions
« Reply #14 on: April 17, 2012, 08:07:46 PM »
There's a few instances I can think of where errors need to be caught, mostly dealing with making sure external resources are properly closed e.g. closing database connections and releasing lock files.

using Statement :? ?
http://msdn.microsoft.com/en-us/library/yh598w02.aspx

Any developer should analyze the workflow of your own code and add "catch" blocks  only when needed. Again: here is very well explained
http://msdn.microsoft.com/en-us/library/system.exception.aspx

If you are unsure then use a "clean output"
Code - C#: [Select]
  1. try {
  2.     //anything
  3. } catch {}

It seems that I am the only one who knows reads English ( @ MSDN) :whistle:

Wow thanks for those great links!!
 
I never have heard of MSDN. I wish I had known about that before.
Oh crap its in English like you mentioned. I can only talk and write in English, but read in Kazakhstaneese.
Oh well.