I have the following code that Inserts a Block with Attributes by using an empty database and
ReadDwgFile. But I seem to be missing something because it has caused memory errors that lead to Exception Errors in Autocad, which then bombs out. Is there something in addition to the db.CloseInput(true) and db.Dispose() that I need to fully release the unseen instance of Autocad?
Thanks in advance,
Brian
Code:
<Autodesk.AutoCAD.Runtime.
CommandMethod("InsertDetailCallOut", CommandFlags.Session)> _
PublicSharedSub InsertDetailCallOut(ByVal BlockPath AsString, ByVal thePoint AsPoint3d, ByVal BlockName AsString, ByVal dblscale AsDouble, _
ByVal Detail_Number AsInteger, ByVal Detail_Name AsString, ByVal Detail_Qty AsInteger, _
ByVal Detail_Material AsString, ByVal Detail_Stock AsString, ByVal Detail_Notes AsString)
Dim acDoc As Autodesk.AutoCAD.ApplicationServices.Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
Dim fname AsString= BlockPath
Dim idBTR AsObjectIdHostApplicationServices.Current.FindFile(fname, acDoc.Database, FindFileHint.Default)
Using docloc AsDocumentLock= acDoc.LockDocument
TryDim trans AsTransaction= acDoc.TransactionManager.StartTransaction
TryDim bt AsBlockTable = CType(trans.GetObject(acDoc.Database.BlockTableId, OpenMode.ForRead), BlockTable)
Dim db AsNewDatabase(False, False)
db.ReadDwgFile(fname, System.IO.
FileShare.Read, True, "")
idBTR = acDoc.Database.Insert(BlockName, db,
False)
Dim btr AsBlockTableRecord = CType(trans.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite), BlockTableRecord)
Dim bref AsBlockReference = NewBlockReference(thePoint, idBTR)
Dim theScale AsScale3d = NewScale3d(dblscale, dblscale, dblscale)
bref.ScaleFactors = theScale
bref.Layer =
"StockList"Try
btr.AppendEntity(bref)
trans.TransactionManager.AddNewlyCreatedDBObject(bref,
True)
FinallyEndTryDim RefBTR AsBlockTableRecord = trans.GetObject(bref.BlockTableRecord, OpenMode.ForRead)
Dim attEnt AsEntityForEach attID AsObjectIdInRefBTR
attEnt = trans.GetObject(attID,
OpenMode.ForRead)
IfTypeOf attEnt IsAttributeDefinitionThenDim attDef AsAttributeDefinition= attEnt
Dim attRef AsAttributeReference = NewAttributeReference()
attRef.SetAttributeFromBlock(attDef, bref.BlockTransform)
Dim attRefID AsObjectId
attRefID = bref.AttributeCollection.AppendAttribute(attRef)
SelectCaseattDef.Tag
Case"DET-NAME"
attRef.TextString = Detail_Name
Case"DET-NO"
attRef.TextString = Trim(Str(Detail_Number))
Case"DET-QTY"
attRef.TextString =
"(" & Trim(Str(Detail_Qty)) & ") - REQ'D. / HEATER"Case"DET-MAT"
attRef.TextString = Detail_Material
Case"DET-STK"
attRef.TextString = Detail_Stock
Case"DET-NOTES"
attRef.TextString = Detail_Notes
EndSelect
trans.AddNewlyCreatedDBObject(attRef,
True)
EndIfNext
trans.Commit()
db.CloseInput(
True)
db.Dispose()
FinallyEndTryFinallyEndTry
acDoc.Editor.UpdateScreen()
EndUsingEndSub
In addition I forgot to mention:
I use this routine multiple times in the same drawing. It appears that after about 10 calls to it that problems start.
But not always. There are times the program will finish properly. Weird.
I see nothing wrong with your code
just chaged few lines in there
See how it will works
' changed on short command "idc" <CommandMethod("InsertDetailCallOut", "idc", CommandFlags.Session)> _ Public Shared Sub testInsertCallout() Dim fname As String = "c:\test\myfile.dwg" ' check if file exist If Not File.Exists(fname) Then Exit Sub End If '' you have also to check if layer "StockList" existbefore '--------------------------------------------- '' you have also to check if block "YourBlockName" exist before '--------------------------------------------- Dim p As Point3d = New Point3d(90.5, 90.1, 0) 'dummy point InsertDetailCallOut(fname, p, "YourBlockName", 0.5, 777, "Detail Name =", 100, "Detail Material =", "Detail_Stock= ", "Detail_Notes= ") End Sub Public Shared Sub InsertDetailCallOut(ByVal BlockPath As String, ByVal thePoint As Point3d, ByVal BlockName As String, ByVal dblscale As Double, _ ByVal Detail_Number As Integer, ByVal Detail_Name As String, ByVal Detail_Qty As Integer, _ ByVal Detail_Material As String, ByVal Detail_Stock As String, ByVal Detail_Notes As String) Dim acDoc As Autodesk.AutoCAD.ApplicationServices.Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument Dim fname As String = BlockPath Dim idBTR As ObjectId Try Using docloc As DocumentLock = acDoc.LockDocument Using trans As Transaction = acDoc.TransactionManager.StartTransaction Dim bt As BlockTable = CType(trans.GetObject(acDoc.Database.BlockTableId, OpenMode.ForRead), BlockTable) ' you have before to check if layer "Stocklist" exist Dim db As New Database(False, False) Using db db.ReadDwgFile(fname, System.IO.FileShare.Read, True, "") idBTR = acDoc.Database.Insert(BlockName, db, False) Dim btr As BlockTableRecord = CType(trans.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite), BlockTableRecord) Dim bref As BlockReference = New BlockReference(thePoint, idBTR) Dim theScale As Scale3d = New Scale3d(dblscale, dblscale, dblscale) bref.ScaleFactors = theScale bref.Layer = "StockList" btr.AppendEntity(bref) trans.TransactionManager.AddNewlyCreatedDBObject(bref, True) Dim RefBTR As BlockTableRecord = trans.GetObject(bref.BlockTableRecord, OpenMode.ForRead) Dim attEnt As Entity For Each attID As ObjectId In RefBTR attEnt = trans.GetObject(attID, OpenMode.ForRead) If TypeOf attEnt Is AttributeDefinition Then Dim attDef As AttributeDefinition = attEnt Dim attRef As AttributeReference = New AttributeReference() attRef.SetAttributeFromBlock(attDef, bref.BlockTransform) Dim attRefID As ObjectId attRefID = bref.AttributeCollection.AppendAttribute(attRef) Select Case attDef.Tag() Case "DET-NAME" attRef.TextString = Detail_Name Case "DET-NO" attRef.TextString = Trim(Str(Detail_Number)) Case "DET-QTY" attRef.TextString = "(" & Trim(Str(Detail_Qty)) & ") - REQ'D. / HEATER" Case "DET-MAT" attRef.TextString = Detail_Material Case "DET-STK" attRef.TextString = Detail_Stock Case "DET-NOTES" attRef.TextString = Detail_Notes End Select attRef.AdjustAlignment(acDoc.Database) trans.AddNewlyCreatedDBObject(attRef, True) End If Next End Using trans.Commit() End Using acDoc.Editor.UpdateScreen() End Using Catch ex As System.Exception MsgBox(ex.Message) Finally End Try End Sub
Thank you for both of your replies.
I've added attRef.Dispose() as Gasty suggested.
I also made the changes suggested by Hallex.
I still get the Unhandled exception error.
It's telling me that:
"Attempted to read or write protected memory. This is often an
indication that other memory is corrupt."
This application is still in development. So I'm the only one using it.
I have run it about 10 times in a row to complettion of the program with no error.
Then other times it will error half way through.
If I bypass the InsertCallOut sub, I have no problems with the program.
Any other suggestions?
Could this be an Autocad bug?
Thanks,
Brian
I did't find this problem with my code
I've added 1000 blocks using my routine
like this
<CommandMethod("InsertDetailCallOut", "idc", CommandFlags.Session)> _ Public Shared Sub testInsertCallout() Dim fname As String = "c:\test\myfile.dwg" ' check if file exist If Not File.Exists(fname) Then Exit Sub End If '' you have also to check if layer "StockList" existbefore '--------------------------------------------- '' you have also to check if block "YourBlockName" exist before '--------------------------------------------- Dim p As Point3d = Point3d.Origin 'dummy point ' add 1000 block for quick test For i As Integer = 0 To 999 InsertDetailCallOut(fname, New Point3d(p.X + (i + 1) * 10, p.Y + (i + 1) * 10, 0), "YourBlockName", 0.5, 777, "Detail Name =", 100, "Detail Material =", "Detail_Stock= ", "Detail_Notes= ") Next ' time expired about 1.3 minutes on my machine End Sub
HostApplicationServices.Current.FindFile(fname, acDoc.Database, FindFileHint.Default) Try Using docloc As DocumentLock = acDoc.LockDocument Using trans As Transaction = acDoc.TransactionManager.StartTransaction Dim bt As BlockTable = CType(trans.GetObject(acDoc.Database.BlockTableId, OpenMode.ForRead), BlockTable) Dim db As New Database(False, False) Using db db.ReadDwgFile(fname, System.IO.FileShare.Read, True, "") idBTR = acDoc.Database.Insert(BlockName & ".dwg", db, False) << Fails on the line Above >> Dim btr As BlockTableRecord = CType(trans.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite), BlockTableRecord) Dim bref As BlockReference = New BlockReference(thePoint, idBTR) Dim theScale As Scale3d = New Scale3d(dblscale, dblscale, dblscale)
Update to the problem.
I've changed my code to build an array of data for the placement and information for the detail call outs.
Then after all the details have been drawn I run through the array list to insert the details call outs.
There are 14 items in the array and it fails on the second pass each time, at the line above.
Any thoughts?
Brian
Ok, after further testing, I now believe the problem is an error in my code in another routine.
I think I might be going past the bounds of a collection which is causing this problem.
I'll update after more debugging.
Brian
Can't find what you're looking for? Ask the community or share your knowledge.