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.
Hi,
Do you use document locking?
using (DocumentLock docLock =
Application.DocumentManager.MdiActiveDocument.LockDocument())
Yes. If i leave out the Document lock i get an eLockViolation exception, without a crash.
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.?
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
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
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).
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.
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 -