.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Alternative to Database.Insert, my current method crashes AutoCAD Arch 2013

8 REPLIES 8
Reply
Message 1 of 9
dwi_it
1622 Views, 8 Replies

Alternative to Database.Insert, my current method crashes AutoCAD Arch 2013

I have the following code to pull in another dwg as a block in the current drawing. 

 

                    Using srcDB As New Database(False, True)
                        srcDB.ReadDwgFile(BlockFile, FileOpenMode.OpenForReadAndAllShare, True, Nothing)
                        blockid = db.Insert(BlockName, srcDB, True)
                    End Using

 Only problem is that this causes AutoCAD to crash, debugger shows a FatalExecutionEngineError on the db.insert line, error code 0xc0000005 (Access Violation). When running withoug the debugger, you just get the windows "Autocad has stopped working" window. The error is not consitent, sometimes happing the 2nd, 3rd, or 4th time the function is called, not always the first. There is nothing wrong with file being inserted, i've tested a bunch of different files and its not related to any particular one.

 

Without any clue and probably no hope of getting past this error, are there alternative ways to accomplish the same thing as the db.Insert function? That is insert the external drawing as a new block? 

 

I'm hoping that changing methods may get me around this error.

 

 

8 REPLIES 8
Message 2 of 9
Marat.Mirgaleev
in reply to: dwi_it

Hi,

 

   Do you use document locking?

     using (DocumentLock docLock =

       Application.DocumentManager.MdiActiveDocument.LockDocument())



Marat Mirgaleev
Developer Technical Services
Autodesk Developer Network
Message 3 of 9
dwi_it
in reply to: Marat.Mirgaleev

Yes. If i leave out the Document lock i get an eLockViolation exception, without a crash.

Message 4 of 9
Marat.Mirgaleev
in reply to: dwi_it

1) Does it crash right when you step over db.Insert()?

 

2) Could you provide a little bigger piece of code, please, in order we could see the transaction start-dispose; try-catch etc.?



Marat Mirgaleev
Developer Technical Services
Autodesk Developer Network
Message 5 of 9
dwi_it
in reply to: Marat.Mirgaleev

Yes, it always stops running on db.insert. 

 

Here is a simplified example that causes the error. This is run from a button on a Palette, created like so AcadUtil.Palettes.CreatePalette("Project", Contrl, New System.Drawing.Size(300, 550)), under a command with the CommandFlags.Session set. (Interestingly, as i found trying to create the example,  the same code does not cause the crash when run directly as a CommandMethod)

 

