【问题标题】:How can I open AutoCAD 2015 through the .NET API如何通过 .NET API 打开 AutoCAD 2015
【发布时间】:2014-08-14 21:53:49
【问题描述】:

我已经浏览了一个小时,但还没有找到可以对此有所帮助的东西。我正在使用 C# 从 VS2013 中的 .NET API 打开 AutoCAD,但由于某种原因,我永远无法真正启动 AutoCAD。我正在使用以下代码:

using System;
using System.Runtime.InteropServices;

using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;

namespace IOAutoCADHandler
{
    public static class ACADDocumentManagement
    {
        [CommandMethod("ConnectToAcad")]
        public static void ConnectToAcad()
        {

            AcadApplication acAppComObj = null;
            // no version number so it will run with any version
            const string strProgId = "AutoCAD.Application";

            // Get a running instance of AutoCAD
            try
            {
                acAppComObj = (AcadApplication)Marshal.GetActiveObject(strProgId);
            }
            catch // An error occurs if no instance is running
            {
                try
                {
                    // Create a new instance of AutoCAD
                    acAppComObj = (AcadApplication)Activator.CreateInstance(Type.GetTypeFromProgID(strProgId), true);
                }
                catch   //// STOPS HERE
                {
                    // If an instance of AutoCAD is not created then message and exit
                    // NOTE: always shows this box and never opens AutoCAD
                    System.Windows.Forms.MessageBox.Show("Instance of 'AutoCAD.Application'" +
                                                         " could not be created.");

                    return;
                }
            }

            // Display the application and return the name and version
            acAppComObj.Visible = true;
            System.Windows.Forms.MessageBox.Show("Now running " + acAppComObj.Name +
                                                 " version " + acAppComObj.Version);

            // Get the active document
            AcadDocument acDocComObj;
            acDocComObj = acAppComObj.ActiveDocument;

            // Optionally, load your assembly and start your command or if your assembly
            // is demandloaded, simply start the command of your in-process assembly.
            acDocComObj.SendCommand("(command " + (char)34 + "NETLOAD" + (char)34 + " " +
                                    (char)34 + @"C:\Users\Administrator\Documents\All Code\main-libraries\IOAutoCADHandler\bin\Debug\IOAutoCADHandler.dll" + (char)34 + ") ");

            acDocComObj.SendCommand("DRAWCOMPONENT");
        }
    }

不幸的是,它总是在嵌套的catch 语句处停止,并且总是在不打开 AutoCAD 的情况下显示弹出框。关于如何至少让 AutoCAD 为我打开的任何建议?

编辑:错误消息

【问题讨论】:

  • 您对确切的问题不是很准确。无论如何,有几个建议:将“catch”语句更改为“catch (Exception e1)”和“catch (Exception e2)”。在 Visual Studio 调试器下运行程序,并在每个 catch 子句的第一条语句上放置断点。当异常被捕获时,你应该能够看到异常的确切类型,这应该(希望)给你一些线索。
  • @RenniePet 是的,意识到这一点并包含错误输出。
  • 您是否将其作为 NETLOADed DLL 运行?如果是,那么 Application 对象是 Autodesk.AutoCAD.ApplicationServices.Application 如果不是,那么 [CommandMethod("ConnectToAcad")] 属性会让我们感到困惑。
  • 我是 CAD 专家,你为什么要把进程内和互操作混在一起?如果需要,您可以将两者放在同一个程序集中,但我会将它们排除在相同的类和命名空间之外。
  • 检查这个常见的新手错误:所有 AutoCAD 参考都需要将“本地复制”设置为 false。我们都做到了。

标签: c# .net visual-studio-2013 autocad


【解决方案1】:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace Tekkit
{
    class Program
    {
        static void Main(string[] args)
        {

                //make sure to add last 2 using statements
                ProcessStartInfo start = new ProcessStartInfo("calc.exe");                              
                Process.Start(start);//starts the process

        }
    }
}

【讨论】:

  • 是的...但是之后从正在运行的实例中获取自动化对象并非易事(需要反复遍历全局对象表,直到出现您要查找的内容)。您还缺少通过在注册表中查找其 LocalServer32 键来获取进程路径的代码。以及 DCOM 远程处理服务器在通过 COM 以正常方式启动时传递给应用程序的 -Embedding 标志。
  • 比遍历表更糟糕的是,ROT 只注册第一个启动的实例。因此,如果您打开了多个会话,您将只能使用第一个会话,到那时谁知道是哪个会话。我实际上在我的一个产品中使用了它,但是如果一个会话已经打开或者有多个会话打开,我会提示用户并从那里开始。我不玩游戏。
【解决方案2】:

我以非常直接的方式打开应用程序。首先,一定要引用正确的类型库。我使用的是 AutoCAD 2014 类型库,位于: c:\program files\common files\autodesk shared\acax19enu.tlb

初始化应用程序:

using AutoCAD;

namespace test
{
class Program
{
    static void Main(string[] args)
    {
        AutoCAD.AcadApplication app;

        app = new AcadApplication();

        app.Visible = true;

        Console.Read();
    }
}
}

【讨论】:

    【解决方案3】:

