【问题标题】:AutoCAD Associative Framework GetEdgeVertexSubentities() FATAL ERRORAutoCAD 关联框架 GetEdgeVertexSubentities() 致命错误
【发布时间】:2018-11-23 08:47:57
【问题描述】:

AutoCAD 2015 - 我目前正在学习用于创建几何约束的 .NET API(注意:我一般对 AutoCAD API 并不陌生)。我正在使用从 AutoDesk 课程之一中获得的代码示例以供学习,我似乎无法弄清楚为什么在尝试使用 GetEdgeVertexSubentities(..) 检索实体的顶点时出现“致命错误”并崩溃.没有抛出异常,Autocad 只是弹出消息并崩溃。 Try/Catch 不执行任何操作,因此无法检查异常消息或调用堆栈。如果有人以前看过这个或者有一些我可以查看或尝试的想法,将不胜感激。

无论是否附加调试器,都会发生这种情况。换句话说,从快捷方式启动的发布版本也会发生同样的错误。

我尝试过使用不同的绘图、不同的计算机,甚至不同的操作系统(即 Win7、Win10),都具有相同的最终结果。下面的错误消息和崩溃。

Visual Studio 输出窗口消息:

抛出异常:AcdbMgd.dll 中的“System.AccessViolationException”

并且弹出错误信息:

这是完整的测试命令。有问题的代码行被清楚地标记,大约在代码 sn-p 的一半处。

using System;
using System.Collections.Generic;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;

[CommandMethod("TESTFIXED")]
public static void testFixedCommand()
{
  Database db = Application.DocumentManager.MdiActiveDocument.Database;
  Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = db.TransactionManager;
  using (Transaction transaction = tm.StartTransaction())
  {
    // Create DB resident line
    BlockTable blockTable = (BlockTable)transaction.GetObject(db.BlockTableId, OpenMode.ForRead, false);
    BlockTableRecord modelSpace = (BlockTableRecord)transaction.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite, false);
    Entity entity = new Line(new Point3d(12, 5, 0), new Point3d(15, 12, 0));
    modelSpace.AppendEntity(entity);
    transaction.AddNewlyCreatedDBObject(entity, true);

    AssocPersSubentityIdPE subentityIdPE;
    RXClass protocolClass = AssocPersSubentityIdPE.GetClass(typeof(AssocPersSubentityIdPE));
    IntPtr pSubentityIdPE = entity.QueryX(protocolClass);
    if (pSubentityIdPE == IntPtr.Zero)
    {
        return;
    }
    subentityIdPE = AssocPersSubentityIdPE.Create(pSubentityIdPE, false) as AssocPersSubentityIdPE;
    if (subentityIdPE == null)
    {
      return;
    }
    // Now we have the PE, we query the subentities
    // First we retrieve a list of all edges (a line has one edge)
    SubentityId[] edgeSubentityIds = null;
    edgeSubentityIds = subentityIdPE.GetAllSubentities(entity, SubentityType.Edge);
    SubentityId test = edgeSubentityIds[0];
    SubentityId startSID = SubentityId.Null;
    // Now we retrieve the vertices associated with the first edge in our array.
    // In this case we have one edge, and the edge has three vertices - start, end and middle.
    SubentityId endSID = SubentityId.Null;
    SubentityId[] other = null;

//****** This next line is the offender ********
    subentityIdPE.GetEdgeVertexSubentities(entity, test, ref startSID, ref endSID, ref other);
//************************************************

    // The PE returns a SubEntId. We want a FullSubentityPath
    FullSubentityPath subentPathEdge = new FullSubentityPath(new ObjectId[1] { entity.ObjectId }, edgeSubentityIds[0]); // The line edge
    FullSubentityPath subentPath1 = new FullSubentityPath(new ObjectId[1] { entity.ObjectId }, startSID); // The edge's startpoint.

    // We call a helper function to retrieve or create a constraints group
    ObjectId constraintGroupID = getConstraintGroup(true);
    using (Assoc2dConstraintGroup constraintGroup = (Assoc2dConstraintGroup)transaction.GetObject(constraintGroupID, OpenMode.ForWrite, false))
    {
      // Pass in geometry to constrain (the line edge)
      ConstrainedGeometry constraintedGeometry = constraintGroup.AddConstrainedGeometry(subentPathEdge);
      // Now create the constraint, a Fixed constraint applied to the line's startpoint.
      FullSubentityPath[] paths = new FullSubentityPath[1] { subentPath1 };
      GeometricalConstraint newConstraint = constraintGroup.AddGeometricalConstraint(GeometricalConstraint.ConstraintType.Fix, paths);
    }

    // Evaluate the network to update the parameters of the constrained geometry
    String temp = "";
    ObjectId networkId = AssocNetwork.GetInstanceFromDatabase(db, true, temp);
    using (AssocNetwork network = (AssocNetwork)transaction.GetObject(networkId, OpenMode.ForWrite, false))
    {
      AssocEvaluationCallback callBack = null;
      network.Evaluate(callBack);
    }
    transaction.Commit();
  }
}

要运行该命令,您还需要此辅助方法。下面的代码没有已知问题,只需复制粘贴即可。