In the below test the crash happend when attempting to insert the 3rd file in the list.

 

                Dim dwg = Application.DocumentManager.MdiActiveDocument
                Dim db = dwg.Database

                Using dl = dwg.LockDocument
                    Using tr = db.TransactionManager.StartTransaction


                        Dim BlockFiles = {"filename1",
                        "filename2",
                        "filename3",
                        "filename4",
                        "filename5",
                        "filename5"}

                        Dim bt As BlockTable = tr.GetObject(db.BlockTableId, OpenMode.ForWrite, False)
                        Dim br As BlockReference

                        For Each item In BlockFiles
                            Using TempDB As New Database(False, True)

                                Dim blockid As ObjectId
                                Dim BlockName As String = item.Replace("\", "").Replace(":", "").Replace(".", "")
                                If Not bt.Has(BlockName) Then
                                    If IO.File.Exists(item) Then
                                        TempDB.ReadDwgFile(item, IO.FileShare.Read, True, Nothing)
                                        blockid = db.Insert(BlockName, TempDB, True)
                                    Else
                                        'Throw exception for missing file 
                                        Throw New System.Exception(String.Format("File {0} is not found.", item))
                                    End If

                                Else
                                    blockid = bt.Item(BlockName)
                                End If

                            End Using
                        Next


                        tr.Commit()
                    End Using
                End Using

 

Message 6 of 9
norman.yuan
in reply to: dwi_it

Are you sure you have drawing named "filename1/2/3/4/5" (NOTE: without extension ".dwg"!) and they are valid drawing file (e.g. you can open then in AutoCAD)? Yes, I saw you use File.Exists() to make sure the file does exists. But just want to make sure the files are actually good drawing file.

 

Why don't you just find a known good block drawing file and hard-code its path in the code to make sure it is read into the side Database, and then run Database.Insert() again to see what happens?

Norman Yuan

Drive CAD With Code

EESignature

Message 7 of 9
dwi_it
in reply to: norman.yuan

I explored the possiblity of bad files. I opened them, ran and audit command and they were clean. I purged all unused stuff from the drawings and re-saved. I though it worked at first (again cause the error was inconsitent on how many times the db.insert could be called before the error happened), but after repeated testing it still would fail with known good files.

 

That said, the files I'm using in this example are drawings (title blocks, text, lines, etc.). I've used similar code (different context, but same code) to insert simple 3d models without issue (at least not that my users have reported).

Message 8 of 9
dwi_it
in reply to: dwi_it

Ok, while I didn't solve the original error, I didn't manage to work out an alternate method that does the same thing without crashing. Using the this post as a shell (http://through-the-interface.typepad.com/through_the_interface/2006/08/import_blocks_f.html), I modified it to create a block from the model space of the origin file. This gives me the same end as db.insert. 

 

Using srcdb As New Database(False, True)
                        srcdb.ReadDwgFile(BlockFile, FileOpenMode.OpenForReadAndAllShare, True, "")

                        Using srdtr = srcdb.TransactionManager.StartTransaction
                            Dim srcbt As BlockTable = srdtr.GetObject(srcdb.BlockTableId, OpenMode.ForWrite, False)

                            'create a new block out of model space 
                            Dim modspace As BlockTableRecord = srdtr.GetObject(srcbt.Item(BlockTableRecord.ModelSpace), OpenMode.ForWrite)
                            Dim allblock As New BlockTableRecord() ' = modspace.DeepClone(srcbt, New IdMapping, True)
                            srcbt.Add(allblock)
                            srdtr.AddNewlyCreatedDBObject(allblock, True)

                            Dim modspaceids As New ObjectIdCollection
                            For Each modspaceid In modspace
                                modspaceids.Add(modspaceid)
                            Next
                            allblock.AssumeOwnershipOf(modspaceids)

                            allblock.Name = BlockName


                            Dim blockids As New ObjectIdCollection
                            For Each srcblockid As ObjectId In srcbt
                                Dim srcbtr As BlockTableRecord = srdtr.GetObject(srcblockid, OpenMode.ForWrite, False)
                                If srcbtr IsNot Nothing AndAlso Not srcbtr.IsAnonymous AndAlso Not srcbtr.IsLayout Then
                                    blockids.Add(srcblockid)
                                    'rename for dest db
                                    If srcbtr.Name <> BlockName Then
                                        srcbtr.Name = AcadUtil.AcadFunctions.GetUniqueBlockID(db, tr)
                                    End If

                                End If
                                'srcbtr.Dispose()
                            Next

                            srdtr.Commit()

                            Dim mapping As New IdMapping
                            srcdb.WblockCloneObjects(blockids, db.BlockTableId, mapping, DuplicateRecordCloning.Ignore, False)

                        End Using
                    End Using

Basically I create a new block in the source database, and AssumeOwnershipOf everything in model space. The follow the rest of Kean's post on copying the blocks to the destination database. There is a call to one of my functions for the app, GetUniqueBlockID just generates a long randomized string and makes sure it doesn't alread exist. This renames the blocks in the source to prevent overlaps in the destination (except for the block i'm creating from the file itself, i need to know that name). I tried DuplicateRecordCloning.MangleName in the WBlockCloneObjects call, but that that changed the name of all the block, even the block i was trying to create (which wasn't a duplicate).

 

For now this seems to work, or at least it works more times in a row than db.insert does.

Message 9 of 9
Alfred.NESWADBA
in reply to: dwi_it

Hi,

 

>> i've tested a bunch of different files and its not related to any particular one

First, sorry to be not able to have a solution, but one idea that might help to come more close to what type of drawings raises the exception.

 

In my case I had a similar problem and used Civil3D. Drawings that where modified/saved with Civil3D 2012 and then opened in C3D2010 had a problem using the Db.Insert code (similar to what you have). Yes, I verified that in modelspace there were no Civil-specific objects saved, so as long as you don't use any C3D-specific functionality in 2010 it should not be a problem to insert any other drawing.

In my case it's not a problem of what drawing I try to insert, it's a problem of what drawing I'm currently in (into which DB I try to insert any other drawing).

 

I could solve the situation using the command -EXPORTTOAUTOCAD (started with C3D2012), that creates a clean drawing without any AEC-specific information. Opening this drawing then let me using the Db.Insert without any issues.

 

My thoughts to that are that mixing drawings based on different AEC-lib is part of this problem. So opening a drawing based on the AEC-lib for 2012 (AEC-version 6.7) with an older AEC-app (C3D2010/AEC-version 6.0) might be one source of the problem.

As I don't have this problem with Map3D and also not with plain AutoCAD (even using the drawing from C3D2012) makes me thinking it's the AEC-lib

As I don't have this problem with any other Civil version than C3D2010 (e.g. C3D2011) makes me thinking it's Civil3D2010

 

....as you too I'm not sure what exactly is the source of the problem, but as also ACA works based on AEC-lib's it might be worth to check out if the drawings you used are based on different versions of AEC when last saved, and maybe more important, verify if the drawings were modified in mixed AEC-environment, newer and older versions of ACA.

 

Just an idea, - alfred -

------------------------------------------------------------------------------------
Alfred NESWADBA
Ingenieur Studio HOLLAUS ... www.hollaus.at ... blog.hollaus.at ... CDay 2024
------------------------------------------------------------------------------------
(not an Autodesk consultant)

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost