Author Topic: Block Reference ?  (Read 7276 times)

0 Members and 1 Guest are viewing this topic.

jcoon

  • Newt
  • Posts: 157
Block Reference ?
« on: August 07, 2013, 08:04:27 AM »

Hi All,

Questions about block reference:
The test below is suppose to check for a block named "SURFACECUT" and if the block name is not found it is suppose to create the block. that works thanks to members here. second part of test is suppose to insert the block reference of the block named "SURFACECUT", which it does however after insertion I'm not able to select the block. that's the area I looking for some help on. block name if defined, then block is created and finally it is inserted. if I use the autocad insert command the block inserts correctly. why can't I list or select the block from this sample insertion.

Thanks
John

<CommandMethod("BlockNameCheckInsert")> _
    Public Sub BlockNameCheckInsert()
        Dim ed As Editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor()
        Dim db As Database = HostApplicationServices.WorkingDatabase
        Dim civilDoc As CivilDocument = CivilApplication.ActiveDocument
        Dim acaddoc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument

        Dim blockName1 As String
        blockName1 = "SURFACECUT"
        Dim blockName2 As String
        blockName2 = "SURFACECUT-WITHINTENFEET"
        Dim ObjId As ObjectId = Nothing
        Dim mytrans As Transaction = db.TransactionManager.StartTransaction
        Try
            Dim id As ObjectId = Nothing
            ' Open the Block table for read
            Dim BlockTable As BlockTable
            BlockTable = mytrans.GetObject(db.BlockTableId, OpenMode.ForRead)
            'blockName1 = "SURFACECUT"
            If Not BlockTable.Has(blockName1) Then
                Using BlockTableRecord As New BlockTableRecord
                    BlockTableRecord.Name = blockName1
                    ' Set the insertion point for the block
                    BlockTableRecord.Origin = New Point3d(0, 0, 0)
                    BlockTableRecord.Units = UnitsValue.Feet
                   
                    Dim InsertionPt = New Point3d(0, 0, 0)
                    ' create point and lines to create block = "SURFACECUT"
                    Dim pt0(2) As Double
                    pt0(0) = 0.0# : pt0(1) = -0.0 : pt0(2) = 0.0#
                    Dim pt1(2) As Double
                    pt1(0) = 0.0# : pt1(1) = -0.04 : pt1(2) = 0.0#
                    Dim pt2(2) As Double
                    pt2(0) = -0.06 : pt2(1) = -0.04 : pt2(2) = 0.0#
                    Dim pt3(2) As Double
                    pt3(0) = 0.06 : pt3(1) = -0.04 : pt3(2) = 0.0#
                    Dim pt4(2) As Double
                    pt4(0) = -0.0 : pt4(1) = 0.08 : pt4(2) = 0.0#

                    Dim Line As Line = New Line(New Point3d(pt2), New Point3d(pt3))
                    Line.Layer = "0"
                    BlockTableRecord.AppendEntity(Line)
                    Line = New Line(New Point3d(pt3), New Point3d(pt4))
                    BlockTableRecord.AppendEntity(Line)
                    Line = New Line(New Point3d(pt4), New Point3d(pt2))
                    BlockTableRecord.AppendEntity(Line)
                    BlockTable.UpgradeOpen()
                    BlockTable.Add(BlockTableRecord)
                    mytrans.AddNewlyCreatedDBObject(BlockTableRecord, True)

                    Dim BlockTableModelSpace As BlockTableRecord = BlockTable(BlockTableRecord.ModelSpace).GetObject(OpenMode.ForWrite)
                    Dim Blockref As New BlockReference(InsertionPt, BlockTableRecord.ObjectId)
                    BlockTableModelSpace.AppendEntity(Blockref)
                    ed.WriteMessage(vbCrLf + vbLf & "block created:" & blockName1)

                End Using
            End If
            ' Save the new object to the database
            mytrans.Commit()
            ' Dispose of the transaction
        Catch ex As Exception
        End Try
    End Sub
End Class

