Closing all open AutoCAD documents from a .NET application

One question that comes up from time to time is how to "gracefully" close all open documents inside AutoCAD. I use the term "gracefully" in quotes, as this does mean different things to different people. Let me first define what it means to me:

  • Changes get saved to modified drawings
  • Even if the drawing in question has never been saved before
    • Which means you should expect to get some DWGs with names such as "Drawing1.dwg" saved to the working directory
  • Active commands get cancelled, where possible

Firstly, we need to define our command in the "session context", which means it can work across drawings. This command will then loop through the documents in the document manager, closing them one-by-one. We need to do certain things to support the above conditions... if a command is active, we need to send a couple of cancel keystrokes to the document, and we also need to check whether the document has been modified or not. To do this last piece we need to activate the drawing and check DBMOD - if you relax the condition about saving (or just force the save, anyway, without checking the value of DBMOD), then you can avoid activating the document.

And that's about all there is to it, at least with my definition of gracefully. 🙂

Here's the C# code I used for this:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.Interop;

namespace CloseDocuments

{

  public class Commands

  {

    // If you change the command name, be sure to change

    // the code that checks for it, below.

    //

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

    static public void CloseDocuments()

    {

      DocumentCollection docs = Application.DocumentManager;

      foreach (Document doc in docs)

      {

        // First cancel any running command

        if (doc.CommandInProgress != "" &&

            doc.CommandInProgress != "CD")

        {

          AcadDocument oDoc =

            (AcadDocument)doc.AcadDocument;

          oDoc.SendCommand("\x03\x03");

        }

        if (doc.IsReadOnly)

        {

          doc.CloseAndDiscard();

        }

        else

        {

          // Activate the document, so we can check DBMOD

          if (docs.MdiActiveDocument != doc)

          {

            docs.MdiActiveDocument = doc;

          }

          int isModified =

            System.Convert.ToInt32(

              Application.GetSystemVariable("DBMOD")

            );

          // No need to save if not modified

          if (isModified == 0)

          {

            doc.CloseAndDiscard();

          }

          else

          {

            // This may create documents in strange places

            doc.CloseAndSave(doc.Name);

          }

        }

      }

    }

  }

}

A quick personal note... aside from it being a busy time of year with lots of internal meetings, I've been busy over the last few weeks getting visas for my family and I to travel to China and India. We leave on Wednesday: I'll be working from our Beijing office for 7 weeks, and then from Bangalore for a further 2 weeks. I actually hope this means I'll have a little more time to spend on this blog (at least more than I have during the last three weeks or so, where I've mostly been on the road), but let's see.

I'm especially excited to be taking my family on this trip; I'm sure it's going to be an enriching experience for all of us. I expect I'll end up interjecting my posts over the next few months with some comments on how it's all going... watch this space! 🙂

19 responses to “Closing all open AutoCAD documents from a .NET application”

  1. Hi,Kean
    Welcome to China!Wish you have a great time!

  2. Nikolay Poleshchuk Avatar
    Nikolay Poleshchuk

    Kean, nice trip! When are you planning to visit Russia?

  3. Thanks!

    Maybe we'll get to Russia next year - who knows? 🙂

    I'd certainly love to visit St. Petersburg one day.

  4. Haha!!!
    Welcome to BeiJing!!!

  5. Hi Kean,

    Is there any way to check if a Database which has no document has been altered?

    Once again, thank you in advance!

  6. hi Kean,
    I am rewriting my VBA command to .NET, that command saved all opened drawings in lower autocad version and closed them, worked fine
    I am having a problem in .NET, where I get an exception "Drawing is busy." when trying to close the last drawing (the one that the command was initiated from)

    You don't seem to be having this problem in your code.

  7. I forgot about the CommandFlags

    now it works, BUT

    I get an error message in AutoCAD Map Messages window (which is strange, as I'm not using AutoCAD Map), the errors are Cannot save options in the drawing and eLockViolation (2 consecutive occurrences)
    Also the resulted drawings can only be open using recover command, if I save them in 2000 version, if I save them in 2010, they are opened OK

  8. Kean Walmsley Avatar

    Hi Matus,

    OK, good - you've realised you had missed making it a "session" command. One implication of defining a session command is that it no lomger implicitly locks the currently active document: you need to use Document.LockDocument() to do so, disposing of the returned lock when you've finished.

    I suggest posting your complete code to the AutoCAD .NET Discussion Group, if this advice doesn't help.

    Regards,

    Kean

    1. Евгений Хрущ Avatar
      Евгений Хрущ

      Hello, Kean. Thank you for help about "session" command. But without it a LockDocument() using not worked:

      using (DocumentManager.MdiActiveDocument.LockDocument()) {
      DocumentManager.MdiActiveDocument = document;
      }

      1. Yes - you need to manually lock documents to access them from session commands. Non-session commands have automatic locking of the active document.

        Kean

  9. Thank you very much Kean,
    this solved both problems, the error and the need of recover.

  10. I have to say this website really rocks.

    I am just starting with events. (Starting to get the hang of things sort of)

    One question is I would like to check to see if the user has pressed YES or NO or CANCEL on the Close Drawing button.

    i.e. If they press YES to save I would love to do a bunch of secondary commands to the drawing (mostly read only stuff) before it closes.

    Any Suggestions?

    Stephan

  11. I'm glad you like the site.

    Unfortunately I don't have time to respond to support requests (that aren't specifically related to my posts).

    Please do submit your question to the ADN team, if you're a member, or otherwise the AutoCAD .NET Discussion Group.

    [Off the top of my head, you should look at the Document.BeginSave() event, or something like that.]

    Kean

  12. Hi Kean,

    I am having an unusual behavior while using document.closeandsave method. For some reason, the code works perfectly fine with AutoCAD version 2012, not with 2010.

    P.S I am forcing the save(not checking DBMOD).

    Is there any possible explanation of such behavior?

    Thanks in advance.

  13. Kean Walmsley Avatar

    Hi HA,

    It could well be something has been fixed between 2010 and 2012 (I tend to worry more when newer versions top working, naturally).

    Beyond that I can't really say what's happening. I suggest posting your code to ADN or to the AutoCAD .NET Discussion Group, in case someone there can comment.

    Regards,

    Kean

  14. Hi Kean,
    I am trying to close and open documents on Autocad OEM 2015 .
    Is there a way ( with lisp, arx, .net, or activex ) to solve this problem without an autocad crash?

    1. Kean Walmsley Avatar
      Kean Walmsley

      Hi Denis,

      AutoCAD OEM shouldn't be different (unless you're talking about a module that isn't bound in to work with your stamped products).

      I suggest contacting ADN: they should be able to help you.

      Regards,

      Kean

  15. Have you tried using Visual Studio 2015 RC with AutoCAD's extension methods? Example DocumentExtension.CloseAndDiscard(). I've never had this problem with earlier versions of Visual Studio.

    Visual Studio 2015 RC marks it as an error:

    ErrorCS1061'Document' does not contain a definition for 'CloseAndDiscard' and no extension method 'CloseAndDiscard' accepting a first argument of type 'Document' could be found (are you missing a using directive or an assembly reference?)

    1. Kean Walmsley Avatar

      Sorry - I haven't used VS 2015 RC.

      Kean

Leave a Reply to HA Cancel reply

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