The AutoCAD Engineering first prototyped a "managed" (for "managed" read ".NET") API for AutoCAD 2004. It was pretty revolutionary stuff at the time - a mixed-mode DLL was created to expose the managed interface and marshall these calls through to "unmanaged" ObjectARX calls. There were a number of reasons .NET was - and remains - very interesting for developers...

.NET provides the ease of development previously available only (or at least primarily) to Visual Basic clients through COM. You can make use of COM or .NET components in your project, but generate simple client code using more evolved programming languages (even VB.NET is really a much more evolved language than VB6, in terms of its intrinsic capabilities).

A key benefit for Autodesk was the ability to map more complex datatypes (such as those defined in ObjectARX) to a managed API. When designing a COM API you are more limited - you can use certain basic types or beyond that define more complex interfaces based on IDispatch, but these come with a substantial design and development overhead: it is laborious to expose COM Automation interfaces for complex C++ classes. With .NET things were different... the consistency of the design of ObjectARX provided us with the capability to automate this to a great extent, generating code semi-automatically from our internal API definition database (which is the same one used to generate our API reference material for both ObjectARX and the managed API for AutoCAD).

For some initial pointers around using the .NET API to AutoCAD, check out the AutoCAD Developer Center - as mentioned previously the Labs are a great place to start. In my next few posts I'll talk about the basic structure of a simple .NET application for AutoCAD, and eventually how to harness the existing COM and unmanaged ObjectARX APIs through COM Interop and P/Invoke respectively.