Micaletti

  • Guest
Re: Block Reference ?
« Reply #1 on: August 07, 2013, 09:16:05 AM »
All of your code is inside this If statement:

If Not BlockTable.Has(blockName1) Then
'Do Stuff
End If

You need to move the code that actually creates the reference below the if statement, because the second time it is ran, the if statement will be false. You also need to add mytrans.AddNewlyCreatedDBObject(Blockref, True).

Forgetting to add the AddNewlyCreatedDBObject is a common mistake. No problem, you're learning the API. Understanding If logic is a big deal however, and you're not yet. You have to learn to walk before you can run.
« Last Edit: August 07, 2013, 09:44:21 AM by Micaletti »

n.yuan

  • Bull Frog
  • Posts: 348
Re: Block Reference ?
« Reply #2 on: August 07, 2013, 09:57:02 AM »
Besides what the comment in the other reply, you also need to remove the Using at the point where new BlockTableRecord is created: the Using.. block ends before Transaction is committed, which will dispose the newly created BlockTablerecord. This could be the reason that your block reference is not selectable, because it is created based on a disposed block definition. In fact, after running your code, the database might already be corrupted.

You do not create a new DBObject in Using...block, if you intend to add it into database within a transaction.

Also, creating a variable with the name exactly the same as a class/type name (BlockTableRecord As New BlockTableRecord) is very bad practice, which makes the code very difficult to read and very confusing.

jcoon

  • Newt
  • Posts: 157
Re: Block Reference ?
« Reply #3 on: August 07, 2013, 10:47:21 AM »
Thanks, I'll make changes during lunch and see if that makes it clearer for me.

I thought the idea would be that if the block is not in the dwg then build the new block and if the block is already in the dwg then just go to the next block to check for.
under this test, if I ran it again it shouldn't create the newly built blocks. wouldn't that work flow work under this type of test? 

 If Not BlockTable.Has(blockName1) Then
'Do Stuff
End If

You need to move the code that actually creates the reference below the if statement, because the second time it is ran, the if statement will be false. You also need to add mytrans.AddNewlyCreatedDBObject(Blockref, True).

Micaletti

  • Guest
Re: Block Reference ?
« Reply #4 on: August 07, 2013, 11:14:10 AM »
It's not really clear what you are trying to do. If you are trying to write code that makes sure certain block definitions exist then you don't need to insert a block reference, you only need to create the definition. It will then be available for the user to insert.

Right now blockName2 is declared but not used, and the code is overly complex.

1) You don't need "ed", "civildoc" or "acaddoc".
2) I would avoid "Using" and "UpgradeOpen" until you start to wrap your head around transactions.

I am assuming your intention is to create two block definitions:

Code: [Select]
Public Sub CreateBlockDefinitions()
        Dim DB as Database = Application.DocumentManager.MdiActiveDocument.Database
        Dim T As Transaction = DB.TransactionManager.StartTransaction
        Try
            Dim BT As BlockTable = T.GetObject(DB.BlockTableId, OpenMode.ForWrite)
            Dim BlockDefName1 = "SomeBlock1"
            Dim BlockDefName2 = "SomeBlock2"
            If Not BT.Has(BlockDefName1) Then
                Dim BTR As New BlockTableRecord
                BTR.Name = BlockDefName1
                'Append entities to create the block def here.
                BT.Add(BTR)
                T.AddNewlyCreatedDBObject(BTR, True)
            End If
            If Not BT.Has(BlockDefName2) Then
                Dim BTR As New BlockTableRecord
                BTR.Name = BlockDefName2
                'Append entities to create the block def here.
                BT.Add(BTR)
                T.AddNewlyCreatedDBObject(BTR, True)
            End If
            T.Commit()
        Catch ex As System.Exception
            MsgBox(ex.ToString)
        Finally
            T.Dispose()
        End Try
    End Sub
« Last Edit: August 07, 2013, 12:04:26 PM by Micaletti »

jcoon

  • Newt
  • Posts: 157
