Author Topic: Get Block Details from external File  (Read 1618 times)

0 Members and 1 Guest are viewing this topic.

GumbyCAD

  • Newt
  • Posts: 84
Get Block Details from external File
« on: July 15, 2014, 11:07:47 PM »
Hi Team,

I am trying to get the Block Details from an external file.

The external file has the blocks inserted into the file file.

The code executes but when I exit AutoCAD I get fatel error and in VS i get Memory violation error

Any ideas what I am doing wrong? Problem area is marked and if I comment it out it seams to be ok.
Many thanks in advance.

Code - Visual Basic: [Select]
  1.  
  2.     Private Sub GetBlockNameDetailsFromFile(ByVal FileName As String)
  3.  
  4.         Dim Doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
  5.         Dim Ed As Editor = Doc.Editor
  6.  
  7.         ' create a new database
  8.        Dim dwgs As Database = New Database(False, True)
  9.         Dim ThisDrawingBlockCount As Integer = 0
  10.  
  11.         Try
  12.  
  13.             dwgs.ReadDwgFile(FileName, FileOpenMode.OpenForReadAndReadShare, True, "")
  14.  
  15.             Using Doc.LockDocument
  16.  
  17.                 Using trans As Transaction = dwgs.TransactionManager.StartTransaction
  18.  
  19.                     Dim bt As BlockTable = CType(trans.GetObject(dwgs.BlockTableId, OpenMode.ForRead, False), BlockTable)
  20.  
  21.                     For Each OID As ObjectId In bt
  22.  
  23.                         Dim btr As BlockTableRecord = CType(trans.GetObject(OID, OpenMode.ForRead, False), BlockTableRecord)
  24.  
  25.                         If btr.IsErased = False AndAlso btr.IsAnonymous = False Then
  26.  
  27.                             If Not btr.Name.ToString.StartsWith("*") Then
  28.  
  29.                                 Dim Col As ObjectIdCollection = btr.GetBlockReferenceIds(True, False)
  30.                                 Dim eXts As Extents3d
  31.                                 If Col.Count > 0 Then
  32.  
  33.                                     Dim Bref As BlockReference = TryCast(trans.GetObject(Col.Item(0), OpenMode.ForRead), BlockReference)
  34.                                     eXts = Bref.GeometricExtents 'Save Block Extents just incase
  35.  
  36.                                     Dim Ans As Boolean = True
  37.  
  38.                                     Dim NR As DataRow = BlockDataSet.Tables("BlockDetails").NewRow
  39.                                     NR.Item("FileNameIncPath") = FileName
  40.                                     NR.Item("FileName") = Path.GetFileNameWithoutExtension(FileName)
  41.                                     NR.Item("BlockName") = btr.Name.ToString
  42.                                     NR.Item("HasAttribute") = btr.HasAttributeDefinitions
  43.  
  44.                                    'Problem Area - Start
  45.                                    Dim Xts As Extents3d = New Extents3d
  46.  
  47.                                     Dim ReturnFoundData As Boolean = False
  48.  
  49.                                     For Each id As ObjectId In btr
  50.  
  51.                                         Dim Entt As Entity = DirectCast(trans.GetObject(id, OpenMode.ForRead), Entity)
  52.                                        
  53.                                         'Get Extents of object provided its not Text, mtext or Attribute
  54.                                        If (Entt.GetRXClass.UnmanagedObject <> Autodesk.AutoCAD.Runtime.RXObject.GetClass(GetType(AttributeDefinition)).UnmanagedObject Or _
  55.                                             Entt.GetRXClass.UnmanagedObject <> Autodesk.AutoCAD.Runtime.RXObject.GetClass(GetType(DBText)).UnmanagedObject Or _
  56.                                             Entt.GetRXClass.UnmanagedObject <> Autodesk.AutoCAD.Runtime.RXObject.GetClass(GetType(MText)).UnmanagedObject) AndAlso _
  57.                                             Entt.Bounds IsNot Nothing Then
  58.  
  59.                                             Xts.AddExtents(CType(Entt.Bounds, Autodesk.AutoCAD.DatabaseServices.Extents3d))
  60.  
  61.                                             ReturnFoundData = True
  62.  
  63.                                         End If
  64.  
  65.                                     Next
  66.  
  67.                                     If ReturnFoundData = False Then
  68.                                         Xts = Bref.GeometricExtents
  69.                                     End If
  70.                                    'Problem Area - End
  71.  
  72.                                     NR.Item("BlockWidth") = Math.Abs(Xts.MaxPoint.X - Xts.MinPoint.X)
  73.                                     NR.Item("BlockHeight") = Math.Abs(Xts.MaxPoint.Y - Xts.MinPoint.Y)
  74.  
  75.                                     NR.Item("PointIsInside") = Ans
  76.                                     BlockDataSet.Tables("BlockDetails").Rows.Add(NR)
  77.  
  78.                                     ThisDrawingBlockCount += 1
  79.  
  80.                                 End If
  81.  
  82.                             End If
  83.  
  84.                         End If
  85.  
  86.                     Next
  87.  
  88.                     trans.Commit()
  89.  
  90.                 End Using
  91.  
  92.             End Using
  93.  
  94.         Catch ex As Exception
  95.  
  96.             Ed.WriteMessage("Error Reading " & FileName & vbCrLf & ex.Message.ToString & vbCrLf)
  97.  
  98.         Finally
  99.  
  100.             dwgs.Dispose()
  101.  
  102.             If ThisDrawingBlockCount = 0 Then
  103.  
  104.                 Dim NR As DataRow = BlockDataSet.Tables("BlockDetails").NewRow
  105.                 NR.Item("FileNameIncPath") = FileName
  106.                 NR.Item("FileName") = Path.GetFileNameWithoutExtension(FileName)
  107.                 NR.Item("BlockName") = ""
  108.                 NR.Item("HasAttribute") = False 'TODO
  109.                NR.Item("BlockWidth") = 0 'TODO
  110.                NR.Item("BlockHeight") = 0 'TODO
  111.                NR.Item("PointIsInside") = False 'TODO
  112.                BlockDataSet.Tables("BlockDetails").Rows.Add(NR)
  113.  
  114.             End If
  115.  
  116.         End Try
  117.  
  118.         dwgs = Nothing
  119.  
  120.     End Sub
  121.  