8 responses to “.NET and AutoCAD”

  1. Hi, Kean.I got some problems when linking a entity to another application's object with the property of objectId.
    When i get the ObjectId from the application's eventHandler, the GetObject() doesn't funtion with the parameter OpenMode.ForWrite, while the use of OpenMode.ForRead is available. the exception is an eLockviolation.
    Do you have any idea with it? Thanks.

  2. Omar Martínez Avatar
    Omar Martínez

    Hi Kean,

    I'm Omar Martinez. I am in a delveloping team that must add new functionalities to AutoCAD.

    We are working with Microsoft Visual C# 2005 Express, Autocad LT 2009 and ObjectARX SDK 2009. We have tried to load our new commands into de AutoCAD, but never works. We have got the same error.

    Can't charge the assembly. Error details:
    System.Security.SecurityException: Security Error in Autodesk.AutoCAD.ApplicationServices.ExtensionLoader.ProcessAssembly(Assembly assembly)
    The assembly zone got this error:
    MyComputer

    We don't know to do. Can you help us?

    Thanks for all,

    Regards,
    Omar Martinez

  3. Kean Walmsley Avatar

    Hi Omar,

    AutoCAD LT is designed not to load external applications.

    Regards,

    Kean

  4. Omar Martínez Avatar

    Thanks Kean,

    then if we want to load external applications, we'll need Autocad complet version.

    Regards,
    Omar

  5. Hartmut Callies Avatar
    Hartmut Callies

    Hi Kean,
    I write a VB.net program (a standalone program) that create new drawings with autocad 2007. Is COM the only solution, that I can access from my program to autocad?
    Which references I need in VS 2008?

    Regards,
    Hartmut

  6. Kean Walmsley Avatar

    Hi Hartmut,

    COM is really the best way to do this (it may still be possible to use DDE but I haven't tried that in many years).

    You'll need to reference the AutoCAD 2007 Type Library (I forget the exact wording).

    Regards,

    Kean

  7. Prasad sumanasekara Avatar
    Prasad sumanasekara

    hello Kean,
    this method has same locking probloms "locking vierlation" what is the wrong.
    #region Create Block

    public String CreateBlockDefinition()
    {
    try
    {

    string strTemplatePath = "acad.dwt";
    DocumentCollection acDocMgr = AcadApp.DocumentManager;
    Document acDoc = acDocMgr.Add(strTemplatePath);

    //The return value for this function
    AcDb.ObjectId newBtrId = new AcDb.ObjectId();

    AcDb.Database db = acDoc.Database; //save some space
    AcDb.HostApplicationServices.WorkingDatabase = db;

    using (AcDb.Transaction trans =
    db.TransactionManager.StartTransaction())
    {

    AcDb.BlockTable bt = (AcDb.BlockTable)trans.GetObject(db.BlockTableId,
    AcDb.OpenMode.ForWrite);
    if ((bt.Has("TestBlock")))
    {
    newBtrId = bt["TestBlock"];
    }
    else
    {

    AcDb.Solid3d acSol3DBox1 = new AcDb.Solid3d();
    AcDb.Solid3d acSol3DBox2 = new AcDb.Solid3d();
    AcDb.Solid3d acSol3DBox3 = new AcDb.Solid3d();
    AcDb.Solid3d acSol3DCy2 = new AcDb.Solid3d();

    acSol3DBox1.SetDatabaseDefaults();
    acSol3DBox2.SetDatabaseDefaults();
    acSol3DBox3.SetDatabaseDefaults();
    acSol3DCy2.SetDatabaseDefaults();

    acSol3DBox1.CreateBox(400, 400, 300);
    acSol3DBox2.CreateBox(450, 450, 50);
    acSol3DBox3.CreateBox(100, 75, 75);
    acSol3DCy2.CreateFrustum(125, 50, 50, 50);

    AcGeo.Vector3d centerBox1 = new AcGeo.Vector3d(0,
    0, 275); // convenient declaration...
    AcGeo.Vector3d centerBox2 = new AcGeo.Vector3d(0,
    0, -25); // convenient declaration...
    AcGeo.Vector3d centerBox3 = new AcGeo.Vector3d(-250,
    0, 250); // convenient declaration...
    AcGeo.Vector3d centerCy2 = new AcGeo.Vector3d(0, 0,
    62.5); // convenient declaration...

    AcGeo.Point3d center = new AcGeo.Point3d(0, 0,
    0); // convenient declaration...

    acSol3DBox1.TransformBy(AcGeo.Matrix3d.Displacement(centerBox1));
    acSol3DBox2.TransformBy(AcGeo.Matrix3d.Displacement(centerBox2));
    acSol3DBox3.TransformBy(AcGeo.Matrix3d.Displacement(centerBox3));
    acSol3DCy2.TransformBy(AcGeo.Matrix3d.Displacement(centerCy2));

    //Create a new block definition called EmployeeBlock
    AcDb.BlockTableRecord newBtr = new AcDb.BlockTableRecord();
    newBtr.Name = "TestBlock";
    //Add the block, and set the id as the return value of our function
    newBtrId = bt.Add(newBtr);
    //Let the transaction know about any object/entity you add to the database!
    newBtr.Origin = center;
    trans.AddNewlyCreatedDBObject(newBtr, true);
    newBtr.AppendEntity(acSol3DBox1); //Append our entities...
    newBtr.AppendEntity(acSol3DBox2); //Append our entities...
    newBtr.AppendEntity(acSol3DBox3); //Append our entities...
    newBtr.AppendEntity(acSol3DCy2); //Append our entities...

    trans.AddNewlyCreatedDBObject(acSol3DBox1, true);
    //Again, let the transaction know about our newly added entities.
    trans.AddNewlyCreatedDBObject(acSol3DBox2, true);
    //Again, let the transaction know about our newly added entities.
    trans.AddNewlyCreatedDBObject(acSol3DBox3, true);
    //Again, let the transaction know about our newly added entities.
    trans.AddNewlyCreatedDBObject(acSol3DCy2, true);
    //Again, let the transaction know about our newly added entities.

    }
    trans.Commit(); //All done, no errors? Go ahead and commit!
    string strDWGName = acDoc.Name;
    object obj = AcadApp.GetSystemVariable("DWGTITLED");

    if (System.Convert.ToInt16(obj) == 0)
    {
    // If the drawing is using a default name (Drawing1, Drawing2, etc)
    // then provide a new name
    strDWGName = "C:\\Test\\Test.dwg";
    }
    acDoc.CloseAndSave(strDWGName);
    }
    return "TestBlock";
    }
    catch (System.Exception ex)
    {
    Debug.Write(String.Format("\nCaught the following Exception:{0}",
    ex.ToString()));
    return "";
    }
    }
    #endregion

    thnak you
    Prasad.

  8. Hello Prasad,

    This isn't a forum for support.

    Your comment doesn't appear to relate to this post, so please submit your question to the ADN team, if you're a member, or otherwise the AutoCAD .NET Discussion Group.

    Kean

Leave a Reply to Kean Walmsley Cancel reply

Your email address will not be published. Required fields are marked *