Re: Block Reference ?
« Reply #5 on: August 07, 2013, 11:51:49 AM »
Your right it is confusing.  Yes, the definition is all I need to create the block but I have not tried the blockRef insert for a block yet so Included it so I could see how that works so that I could include it in a function later. I'm converting VBA application that I 've used for years. In VBA it was pretty simple but dot net is another animal with all the objectID and the like to wrap your head around. I got help from Jeff M a while back on the first part of this application which was selecting civil points and a surface.

n.yuan, I did change the variable names.  you were right it is a lot easier to read thanks. it appears to work correctly..........for now!

thanks for the help
John


  <CommandMethod("BlockNameCheckInsert")> _
    Public Sub BlockNameCheckInsert()
        Dim ed As Editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor()
        Dim db As Database = HostApplicationServices.WorkingDatabase
        Dim civilDoc As CivilDocument = CivilApplication.ActiveDocument
        Dim acaddoc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument

        Dim blockName1 As String
        blockName1 = "SURFACECUT"
        Dim ObjId As ObjectId = Nothing

        Dim mytrans As Transaction = db.TransactionManager.StartTransaction
        Try

            Dim id As ObjectId = Nothing
            ' Open the Block table for read
            Dim BT As BlockTable
            BT = mytrans.GetObject(db.BlockTableId, OpenMode.ForRead)
            'blockName1 = "SURFACECUT"
            If Not BT.Has(blockName1) Then
                Dim BTR As New BlockTableRecord
                BTR.Name = blockName1
                ' Set the insertion point for the block
                BTR.Origin = New Point3d(0, 0, 0)
                BTR.Units = UnitsValue.Feet
                ' create point and lines to create block = "SURFACECUT"
                Dim InsertionPt = New Point3d(0, 0, 0)

                Dim pt0(2) As Double
                pt0(0) = 0.0# : pt0(1) = -0.0 : pt0(2) = 0.0#
                Dim pt1(2) As Double
                pt1(0) = 0.0# : pt1(1) = -0.04 : pt1(2) = 0.0#
                Dim pt2(2) As Double
                pt2(0) = -0.06 : pt2(1) = -0.04 : pt2(2) = 0.0#
                Dim pt3(2) As Double
                pt3(0) = 0.06 : pt3(1) = -0.04 : pt3(2) = 0.0#
                Dim pt4(2) As Double
                pt4(0) = -0.0 : pt4(1) = 0.08 : pt4(2) = 0.0#

                Dim Line As Line = New Line(New Point3d(pt2), New Point3d(pt3))
                Line.Layer = "0"
                BTR.AppendEntity(Line)
                Line = New Line(New Point3d(pt3), New Point3d(pt4))
                BTR.AppendEntity(Line)
                Line = New Line(New Point3d(pt4), New Point3d(pt2))
                BTR.AppendEntity(Line)
                BT.UpgradeOpen()
                BT.Add(BTR)
                Dim BTMSpace As BlockTableRecord = BT(BlockTableRecord.ModelSpace).GetObject(OpenMode.ForWrite)
                Dim Blockref As New BlockReference(InsertionPt, BTR.ObjectId)
                BTMSpace.AppendEntity(Blockref)
                ed.WriteMessage(vbCrLf + vbLf & "block created:" & blockName1)
                mytrans.AddNewlyCreatedDBObject(Blockref, True)

            End If

Micaletti

  • Guest
Re: Block Reference ?
« Reply #6 on: August 07, 2013, 11:55:53 AM »
I've made some edits to my above post. Paste that in, it should be much easier to follow.

jcoon

  • Newt
  • Posts: 157
Re: Block Reference ?
« Reply #7 on: August 07, 2013, 01:06:22 PM »
Micaletti,

I was successful switching out my sample with yours.
Thanks so much for your help, I'm sure I'll be back as I work on the other parts of this.

Thanks
John


MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: Block Reference ?
« Reply #8 on: August 07, 2013, 01:30:47 PM »
2) I would avoid "Using" and "UpgradeOpen" until you start to wrap your head around transactions.


