In the past C++/C era, it was very easy to crash AutoCAD or even the whole Operating System. Now in the .NET time, it is harder, much harder than before, but we still can find various ways to crash AutoCAD using its .NET API, from the easiest or most common to quite hard or very creative.
We made AutoCAD crash a while back using the .NET BRep API. At that time, the crash was likely caused by some BRep objects not being explicitly disposed of by us but being left to the .NET GC. Let’s try to be a little bit too cautions, disposing of every disposable BRep object, and see what we will get this time.
Here is the sample code:
[CommandMethod("CrashAutoCAD10")]
public static void CrashAutoCAD10_Method()
{
Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
Database db = HostApplicationServices.WorkingDatabase;
try
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
RXClass solidRxClass = RXObject.GetClass(typeof(Solid3d));
foreach (ObjectId id in btr)
{
if (id.ObjectClass == solidRxClass)
{
Solid3d solid = (Solid3d)tr.GetObject(id, OpenMode.ForRead);
using (Autodesk.AutoCAD.BoundaryRepresentation.Brep brep = new Autodesk.AutoCAD.BoundaryRepresentation.Brep(solid))
{
ed.WriteMessage("\nObjectId of the solid: {0}", id);
using (Autodesk.AutoCAD.DatabaseServices.Surface surface = brep.Surf)
{
ed.WriteMessage("\n\tSurface area: {0}", surface.GetArea());
}
foreach (Autodesk.AutoCAD.BoundaryRepresentation.Face face in brep.Faces)
{
using (face)
{
ed.WriteMessage("\n\tFace IsOrientToSurface: {0}", face.IsOrientToSurface);
foreach (Autodesk.AutoCAD.BoundaryRepresentation.BoundaryLoop loop in face.Loops)
{
using (loop)
{
ed.WriteMessage("\n\tBoundaryLoop type: {0}", loop.LoopType);
foreach (Autodesk.AutoCAD.BoundaryRepresentation.Edge edge in loop.Edges)
{
using (edge)
{
using (edge.Curve) { ed.WriteMessage("\n\t\tEdge curve type: {0}", edge.Curve.GetType()); }
using (edge.Vertex1) { ed.WriteMessage("\n\t\t\tVertext1: {0}", edge.Vertex1.Point); }
using (edge.Vertex2) { ed.WriteMessage("\n\t\t\tVertext2: {0}", edge.Vertex2.Point); }
}
}
}
}
}
}
}
}
}
tr.Commit();
}
}
catch (System.Exception ex)
{
ed.WriteMessage(Environment.NewLine + ex.Message);
}
}
Now we lanuch AutoCAD, load the assembly, draw a cylinder solid, and run the test command. The kaboom occurs right away!
What about not disposing of those BRep objects explicitly by us then?
Here we go:
[CommandMethod("SeemsFine10")]
public static void SeemsFine10_Method()
{
Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
Database db = HostApplicationServices.WorkingDatabase;
try
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
RXClass solidRxClass = RXObject.GetClass(typeof(Solid3d));
foreach (ObjectId id in btr)
{
if (id.ObjectClass == solidRxClass)
{
Solid3d solid = (Solid3d)tr.GetObject(id, OpenMode.ForRead);
Autodesk.AutoCAD.BoundaryRepresentation.Brep brep = new Autodesk.AutoCAD.BoundaryRepresentation.Brep(solid);
{
ed.WriteMessage("\nObjectId of the solid: {0}", id);
Autodesk.AutoCAD.DatabaseServices.Surface surface = brep.Surf;
//using (surface)
{
ed.WriteMessage("\n\tSurface area: {0}", surface.GetArea());
}
foreach (Autodesk.AutoCAD.BoundaryRepresentation.Face face in brep.Faces)
{
//using (face)
{
ed.WriteMessage("\n\tFace IsOrientToSurface: {0}", face.IsOrientToSurface);
foreach (Autodesk.AutoCAD.BoundaryRepresentation.BoundaryLoop loop in face.Loops)
{
//using (loop)
{
ed.WriteMessage("\n\tBoundaryLoop type: {0}", loop.LoopType);
foreach (Autodesk.AutoCAD.BoundaryRepresentation.Edge edge in loop.Edges)
{
//using (edge)
{
//using (edge.Curve)
{ ed.WriteMessage("\n\t\tEdge curve type: {0}", edge.Curve.GetType()); }
//using (edge.Vertex1)
{ ed.WriteMessage("\n\t\t\tVertext1: {0}", edge.Vertex1.Point); }
//using (edge.Vertex2)
{ ed.WriteMessage("\n\t\t\tVertext2: {0}", edge.Vertex2.Point); }
}
}
}
}
}
}
}
}
}
tr.Commit();
}
}
catch (System.Exception ex)
{
ed.WriteMessage(Environment.NewLine + ex.Message);
}
}
As the command name indicates, it seems fine!
The second command behaves better than the first! At least, users can see something and get some results at this moment.
So what is the good practice regarding disposing of or not BRep related objects?
No idea!
The leading edge AutoCAD .NET Addin Wizard (AcadNetAddinWizard) provides various project wizards, item wizards, coders and widgets to help program AutoCAD .NET addins.
Posted by: |