Replacing AutoCAD's OPEN command using .NET

This very good question came in by email from Patrick Nikoletich:

I was wondering what the preferred method for overriding the default "Open" common dialog in AutoCAD 2007 would be? I can catch the event but can't send AutoCAD a command to cancel the request so I can launch my Win Form instead.

This is quite a common requirement - especially for people integrating document management systems with AutoCAD.

The simplest way to accomplish this - and this technique goes back a bit - is to undefine the OPEN command, replacing it with your own implementation. The classic way to do this from LISP was to use the (command) function to call the UNDEFINE command on OPEN, and then use (defun) to implement your own (c:open) function.

This technique can be adapted for use with .NET. The following C# code calls the UNDEFINE command in its initialization and then implements an OPEN command of its own.

A few notes on the implementation:

  • I'm using the COM SendCommand(), rather than SendStringToExecute(), as it is called synchronously and is executed before the command gets defined
    • Unfortunately this causes the UNDEFINE command to be echoed to the command-line, an undesired side effect.
    • I have not tested this being loaded on AutoCAD Startup - it may require some work to get the initialization done appropriately, if this is a requirement (as SendCommand is called on the ActiveDocument).
  • I've implemented the OPEN command very simply - just to request a filename from the user with a standard dialog - and then call a function to open this file. More work may be needed to tailor this command's behaviour to match AutoCAD's or to match your application requirements.
    • This is defined as a session command, allowing it to transfer focus to the newly-opened document. It does not close the active document, which AutoCAD's OPEN command does if the document is "default" and unedited (such as "Drawing1.dwg").

And so here's the code:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.Interop;

using System.Runtime.InteropServices;

namespace RedefineOpen

{

  public class CommandRedefinitions

  : Autodesk.AutoCAD.Runtime.IExtensionApplication

  {

    public void Initialize()

    {

      AcadApplication app =

        (AcadApplication)Application.AcadApplication;

      app.ActiveDocument.SendCommand("_.UNDEFINE _OPEN ");

    }

    public void Terminate(){}

    [CommandMethod("OPEN", CommandFlags.Session)]

    static public void Open()

    {

      DocumentCollection dm = Application.DocumentManager;

      Editor ed = dm.MdiActiveDocument.Editor;

      PromptOpenFileOptions opts =

        new PromptOpenFileOptions(

          "Select a drawing file (for a custom command)"

        );

      opts.Filter = "Drawing (*.dwg)";

      PromptFileNameResult pr = ed.GetFileNameForOpen(opts);

      if (pr.Status == PromptStatus.OK)

      {

        dm.Open(pr.StringResult);

      }

    }

  }

}