The Using statement and your Try/Catch/Finally block are identical in your example.  The difference would be if an exception occurred in this block of code but you'll never see it because any exception that would happen within your example would cause AutoCAD to fail and never return to your program. The Using statement has become the preferred method in .NET and AutoCAD and is the way you'll see in most AutoCAD examples from Autodesk and on The Swamp.
Revit 2019, AMEP 2019 64bit Win 10

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Block Reference ?
« Reply #9 on: August 07, 2013, 01:56:25 PM »
Sometimes it helps to break it down to task and responsibilities, and class or functions should focus on one thing and do that thing well.
 
You are
1) Checking if BlockTableRecord exists
2) Creating a BlockTableRecord if it does not
3) Inserting a BlockReference from BlockTableRecord
 
You can break this down to make it more reusable, easier to read, debug, etc..  and many different ways to approach it
 
To start off with first round of a simple refactor and this will NOT make it robust, re-usable, or close to deployable to many users but start breaking down in different parts and start in better direction.
 
Ask yourself
Should a function to insert a BlockReference need to worry about creating a BlockTableRecord?
Should it need to care if it was just created or been there for days, years, etc...
 
One hint would be the function name and to be more correct would be CheckBlockNameCreateIfNotInDrawingInsert. So maybe first step would be getting functions name to contain only one verb.
 
Its up to you to decide which responsibilities and contracts to implement like
1)Should the function to insert be responsible for checking if it exists and if not exist then call function to create it.
or
2)The Insertion function should Insert.
 
Can you see how first options now requires insertion function responsible for still creating BlockTableRecords and if you need more than one then it needs to know how to do that.
 
The insertion function signature could have a parameter for the ObjectId of the BlockTableRecord, which for a BlockTableRecord to have a ObjectId it must be in the drawing(up to you for checking if it is valid, is from correct database, etc...)
 
 
 
Depending on requirements there are many different approaches.
 
 
So just making up a quick example and better ways to do it but to get started in better direction
For a short easy example say you have folders containing drawings for blocks and folder is in SearchPaths
 
3 Functions
 
 
InsertBlockReference(Name)
 If not In drawing
  CreateBlock(Name)
 InsertBlock(Id)
 
CreateBlock(name)
 FindFile(Name)
 InsertBlock("Path from Filename")
 
InsertBlock(Id)
 ......
 ......
 
As far as inserting blocks and you are going to get user input and provide visual feedback then I would script insert command.
Unless you want to deal with scaling, scales uniformly, is it annotative, alignment parameters, attributes, attributes with fields, Ucs, etc...
 
Again just quick example to help maybe push in right direction
 
 

Micaletti

  • Guest
Re: Block Reference ?
« Reply #10 on: August 07, 2013, 03:44:32 PM »
The Using statement and your Try/Catch/Finally block are identical in your example.

He was using both try/catch and using, which is redundant and confusing.

The difference would be if an exception occurred in this block of code but you'll never see it because any exception that would happen within your example would cause AutoCAD to fail and never return to your program.

Huh?? Can you elaborate on this? It catches the exception, gives you a msgbox, and disposes the transaction. I've seen it happen. We've all seen that. What do you mean by "would cause AutoCAD to fail and never return to your program"? Are you talking about stuff like eNotOpenForWrite? You'll crash AutoCAD either way.
« Last Edit: August 07, 2013, 04:58:24 PM by Micaletti »

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Block Reference ?
« Reply #11 on: August 07, 2013, 04:12:23 PM »
MSDN is very useful
 
Quote

The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler. The code example earlier expands to the following code at compile time (note the extra curly braces to create the limited scope for the object):
http://msdn.microsoft.com/en-us/library/yh598w02.aspx

Micaletti

  • Guest
Re: Block Reference ?
« Reply #12 on: August 07, 2013, 04:13:57 PM »
MSDN is very useful
 
Quote

