How can I open AutoCAD 2015 through the .NET API

我的梦境 提交于 2019-11-28 10:02:21

The issue is you're coding (correctly) to the AutoCAD interop interface. I recommend against that (due to potential version changes).

The other issue is that the documentation for AutoCAD plugins using the newer .net api is for plugins when AutoCAD is already running.

Final issue could be that the program Id of AutCAD is a mystery. I have resorted to making that a configurable setting, but default to "AutoCAD.Application", which will take the currently registered AutoCAD.Application on the production machine. If there are multiple versions installed on the machine and you want to be specific, then you could append the version number (which you'll need to research) to the ProgID like: "AutoCAD.Application.19", or "AutoCAD.Application.20" for 2015.

For the first issue, one technique is to use dynamics for the autoCad objects, particularly for creating instances. I have used the ObjectARX api for creating my application in a dummy project, and then switching to dynamics when I'm happy with the properties and method names.

In a standalone .Net application that starts AutoCAD you could use something like:

// 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);
        }
    }
}

When there are several versions of AutoCAD installed on a computer, creating an instance with the ProgID "AutoCAD.Application" will run the latest version started on this computer by the current user. If the version of the Interop assemblies used does not match the version that is starting, you'll get a System.InvalidCastException with an HRESULT 0x80004002 (E_NOINTERFACE).

In your specific case, the {070AA05D-DFC1-4E64-8379-432269B48B07} IID in your error message is the GUID for the AcadApplicationinterface in R19 64-bit (AutoCAD 2013 & 2014). So there is an AutoCAD 2013 or 2014 that is starting, and you cannot cast this COM object to a 2015 type because 2015 is R20 (not binary compatible).

To avoid that, you can add a specific version to your ProgID (like "AutoCAD.Application.20" for AutoCAD 2015 (R20.0) to 2016 (R20.1)) to start the version matching your Interop assemblies or you can use late binding (eg. remove your references to Autodesk.AutoCAD.Interop* and use the dynamic keyword instead of the AutoCAD types).

In the last case, you will lost autocompletion, but your program will work with all the versions of AutoCAD.

Check also 32-bit vs 64-bit because TypeLib/Interop assemblies are not the same.

I open the application in a much straight-forward way. First, be sure to reference the correct type library. The one I am using is AutoCAD 2014 Type Library, located at: c:\program files\common files\autodesk shared\acax19enu.tlb

To initialize the application:

using AutoCAD;

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

        app = new AcadApplication();

        app.Visible = true;

        Console.Read();
    }
}
}

Try this:


"sourcefile" is the original file
"newfile" is the new file

[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);
    }
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

        }
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!