MickD

  • King Gator
  • Posts: 3637
  • (x-in)->[process]->(y-out) ... simples!
Re: Get Block Details from external File
« Reply #1 on: July 15, 2014, 11:35:04 PM »
Maybe I'm missing something but why are you getting the 'UnManagedObject' of the entity, the easiest way is just to compare the string values of the GetRXClass.Name method:


if (Entt.GetRXClass.Name <> "AcDbMText") for example.

By getting this unmanaged object you are bypassing the wrapper that handles the memory (I'm only making a wild guess here though) of the object.
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien

GumbyCAD

  • Newt
  • Posts: 84
Re: Get Block Details from external File
« Reply #2 on: July 16, 2014, 08:55:20 PM »

Tryed that.......

Still getting:

AccessViolationException was Handled.
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: Get Block Details from external File
« Reply #3 on: July 18, 2014, 01:44:50 PM »
check out the dumpuserdata.xml file to see if you can get any insight


What is it you are trying to accomplish with this here?  I see you're looking at the bounds of objects within the block definition and also the extents of the first reference in the list with no regard for the transform applied to the reference.
Code - vb.net: [Select]
  1.                                    'Problem Area - Start
  2.                                     Dim Xts As Extents3d = New Extents3d
  3.  
  4.                                     Dim ReturnFoundData As Boolean = False
  5.  
  6.                                     For Each id As ObjectId In btr
  7.  
  8.                                         Dim Entt As Entity = DirectCast(trans.GetObject(id, OpenMode.ForRead), Entity)
  9.  
  10.                                         'Get Extents of object provided its not Text, mtext or Attribute
  11.                                         If (Entt.GetRXClass.UnmanagedObject <> Autodesk.AutoCAD.Runtime.RXObject.GetClass(GetType(AttributeDefinition)).UnmanagedObject Or _
  12.                                             Entt.GetRXClass.UnmanagedObject <> Autodesk.AutoCAD.Runtime.RXObject.GetClass(GetType(DBText)).UnmanagedObject Or _
  13.                                             Entt.GetRXClass.UnmanagedObject <> Autodesk.AutoCAD.Runtime.RXObject.GetClass(GetType(MText)).UnmanagedObject) AndAlso _
  14.                                             Entt.Bounds IsNot Nothing Then
  15.  
  16.                                             Xts.AddExtents(CType(Entt.Bounds, Autodesk.AutoCAD.DatabaseServices.Extents3d))
  17.  
  18.                                             ReturnFoundData = True
  19.  
  20.                                         End If
  21.  
  22.                                     Next
  23.  
  24.                                     If ReturnFoundData = False Then
  25.                                         Xts = Bref.GeometricExtents
  26.                                     End If
  27.                                    'Problem Area - End

Then I start to get picky because I'm watching you create thousands of RXClass objects and make multiple accesses to the RXClass on each entity as you walk through the block table.

You haven't read the documentation for RXClass or you would know about using RXClass.IsDerivedFrom, since we know from the classmap that AttributeDefinition is derived from DBText the check for both can be done with a single operation mitigating the above partially.

Consider a different code structure:
Code - vb.net: [Select]
  1.                                    'Problem Area - Start
  2.                                     Dim Xts As Extents3d = New Extents3d
  3.  
  4.                                     Dim ReturnFoundData As Boolean = False
  5.  
  6.                                     Dim rxT as RXClass = Autodesk.AutoCAD.Runtime.RXObject.GetClass(GetType(DBText))
  7.                                     Dim rxM as RXClass = Autodesk.AutoCAD.Runtime.RXObject.GetClass(GetType(MText))
  8.  
  9.                                     For Each id As ObjectId In btr
  10.  
  11.                                         Dim Entt As Entity = DirectCast(trans.GetObject(id, OpenMode.ForRead), Entity)
  12.  
  13.                                         Dim rxc as RXClass = Entt.GetRXClass()
  14.  
  15.                                         'Get Extents of object provided its not Text, mtext or Attribute
  16.                                         If rxc.IsDerivedFrom(rxT) OrElse rxc.IsDerivedFrom(rxM) OrElse Entt.Bounds Is Nothing Then
  17.                                             Continue For
  18.                                         End If
  19.                                         Xts.AddExtents(CType(Entt.Bounds, Autodesk.AutoCAD.DatabaseServices.Extents3d))
  20.  
  21.                                          ReturnFoundData = True
  22.                                     Next
  23.  
  24.                                     If ReturnFoundData = False Then
  25.                                         Xts = Bref.GeometricExtents
  26.                                     End If
  27.                                    'Problem Area - End

As to the real source of your problem... I don't think it's in this code here, this code should all easily dispose when it goes out of scope.

nekitip

  • Guest
Re: Get Block Details from external File
« Reply #4 on: July 21, 2014, 04:14:50 AM »
maybe to try
Code - vb.net: [Select]
  1. dwgs.ReadDwgFile(FileName, FileOpenMode.OpenForReadAndReadShare, False, Nothing)
also, maybe try Using block instead of dispose (this should not have been the issue but because of consistensy...?)
Code - vb.net: [Select]
  1. Using Using db As New Database(False, True)