The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler. The code example earlier expands to the following code at compile time (note the extra curly braces to create the limited scope for the object):
http://msdn.microsoft.com/en-us/library/yh598w02.aspx

Thanks Jeff but we've already established that. That wasn't what I was asking. In fact it says using is translated to try catch finally by the compiler...

Let me clarify. He said Try/Catch/Finally:

Quote
"would cause AutoCAD to fail and never return to your program"

Which isn't true at all, he's confused. If you crash ACAD with Try/Catch/Finally, you're going to crash it with Using too. I'm sorry if I appear to be the abrasive "new guy" but you can't be like "oh well we use using around here so that's what you should use", and then proceed to spout misinformation, further confusing a person I am trying to help.

Now then, if you guys would like to explain when and why it is better without any hearsay or bias, I'd like to hear it, however MSDN just told you they are basically the same thing!

The cool thing about Try/Catch/Finally is you can do a lot more than dispose one object. You can actually provide some feedback as to what went wrong, AND you can add code to handle the exception gracefully.
« Last Edit: August 07, 2013, 06:56:27 PM by Micaletti »

dgorsman

  • Water Moccasin
  • Posts: 2437
Re: Block Reference ?
« Reply #13 on: August 07, 2013, 05:26:03 PM »
pssst jcoon: see how the others code examples are formatted?  Easier to read, isn't it?  Have a look at the "Insert code" button in the Post reply section.   :angel:
If you are going to fly by the seat of your pants, expect friction burns.

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

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Block Reference ?
« Reply #14 on: August 07, 2013, 06:51:23 PM »
Sorry to disappoint you Micaletti but you need try harder and put forth more effort if you want to be considered abrasive.
I am kidding.
 
Nothing to do with the validity of what anyone posted in this thread, but when it comes to anything I post if anyone thinks what I post is misleading or wrong then point it out and make it known. I want to know when I am wrong.
If someone has problem with being pointed out they are incorrect then their answers an advice are effected by motivation that they care what people think.
I guess that is easy for me to say since I am never wrong.
 
 
A Finally block is used to guarantee a block of code will execute.
One reason to use try/finally is to make sure you clean up resources 
"Using" uses try/finally and also cast the object to IDisposable in finally block, so in a way to me is a easy way to see that your using Try/Finally to clean-up resources(to be correct call Dispose on an object that implement IDisposable) .
 
So I prefer using because it makes it easier for me to se that I am dealing with an object that implements IDisposable.
And helps me make sure I correctly keep it scoped and not able to be used once disposed, and  just looks cleaner.
 
One thing to consider with example that makes it different from using is the addition of Catch block.
When catching exceptions in a way you are saying you expected this might happen, and you understand why it happened, and you know how to deal with it.
 
 
I can not think of a specific example for AutoCAD but with adding Catch block especially with System.Exception should re-throw it and even though it might still crash and burn the application could have a exception handling for fixing corrupted objects or creating recovery file that will never happened since the exception was swallowed up before it could make it up the call stack.
 
 

Micaletti

  • Guest
Re: Block Reference ?
« Reply #15 on: August 07, 2013, 07:22:41 PM »
Agreed. Good post.

Quote
When catching exceptions in a way you are saying you expected this might happen, and you understand why it happened, and you know how to deal with it.

Not always. Sometimes you are saying, I didn't expect anything to happen so what the hell happened? Especially when its in an example for a person using an unfamiliar API. I agree you should probably rethrow the exception if you're not going to actually handle it.
« Last Edit: August 07, 2013, 07:51:54 PM by Micaletti »

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Block Reference ?
« Reply #16 on: August 07, 2013, 07:57:52 PM »
Sorry if it implied that a using statement is better than a Try/Finally, but if used for guaranteeing that dispose is called on a object I prefer Using.
 
As for which one is better I can't really compare a Try/Catch/Finally because if Catch functionality is needed then need to use a Try/Catch/Block, and if any other code needs to execute in Finally block other than Dispose then a Try/Finally would be required.
 
