I'm working on an AutoCAD plug-in. The following three functions are from a course by AutoCAD, written by Jerry Winters. I'm using these functions to obtain the data I need and pass it into a data grid.
Function SelectAllBlocks(dbIn As Database) As ObjectIdCollection
Dim retIDs As New ObjectIdCollection
Using myTrans As Transaction = dbIn.TransactionManager.StartTransaction
Dim myBT As BlockTable = dbIn.BlockTableId.GetObject(OpenMode.ForRead)
For Each btrID As ObjectId In myBT
Dim myBTR As BlockTableRecord = btrID.GetObject(OpenMode.ForRead)
For Each BRefID As ObjectId In myBTR.GetBlockReferenceIds(True, False)
retIDs.Add(BRefID)
Next
Next
End Using
Return retIDs
End Function
Function GetBlockProperties(ObjID As ObjectId) As Dictionary(Of String, Object)
Dim myD As New Dictionary(Of String, Object)
Using myTrans As Transaction =
ObjID.Database.TransactionManager.StartTransaction
Dim myEnt As BlockReference =
ObjID.GetObject(OpenMode.ForRead)
For Each myPInfo As Reflection.PropertyInfo In GetType(BlockReference).GetProperties
myD.Add(myPInfo.Name, myPInfo.GetValue(myEnt))
Next
End Using
Return myD
End Function
Function GetBTRProperties(ObjID As ObjectId) As Dictionary(Of String, Object)
Dim myD As New Dictionary(Of String, Object)
Using myTrans As Transaction =
ObjID.Database.TransactionManager.StartTransaction
Dim myEnt As BlockTableRecord =
ObjID.GetObject(OpenMode.ForRead)
For Each myPInfo As System.Reflection.PropertyInfo In GetType(BlockTableRecord).GetProperties
myD.Add(myPInfo.Name, myPInfo.GetValue(myEnt))
Next
End Using
Return myD
End Function
My code, which is an attempt to rewrite some of the material from the course for my own needs, loads some information into the data grid but throws an "Exception has been thrown by the target of an invocation" error.
Private Sub cmdBlocks_Click(sender As Object, e As EventArgs) Handles cmdBlocks.Click
Dim tbl As New System.Data.DataTable
' Create four typed columns in the DataTable.
tbl.Columns.Add("User name", GetType(String))
tbl.Columns.Add("Full name", GetType(String))
tbl.Columns.Add("Time", GetType(String))
tbl.Columns.Add("name", GetType(String))
tbl.Columns.Add("Block handle", GetType(String))
tbl.Columns.Add("Block name", GetType(String))
tbl.Columns.Add("Location X", GetType(String))
tbl.Columns.Add("Location Y", GetType(String))
tbl.Columns.Add("Location Z", GetType(String))
dgvBlocks.DataSource = tbl
Dim myDB As Database = HostApplicationServices.WorkingDatabase,
myIDs As ObjectIdCollection = SelectAllBlocks(myDB)
Using myTrans As Transaction = myDB.TransactionManager.StartTransaction
For Each myBID As ObjectId In myIDs
Dim blockProps As Dictionary(Of String, Object) = GetBlockProperties(myBID)
Dim blockProps2 As Dictionary(Of String, Object) = GetBTRProperties(blockProps("DynamicBlockTableRecord"))
Dim blockAtts As Dictionary(Of String, Dictionary(Of String, String)) = GetBlockAttributes(myBID)
Dim username As String = My.Computer.Name,
filename As String = HostApplicationServices.WorkingDatabase.Filename,
time As String = DateTime.UtcNow,
Name As String = blockProps2("Name"),
BlockHandle As String = blockProps("Handle").ToString,
BlockName As String = blockProps("BlockName").ToString,
location As Point3d = blockProps("Position"),
locX As String = location.X.ToString,
locY As String = location.Y.ToString,
locZ As String = location.Z.ToString
tbl.Rows.Add(username, filename, time, Name, BlockHandle, BlockName, locX, locY, locZ)
Next
myTrans.Abort()
End Using
End Sub
The "eLockViolation" exception usually happens when you try modify the database from a modeless form or palette (which is also modeless).
Here is a way to lock it:
Using docLock As DocumentLock = Application.DocumentManager.MdiActiveDocument.LockDocument()
' do your code here...
End Using
Usually you call it once, meaning one lock per action to change database, even if you have several transactions, but you might consider one lock per transaction to make it easier to implement (although at higher performance cost).