// Helper function to retrieve (or create) constraint group
internal static ObjectId getConstraintGroup(bool createIfDoesNotExist)
{
    // Calculate the current plane on which new entities are added by the editor
    // (A combination of UCS and ELEVATION sysvar).
    Editor editor = Application.DocumentManager.MdiActiveDocument.Editor;
    Matrix3d ucsMatrix = editor.CurrentUserCoordinateSystem;
    Point3d origin = ucsMatrix.CoordinateSystem3d.Origin;
    Vector3d xAxis = ucsMatrix.CoordinateSystem3d.Xaxis;
    Vector3d yAxis = ucsMatrix.CoordinateSystem3d.Yaxis;
    Vector3d zAxis = ucsMatrix.CoordinateSystem3d.Zaxis;
    origin = origin + Convert.ToDouble(Application.GetSystemVariable("ELEVATION")) * zAxis;
    Plane currentPlane = new Plane(origin, xAxis, yAxis);

    // get the constraint group from block table record
    ObjectId ret = ObjectId.Null;
    Database database = HostApplicationServices.WorkingDatabase;
    ObjectId networkId = AssocNetwork.GetInstanceFromObject(SymbolUtilityServices.GetBlockModelSpaceId(database), createIfDoesNotExist, true, "");
    if (!networkId.IsNull)
    {
        // Try to find the constraint group in the associative network
        using (Transaction transaction = database.TransactionManager.StartTransaction())
        {
            using (AssocNetwork network = transaction.GetObject(networkId, OpenMode.ForRead, false) as AssocNetwork)
            {
                if (network != null)
                {
                    // Iterate all actions in network to find Assoc2dConstraintGroups
                    ObjectIdCollection actionsInNetwork = network.GetActions;
                    for (int nCount = 0; nCount <= actionsInNetwork.Count - 1; nCount++)
                    {
                        ObjectId idAction = actionsInNetwork[nCount];
                        if (idAction == ObjectId.Null)
                        {
                            continue;
                        }

                        // Is this action a type of Assoc2dConstraintGroup?
                        if (idAction.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(Assoc2dConstraintGroup))))
                        {
                            using (AssocAction action = (AssocAction)transaction.GetObject(idAction, OpenMode.ForRead, false))
                            { 
                                if (action == null)
                                {
                                    continue;
                                }

                                Assoc2dConstraintGroup constGrp = action as Assoc2dConstraintGroup;
                                // Is this the Assoc2dConstraintGroup for our plane of interest?
                                if (constGrp.WorkPlane.IsCoplanarTo(currentPlane))
                                {
                                    // If it is then we've found an existing constraint group we can use.
                                    ret = idAction;
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            // If we get to here, a suitable contraint group doesn't exist, create a new one if that's what calling fn wanted.
            if (ret.IsNull && createIfDoesNotExist)
            {
                using (AssocNetwork network = (AssocNetwork)transaction.GetObject(networkId, OpenMode.ForWrite, false))
                {
                    // Create  construction plane
                    Plane constraintPlane = new Plane(currentPlane);
                    // If model extent is far far away from origin then we need to shift
                    // construction plane origin within the model extent.
                    // (Use Pextmin, PExtmax in paper space)
                    Point3d extmin = database.Extmin;
                    Point3d extmax = database.Extmax;
                    if (extmin.GetAsVector().Length > 100000000.0)
                    {
                        Point3d originL = extmin + (extmax - extmin) / 2.0;
                        PointOnSurface result = currentPlane.GetClosestPointTo(originL);
                        constraintPlane.Set(result.GetPoint(), currentPlane.Normal);
                    }
                    // Create the new constraint group and add it to the associative network.
                    using (Assoc2dConstraintGroup constGrp = new Assoc2dConstraintGroup(constraintPlane))
                    {
                        ret = database.AddDBObject(constGrp);
                    }
                    network.AddAction(ret, true);
                }
            }
            transaction.Commit();
        }
    }
    return ret;
}

【问题讨论】:

    标签: c# autocad autocad-plugin


    【解决方案1】:

    (我想将此添加为评论,但我还没有资格发表评论) 我认为这与您的 Visual Studio 设置有关。我的建议是仔细检查属性-> 调试。我的一个加载项有类似的问题,在我添加工作目录并在调试设置中修复命令行参数后,它开始按预期工作。

    【讨论】:

    • 感谢您的建议。我多年来一直在开发这个项目,这是我第一次看到这个。不知何故,我怀疑这是问题所在,但在这一点上,我愿意尝试任何事情。您能否更具体地说明“我在调试设置中添加了工作目录并修复了命令行参数”的含义。
    • 顺便说一句,我尝试在没有附加调试器的情况下运行发布版本。效果一样。
    • 所以在你的调试设置中应该如下: 1. 启动外部程序:C:\Program Files\Autodesk\AutoCAD 2018\acad.exe 2. 命令行参数:/ld "C:\ Program Files\Autodesk\AutoCAD 2018\\AecBase.dbx" /p ">" 3. 工作目录:C:\Program Files\Autodesk\AutoCAD 2018\UserDataCache\ 。一旦我将设置更改为高于我消失的类似错误。
    • 谢谢,但似乎不是这样。还是一样的崩溃。
    猜你喜欢
    • 1970-01-01
    • 2013-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多