When using a Try/Finally to accomplish the equivalent functionality as a using block then I can give no reason why one would be better than the other, other than preference.
 
Could also do
 
OnError GoTo Handler
....
...
GoTo Final
 
Handler:
Goto Final
 
Final:
Dispose()
 
 
 
 

exmachina

  • Guest
Re: Block Reference ?
« Reply #17 on: August 07, 2013, 11:13:38 PM »
There is no difference between the "using" Statement and a "try/finally" block, internally is the same (MSIL) code. If anyone has any doubt about this and about the performance,  take a look at this:

C# code
Code - C#: [Select]
  1. public void func1(){
  2.     using (MemoryStream stream = new MemoryStream()){
  3.     }
  4. }
  5.  

MSIL Code



C# code
Code - C#: [Select]
  1. public void func2(){
  2.     MemoryStream stream = new MemoryStream();
  3.  
  4.     try{
  5.     }finally
  6.     {
  7.         stream.Dispose();
  8.     }
  9. }
  10.  

MSIL Code



MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: Block Reference ?
« Reply #18 on: August 08, 2013, 07:44:28 AM »
Micaletti, you were telling someone not to use the Using statement which could be confusing since most of the examples they will be looking at will have the Using statement in them.  Your right putting a Using statement inside a Try/Catch/Finally block is redundant but during development I'll put a Using statement inside a Try/Catch block until I'm finished debugging. Then all I have to do is remove the Try/Catch and leave the Using.

The only methods you call in your example are part of the AutoCAD API and if you've ever crashed inside of one of their method calls you know that AutoCAD blows up and never returns to your try/catch.  Thats specific to the example you posted, I'm not saying that using the AutoCAD API will always blow up and not return to your try/catch just the example you posted.
Revit 2019, AMEP 2019 64bit Win 10

jcoon

  • Newt
  • Posts: 157
Re: Block Reference ?
« Reply #19 on: August 08, 2013, 09:15:14 AM »
Thanks for the descriptions and advice it really helps

Thank you,
John

Micaletti

  • Guest
Re: Block Reference ?
« Reply #20 on: August 08, 2013, 10:40:12 AM »
Micaletti, you were telling someone not to use the Using statement which could be confusing since most of the examples they will be looking at will have the Using statement in them.  Your right putting a Using statement inside a Try/Catch/Finally block is redundant but during development I'll put a Using statement inside a Try/Catch block until I'm finished debugging. Then all I have to do is remove the Try/Catch and leave the Using.

The only methods you call in your example are part of the AutoCAD API and if you've ever crashed inside of one of their method calls you know that AutoCAD blows up and never returns to your try/catch.  Thats specific to the example you posted, I'm not saying that using the AutoCAD API will always blow up and not return to your try/catch just the example you posted.

MC I still have no idea what you are talking about. Your OP wasn't clear and neither is this one. Specific to what exactly? AutoCAD exceptions inherit System.Exception. It catches everything unless you blow up AutoCAD, which has nothing to do with Try/Finally, Using, or my example. That's true for everything. In fact using doesn't catch anything, so what is your point sir?

The reason I told him that I would avoid Using is because hes going to be catching lots of exceptions while learning the API. You just said that you yourself do. Catch provides feedback. Using doesn't.
« Last Edit: August 08, 2013, 12:01:03 PM by Micaletti »

owenwengerd

  • Bull Frog
  • Posts: 451
Re: Block Reference ?
« Reply #21 on: August 08, 2013, 11:51:30 AM »
Catch provides feedback. Using doesn't.

You are mistaken. Catching exceptions indiscriminately is a very, very bad idea (in general, but especially when learning an API) precisely because it hides errors and propagates invalid or unexpected program state to a later point in the code where the cause is less obvious. This doesn't have anything to do per se with Using, which seems to me clearly superior to Try/Catch/Finally for encapsulating IDisposable object lifetime.

Micaletti

  • Guest
Re: Block Reference ?
« Reply #22 on: August 08, 2013, 12:04:23 PM »
Catch provides feedback. Using doesn't.

