December 2014

Sun Mon Tue Wed Thu Fri Sat
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      










« Creating an AutoCAD Wipeout using .NET | Main | Getting AutoCAD's current directory from a .NET application »

December 14, 2007

Launching AutoCAD from a .NET application

This topic has been raised a few times, and Adam Nagy, from our DevTech EMEA team, sent a technical response recently with code that I decided to use as the basis for this post.

Developers typically want to either integrate functionality into AutoCAD (using its plug-in architecture to add commands, user-interface elements, objects, etc.), or to drive it, automating common tasks. Clearly the line can get blurred between these two areas, but today I’m going to focus on the second category.

To help with later explanations, I’d like to introduce two types of application interaction:

Out-of-process

In this situation we have two separate executables trying to communicate. Imagine you have an EXE and you want to drive AutoCAD. You need to find some way to launch AutoCAD and communicate with it – typically using COM or, before that, DDE. The communication is, by definition, done via Inter-Process Communication (IPC), which is a very inefficient way to send large chunks of data. This is why old ADS and external VB applications ran (or run) so slowly.

In-process

When your code is packaged inside a DLL (whether an ActiveX DLL defined in VB6, an ObjectARX module or a .NET assembly), the communication with the host process (AutoCAD) is much more efficient – data structures can be passed by pointer or reference rather than squirting the information through the inefficient marshalling of IPC.

Most of AutoCAD’s current APIs are designed to be used “in-process” – this includes LISP, ObjectARX and AutoCAD’s .NET API. Given the availability of .NET Remoting, people often hope or expect AutoCAD to be drivable via .NET “out-of-process”, but this is not how the managed API was designed: it is really a wrapper on top of ObjectARX, whose performance is based on direct access to objects via pointers, and this simply does not extend to work across process boundaries. One of the great features of COM Automation is that it was designed to work either out-of-process (from an external EXE) or in-process (from VBA or by calling GetInterfaceObject() to load a VB6 ActiveX DLL). This is still the best way to drive AutoCAD from an external executable.

I generally recommend not trying to pass too much information across the process boundary: if you need to drive AutoCAD from an external executable, simply launch it (or connect to a running instance, if that’s an option) and then load an in-process module to do the heavy lifting from within AutoCAD’s process space.

The following code shows how to do just that, using C#. It tries to connect to a running instance of AutoCAD (this is optional – you can easily adjust the code only to launch AutoCAD), and failing that launches it. Once there’s a running instance we make it visible and run a custom command. My recommendation is to set up demand-loading for your application – either to load it on AutoCAD startup or when a command is invoked – and then to run a command defined in your module.

You will need to add a reference to the “AutoCAD Type Library” from your application, as well as including these assembly references:

using System;

using System.Runtime.InteropServices;

using Autodesk.AutoCAD.Interop;

This C# code can be added to an “on-click” event handler for a button (for example) or another function that makes sense in the context of your application.

  // "AutoCAD.Application.17" uses 2007 or 2008,

  //  whichever was most recently run


  // "AutoCAD.Application.17.1" uses 2008, specifically


  const string progID = "AutoCAD.Application.17.1";


  AcadApplication acApp = null;

  try

  {

    acApp =

      (AcadApplication)Marshal.GetActiveObject(progID);

  }

  catch

  {

    try

    {

      Type acType =

        Type.GetTypeFromProgID(progID);

      acApp =

        (AcadApplication)Activator.CreateInstance(

          acType,

          true

        );

    }

    catch

    {

      MessageBox.Show(

        "Cannot create object of type \"" +

        progID + "\""

      );

    }

  }

  if (acApp != null)

  {

    // By the time this is reached AutoCAD is fully

    // functional and can be interacted with through code

    acApp.Visible = true;

    acApp.ActiveDocument.SendCommand("_MYCOMMAND ");

  }

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/services/trackback/6a00d83452464869e200e54fb759508834

Listed below are links to weblogs that reference Launching AutoCAD from a .NET application:

blog comments powered by Disqus

Feed/Share

10 Random Posts