    问题是您正在(正确地)编码到 AutoCAD 互操作界面。我建议不要这样做(由于潜在的版本更改)。

    另一个问题是使用较新的 .net api 的 AutoCAD 插件的文档适用于 AutoCAD 已经运行时的插件。

    最后一个问题可能是 AutCAD 的程序 ID 是个谜。我已将其设为可配置设置,但默认为“AutoCAD.Application”,它将在生产机器上采用当前注册的 AutoCAD.Application。如果机器上安装了多个版本并且您想要具体,那么您可以将版本号(您需要研究)附加到 ProgID,例如:“AutoCAD.Application.19”或“AutoCAD.Application .20" 为 2015 年。

    对于第一个问题,一种技术是对 autoCad 对象使用动力学,特别是在创建实例时。我使用 ObjectARX api 在一个虚拟项目中创建我的应用程序,然后当我对属性和方法名称感到满意时切换到动态。

    在启动 AutoCAD 的独立 .Net 应用程序中,您可以使用以下内容:

    // I comment these out in production
    //using Autodesk.AutoCAD.Interop;
    //using Autodesk.AutoCAD.Interop.Common;
    //...
    //private static AcadApplication _application;
    private static dynamic _application;
    static string _autocadClassId = "AutoCAD.Application";
    
    private static void GetAutoCAD()
    {
        _application = Marshal.GetActiveObject(_autocadClassId);
    }
    
    private static void StartAutoCad()
    {
        var t = Type.GetTypeFromProgID(_autocadClassId, true);
        // Create a new instance Autocad.
        var obj = Activator.CreateInstance(t, true);
        // No need for casting with dynamics
        _application = obj;
    }
    
    public static void EnsureAutoCadIsRunning(string classId)
    {
        if (!string.IsNullOrEmpty(classId) && classId != _autocadClassId)
            _autocadClassId = classId;
        Log.Activity("Loading Autocad: {0}", _autocadClassId);
        if (_application == null)
        {
            try
            {
                GetAutoCAD();
            }
            catch (COMException ex)
            {
                try
                {
                    StartAutoCad();
                }
                catch (Exception e2x)
                {
                    Log.Error(e2x);
                    ThrowComException(ex);
                }
            }
            catch (Exception ex)
            {
                ThrowComException(ex);
            }
        }
    }
    

    【讨论】:

      【解决方案4】:

      当计算机上安装了多个版本的 AutoCAD 时,使用 ProgID“AutoCAD.Application”创建实例将运行当前用户在此计算机上启动的最新版本。如果使用的互操作程序集的版本与正在启动的版本不匹配,您将收到带有 HRESULT 0x80004002 (E_NOINTERFACE) 的 System.InvalidCastException。

      在您的具体情况下,错误消息中的 {070AA05D-DFC1-4E64-8379-432269B48B07} IID 是 R19 64 位(AutoCAD 2013 和 2014)中 AcadApplicationinterface 的 GUID。所以有一个 AutoCAD 2013 或 2014 正在启动,并且您不能将此 COM 对象转换为 2015 类型,因为 2015 是 R20(不兼容二进制)。

      为避免这种情况,您可以将特定版本添加到 ProgID(例如 AutoCAD 2015 (R20.0) 到 2016 (R20.1) 的“AutoCAD.Application.20”)以启动与您的互操作程序集匹配的版本或您可以使用后期绑定(例如,删除对 Autodesk.AutoCAD.Interop* 的引用并使用 dynamic 关键字而不是 AutoCAD 类型)。

      在最后一种情况下,您将失去自动完成功能,但您的程序将适用于所有版本的 AutoCAD。

      还要检查 32 位和 64 位,因为 TypeLib/Interop 程序集不一样。

      【讨论】:

        【解决方案5】:

        试试这个:


        “sourcefile”是原始文件
        “newfile”是新文件

        [CommandMethod("ModifyAndSaveas", CommandFlags.Redraw | CommandFlags.Session)]
            public void ModifyAndSaveAs()
            {
                Document acDoc = Application.DocumentManager.Open(sourcefile);
                Database acDB = acDoc.Database;
        
                Transaction AcTran = acDoc.Database.TransactionManager.StartTransaction();
                using (DocumentLock acLckDoc = acDoc.LockDocument())
                {
                    using (AcTran)
                    {
                        BlockTable acBLT = (BlockTable)AcTran.GetObject(acDB.BlockTableId, OpenMode.ForRead);
                        BlockTableRecord acBLTR = (BlockTableRecord)AcTran.GetObject(acBLT[BlockTableRecord.ModelSpace], OpenMode.ForRead);
                        var editor = acDoc.Editor;                  
        
                        var SelectionSet = editor.SelectAll().Value;
                        foreach (ObjectId id in SelectionSet.GetObjectIds())
                        {
                            Entity ent = AcTran.GetObject(id, OpenMode.ForRead) as Entity;
        
                            //modify entities 
        
                        }
        
                        AcTran.Commit();
        
                    }
                }
                acDB.SaveAs(newfile, DwgVersion.AC1021);
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-03-01
          • 2013-08-17
          • 1970-01-01
          • 2012-06-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-03-15
          相关资源
          最近更新 更多