You are mistaken. Catching exceptions indiscriminately is a very, very bad idea (in general, but especially when learning an API) precisely because it hides errors and propagates invalid or unexpected program state to a later point in the code where the cause is less obvious. This doesn't have anything to do per se with Using, which seems to me clearly superior to Try/Catch/Finally for encapsulating IDisposable object lifetime.

Jeff has already pointed that out and I have already agreed. You can catch the exception, provide some feedback, then throw it again can't you? That would be exactly the same as using but with some feedback wouldn't it?

I agree you should probably rethrow the exception if you're not going to actually handle it.

I work specifically with the ACA/MEP API which has almost zero documentation and is riddled with eNotImplementedYet and the like. I can't begin to tell you how useful that catch feedback has been. With that said I have nothing against Using and don't intend to debate any further about it.
« Last Edit: August 08, 2013, 12:50:55 PM by Micaletti »

owenwengerd

  • Bull Frog
  • Posts: 451
Re: Block Reference ?
« Reply #23 on: August 08, 2013, 12:28:58 PM »
You can catch the exception, provide some feedback, then throw it again can't you? That would be exactly the same as using but with some feedback wouldn't it?

Yes, you can do that, but it would be a mistake (and most certainly not the same thing). During development your debugger will catch exceptions at the earliest possible point where you have the best chance to find and fix the cause. Catching exceptions at runtime should be done for a different purpose, namely to gracefully recover (or yes, in some cases rethrow when a graceful recovery is not possible). I can think of very few scenarios where it would be wise to intentionally catch eNotImplementedYet exceptions at runtime; those should be found and addressed while the program is under development. At runtime they should remain unhandled so the program code immediately ceases execution.

Micaletti

  • Guest
Re: Block Reference ?
« Reply #24 on: August 08, 2013, 01:17:05 PM »
Thanks Owen, I needed to hear that. I'm curious now, what is the proper way to report unforeseen exceptions that end users may experience?

I would also like to say that while its *possible* you could corrupt a database, explode a monitor, or launch a missile by msgboxing a caught exception *gasp*, it's highly unlikely in this context (debugging) and is a common "mistake" found everywhere, including autodesk university examples, these forums, google etc. I've never seen AutoCAD handle any exceptions on it's own, and have not had any problems with it in many thousands of lines of code.

Immediately ceasing execution as you suggested could also directly or indirectly cause a database to be corrupted or a missile to be unintentionally launched. The only bullet proof method is to be omniscient and handle everything.

Using your cellphone could give you brain cancer.
« Last Edit: August 08, 2013, 02:37:56 PM by Micaletti »

owenwengerd

  • Bull Frog
  • Posts: 451
Re: Block Reference ?
« Reply #25 on: August 08, 2013, 02:39:34 PM »
I'm curious now, what is the proper way to report unforeseen exceptions that end users may experience?

I think the .NET framework and AutoCAD do a pretty good job of reporting exceptions. The .NET framework insulates managed code from the underlying native AutoCAD code in such a way that many exceptions can be reported and the managed code halted, while still rolling the native system back into a safe and stable state so that the user can go on working in AutoCAD. Furthermore, AutoCAD does a good job of recovering when possible, or otherwise shutting down immediately before further damage is done. So to answer your question, I think exception reporting should be left to AutoCAD unless you have a specific reason not to.

The fallacy that many novice programmers make is believing it important to hide exceptions from end users. Exceptions are a useful resource, and it's less important how they are reported, just that they are reported. It's always the quiet ones that cause the most grief.

owenwengerd

  • Bull Frog
  • Posts: 451
Re: Block Reference ?
« Reply #26 on: August 08, 2013, 02:44:33 PM »
I should add for completeness that there are edge cases where every exception should be caught indiscriminately and reported manually. A notable case with AutoCAD plugins is during module initialization (i.e. IExtensionApplication::Initialize), where AutoCAD quietly ignores exceptions. That is a design flaw in AutoCAD's loader that must be "fixed" in user code, unfortunately.