32 responses to “Replacing AutoCAD's OPEN command using .NET”

  1. Hi,Kean
    How to get the Hatch dialog using .NET?It seems that there is no such class in the .NET API?
    Thanks!

  2. Vladimir Michl Avatar

    Just a note - the right international command is "_.UNDEFINE _OPEN ", not "_.UNDEFINE OPEN ".

  3. Oops - thanks, Vladimir. Will fix the post.

  4. Patrick Nikoletich Avatar
    Patrick Nikoletich

    Hi Kean,
    Thank you for answering my question so quickly. You say that this is the simplest way, but describe a few downsides such as possible problems that might occur when executing this on AutoCAD startup and a UNDEFINE message that will be echoed to the command line; is there a more complex but preferred method for integrating this in 100% seamlessly, possibly even in C++?

  5. DocumentLockModeChangedEventArgs.Veto() perhaps...?

  6. Kean Walmsley Avatar

    Hi Patrick,

    One way to get rid of the command echo would be to use two modules: the "loader" module would use Document.SendStringToExecute() to use the UNDEFINE command, with the flag set to not echo the string to the command-line. It would then use the same function to load another module defining the new OPEN command.

    This would also resolve the timing issue solved previously by the call to SendCommand().

    Regards,

    Kean

  7. how to open autocad 2004 using vb6 and VB.net both.

  8. Kean Walmsley Avatar

    You need to use COM - you cannot use AutoCAD's native .NET interface out-of-process. So CreateObject() with the appropriate ProgID ("AutoCAD.Application.16"? I forget...) should do it from VB6, and the equivalent function VB.NET (which should be easy to find via Google).

    Kean

  9. DO YOU HAVE THE VB.NET VERSION?

  10. Hi Alberto,

    I suggest checking out these code conversion websites:

    Carlos Aguilar's "Code Translator"
    Kamal Patel's "Convert C# to VB.NET"

    Regards,

    Kean

  11. Hi Kean,

    Is there a way to redefine QSAVE?

  12. You UNDEFINE it and implement a command of the same name.

    Kean

  13. Hi Kean,
    I am entirely new to .net. I hope you can provide me the VB.net version of the following classic vb expressions.
    ------------------------------------------------

    Public WithEvents AcadApp as Acad.Application
    Dim AcadDoc as Acad.Document

    Sub Main()
    Set AcadApp = New AcadApplication
    AcadApp.Documents.Open "c:\test.dwg"
    Set AcadDoc = AcadApp.ActiveDocument
    AcadDoc.SendCommand "e all _qsave"
    AcadApp.Documents.Close
    Set AcadDoc = Nothing
    AcadApp.Quit
    End Sub
    -------------------------------------------
    Habeeb

  14. Hello, Kean,

    I have troubles implementing this sample in AutoCAD 2008 (German version), even more in 2009

    With 2008 I get it done, but it will not work, if I try to load the utility via the applications in the registry, only interactively with NETLOAD
    But I will need it loaded automatically on startup....

    With 2009 I just do not get the new command definitions to work....

    Any idea?

    Thanks,

    Marco

  15. Hi Marco,

    Each language version of each AutoCAD version (and each language version of each of its vertical versions) has its own Registry section, which is where you'll need to make the demand-loading entries.

    These keys are listed in this DevNote, if you're an ADN member.

    So for German AutoCAD 2008, it's here:

    [HKCU|HKLM]\Software\Autodesk\AutoCAD\R17.1\ACAD-6001:407

    And for German AutoCAD 2009, it's here:

    [HKCU|HKLM]\Software\Autodesk\AutoCAD\R17.2\ACAD-7001:407

    I reproduced your problem with 2009, and did some research: it seems there is a change in the string format you need to enter for the Filter property (the change was introduced to fix some issues with how it worked previously, but it does mean a change in the string format).

    So for 2009, you should change it to this (adding the extension as an additional item separated by '|'):

    opts.Filter = "Drawing (*.dwg)|*.dwg";

    By the way - if you want to add provide multiple filters, the format is this:

    opts.Filter = "Drawing (*.dwg)|*.dwg|All files (*.*)|*.*";

    I hope this fixes your problems,

    Kean

  16. CHeers for this

  17. Antony Joseph Avatar

    Hello Kean,

    How can I get a list of documents that are already open in AutoCAD? I am using VB.net to create some drawings and when I try to save, it gives an error if a drawing with the same name is already open.

    Thanks in advance,
    Antony

  18. Antony Joseph Avatar

    Hello Kean,

    How can I get a list of documents that are already open in AutoCAD? I am using VB.net to create some drawings and when I try to save, it gives an error if a drawing with the same name is already open.

    I am able to get the count using documentcollection.count

    But I don't know how to get into the details of each document.

    Thanks in advance,
    Antony

  19. Kean Walmsley Avatar

    Hi Antony,

    Please post this type of question to the ADN team or the AutoCAD .NET Discussion Group.

    I don't provide support that isn't directly related to the post topic (and the code I've provided).

    Regards,

    Kean

  20. Juergen.Becker@CAD-Becker.de Avatar
    Juergen.Becker@CAD-Becker.de

    Hi Kean,
    i tried this out:
    AcadApplication app =
    (AcadApplication)Application.AcadApplication
    But it doesnt work, because

    Autodesk.AutoCAD.Applicationservices.AcadApplication is a property not a type.

    What goes wrong?
    Regards Juergen

  21. Hi Juergen,

    Do you have the namespace included:

    using Autodesk.AutoCAD.Interop;

    And the assembly reference to AutoCAD's Type Library?

    Regards,

    Kean

  22. Juergen.Becker@CAD-Becker.de Avatar
    Juergen.Becker@CAD-Becker.de

    Hi Kean,
    yes I did.
    But don't worry, I did it another way so the problem is fixed.
    Many thanks.
    Regards Juergen.

  23. Hi Kean, This is excellent idea to open file.

    I tried in simple way :

    DocumentCollection dm = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager;
    dm.Open("C:\\a.dwg",true,"");

    Its say: Invalid execution context.

    Do u have any suggession please?

  24. Try marking your command as a "session" (rather than "modal") command.

    Kean

  25. Hi Kean, Thanks. Yes it is works when it is class only & command with session. If command into class & the file is open from a form under button, Its say same problem. Any advice pls?

  26. From a modeless dialog you should really SendStringToExecute() to execute commands via AutoCAD's command-line. Either that or handle the document locking yourself, which is more risky.

    Kean

    1. Hi Kean,

      how to open a Drawing with SendStringToExectue() ?

      Richard

      1. Hi Richard,

        Please post support questions to the AutoCAD .NET Discussion Group.

        I'm not sure exactly what you're suffering from... you may need to try setting the Session flag for your command. I don't recall specifically whether this is needed for OPEN via SendStringToExecute(), but it's typically needed for commands that work with multiple drawings.

        Regards,

        Kean

  27. Hi Kean,

    Where do I find the reference so I can use COM for Autocad 2009? Here is compile error

    Thanks, Andrew

    C:\Programming\Acs2009\xBatch\xBatch\Class.cs(73,13): error CS0012: The type 'Autodesk.AutoCAD.Interop.Common.IAcadDatabase' is defined in an assembly that is not referenced. You must add a reference to assembly 'Autodesk.AutoCAD.Interop.Common, Version=17.2.0.0, Culture=neutral, PublicKeyToken=eed84259d7cbf30b'.

  28. Hi Andrew,

    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.

    That said, it sounds as though you're missing a project reference to the appropriate AutoCAD/ObjectDBX Common Type Library. If that suggestion doesn't help, please post your follow-up question to one of the above resources.

    Kean

  29. Any ideas on how to do this with AutoCad 2015? I can't seem to get undefine to work with editor.Command

    1. I suggest posting a code snippet to the AutoCAD .NET Discussion Group: someone there should be able to help.

      Kean

Leave a Reply to ALBERTO BENITEZ Cancel reply

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