C# 从现有的.NET应用程序启动AutoCAD 2013并写入窗口

C# 从现有的.NET应用程序启动AutoCAD 2013并写入窗口,c#,.net,dll,managed,autocad,C#,.net,Dll,Managed,Autocad,我正在尝试从现有的C#桌面应用程序启动AutoCAD 2013,使用数据库值绘制图表,然后将图形作为变量位数组(varbyte)保存到数据库中。除了将坐标输入现有的AutoCAD编辑器窗口外,我在所有方面都取得了很好的成功 我尝试了NETLOAD,但无法通过命令行放置55个以上AutoCAD数据库圆形对象的列表。尝试通过COM互操作传递对象时遇到了失败,并对AutoCAD和我的应用程序的32位与64位状态产生了混淆。虽然这个网站很有帮助,但我还没能完成我想做的事情 如有任何建议,将不胜感激。谢谢

我正在尝试从现有的C#桌面应用程序启动AutoCAD 2013,使用数据库值绘制图表,然后将图形作为变量位数组(varbyte)保存到数据库中。除了将坐标输入现有的AutoCAD编辑器窗口外,我在所有方面都取得了很好的成功

我尝试了NETLOAD,但无法通过命令行放置55个以上AutoCAD数据库圆形对象的列表。尝试通过COM互操作传递对象时遇到了失败,并对AutoCAD和我的应用程序的32位与64位状态产生了混淆。虽然这个网站很有帮助,但我还没能完成我想做的事情

如有任何建议,将不胜感激。谢谢

编辑:

我采纳了Locke的建议,在.NETDLL中添加了函数,以基于简单参数(如X、Y坐标、半径、标签等)绘制单个项。以下是方法签名的外观:

[CommandMethod("DrawSmallCircle", CommandFlags.Session)]
public static void DrawSmallCircle(double x, double y, double aRadius, string aGuage, string aLabel, string aTitle)
在网络加载承载上述方法(及其包含的类)的.dll之后,我对实例化的interop AcadApplication使用SendCommand,如下所示:

acApp.ActiveDocument.SendCommand("DrawSmallCircle " +
circ.circle.Center.X.ToString() + ", " +
circ.circle.Center.Y.ToString() + ", " +
circ.circle.Radius.ToString() + ", " +
circ.guage + ", " +
circ.label + ", " +
circ.title + " "
);
不幸的是,我在响应中得到的错误只是“公共语言运行库检测到一个无效程序”

我不确定在我的.dll中注册命令是否有用,因为据称,“命令方法不能接受参数,但LispFunction可以。”


好的,您遇到了互操作/进程内自动化问题。传统上,AutoCAD不希望进程外模块与进程内模块对话,至少在来回发送参数的情况下是这样。涉及注册进程内COM接口的正式方法很难正确运行,尤其是在x64位的环境中。我还没有看到它在多台计算机上表现出一致性,因此我倾向于默认使用以下方法

您是正确的,带有[CommandMethod]标志的方法不能接受参数,所以它们显然需要是空的。在运行时向其发送参数上下文的技巧是在定义的方法本身中包含参数提示。想象一下,您正在开发用户在AutoCAD中调用的命令,在命令继续执行之前,系统会提示用户输入每一条数据。与其他原生AutoCAD命令类似,参数数据可以在调用命令的同时以单个字符串发送

例如:
(命令“.\u CIRCLE”“0,0”“5”)您能否对此语句进行一点扩展:“除了将坐标输入现有AutoCAD编辑器窗口之外,我在所有方面都取得了很好的成功。”?我认为将内部定义的dll结构化为一次运行一个项目可能会对您有所帮助。正如您所经历的,将互操作列表传递到进程中是很棘手的,尤其是当比特数不同时。对我来说,interop应用程序在列表中循环,并将每个项目的参数一次一个地发送到已定义的命令是有意义的。现在我有了一些背景知识,我可以把一些东西拼凑起来。一旦我回到家,我就可以打字了。众所周知,我不擅长用手机写东西。你在这里找到工作了吗?
[CommandMethod("DRAWDBCIRCLE")]
public void DrawDbCircle()
{
    var acDb = HostApplicationServices.WorkingDatabase;
    var acEd = Application.DocumentManager.MdiActiveDocument.Editor;

    using (var acTrans = acDb.TransactionManager.StartOpenCloseTransaction())
    {
        var bt = (BlockTable)acTrans.GetObject(acDb.BlockTableId, OpenMode.ForWrite);
        var btr = (BlockTableRecord)acTrans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

        Point3d centerPoint;
        double radius;
        string gauge, label, title;

        // Prompt for the centerpoint
        var pointResult = acEd.GetPoint("ENTER CIRCLE ORIGIN: \n");
        centerPoint = pointResult.Value;

        // Prompt for the radius
        var doubleResult = acEd.GetDouble("ENTER CIRCLE RADIUS: \n");
        radius = doubleResult.Value;

        // Prompt for the strings
        var stringResult = acEd.GetString("ENTER CIRCLE GAUGE: \n");
        gauge = stringResult.StringResult;
        stringResult = acEd.GetString("ENTER CIRCLE LABEL: \n");
        label = stringResult.StringResult;
        stringResult = acEd.GetString("ENTER CIRCLE TITLE: \n");
        title = stringResult.StringResult;

        // Create the circle
        var circ = new Circle(centerPoint, Vector3d.ZAxis, radius);
        // <-- Add code for dealing with strings -->
        btr.AppendEntity(circ);
        acTrans.AddNewlyCreatedDBObject(circ, true);

        acTrans.Commit();
    }
}
private AcadApplication acApp;
private AcadDocument acDoc;

private void btnRun_Click(object sender, EventArgs e)
{
    if (acApp == null) return;
    acDoc = acApp.ActiveDocument;

    foreach (DataRow row in circleTable.Rows)
        DrawDatabaseCircle(row);
}

private void DrawDatabaseCircle(DataRow circRow)
{
    var cmdFormat = string.Format("\"{0},{1}\" \"{2}\" \"{3}\" \"{4}\" \"{5}\"", circRow.ItemArray);
    acDoc.SendCommand(string.Format("(Command \"DRAWDBCIRCLE\" {0})\n", cmdFormat));
}