Getting AutoCAD's current directory from a .NET application

This question came in via a comment from Danny Polkinhorn on this post:

After AutoCAD has launched, I often have a need to determine the "Start In" directory specified in the shortcut (Right-click AutoCAD shortcut, Properties, Start in). Is there a way to determine what that directory is? I'm thinking I can use the path of the active drawing (either Drawing1 or the drawing they double-clicked on). Is that a fool-proof way?

This is an interesting topic, and raises the questions of what that the "Start In" setting is used for and how it can be modified.

The "Start In" property in a Windows shortcut specifies the initial "current directory" for a process. The concept of a current or working directory is common across the various Operating Systems I've worked with: processes have a current directory which is the default file-system folder used for certain operations (such as opening a drawing inside AutoCAD). It is also used by Windows when attempting to locate DLLs to load.

As Danny mentions, it is possible to specify the current directory for a process when it is launched: common ways are to edit the "Start In" property in the shortcut used to launch the application, to change the current directory (using CHDIR or CD) in a command-prompt window and launch the executable from there, or even to specify the working directory for an application to be launched from the Visual Studio debugger. And while the current directory is generally specified as the process starts, it can also change during execution.

AutoCAD 2008's default "Start In" location is "C:\Program Files\Autodesk\AutoCAD 2008\UserDataCache\". Just to verify the process of querying it from an application, I copied the standard shortcut and modified the property to "c:\temp":

Shortcut_properties

I know of two ways to query this property:

System.Environment.CurrentDirectory

System.IO.Directory.GetCurrentDirectory()

 

I created a simple command, CURDIR, to query this property and print the results.

using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

namespace CurrentDirectory

{

  public class Commands

  {

    [CommandMethod("CURDIR")]

    public void GetCurrentDirectory()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Database db = doc.Database;

      Editor ed = doc.Editor;

      ed.WriteMessage(

        "\nSystem.Environment.CurrentDirectory: "

        + System.Environment.CurrentDirectory

        + "\nSystem.IO.Directory.GetCurrentDirectory(): "

        + System.IO.Directory.GetCurrentDirectory()

      );

    }

  }

}

 

This code works very well, but it may not return the results expected, depending on when the command is executed and - in particular - how the module is loaded. If we use demand-loading to load your module, it will generally returns the results we expect, assuming it runs early enough. Here's what's returned by the CURDIR command once it has demand-loaded our module in the instance of AutoCAD created by the modified shortcut:

Command: curdir

System.Environment.CurrentDirectory: C:\temp

System.IO.Directory.GetCurrentDirectory(): C:\temp

If, on the other hand, we use the NETLOAD command to load our module, we get the directory from which it was loaded:

Command: netload

Command: curdir

System.Environment.CurrentDirectory: C:\Program Files\Autodesk\ObjectARX

2008\samples\dotNet\Prompts\bin\Debug

System.IO.Directory.GetCurrentDirectory(): C:\Program Files\Autodesk\ObjectARX

2008\samples\dotNet\Prompts\bin\Debug

 

It took me some time to realise what was happening: it appears that the standard "file navigation" dialog inside AutoCAD - whether it's being used to open a drawing, load an application or perform an action on another type of file - sets the current directory to its most
recent location, the first time it is run and closed. So even if you escape from the OPEN command, the location to which you had browsed before cancelling becomes the new current directory.

Whether this is intuitive or expected isn't really for me to say (although I can understand why people might have an opinion). The moral of the story is that you cannot reliably determine the "Start In" folder for AutoCAD (or any other complex application, in reality), unless you ask it very early on in its execution. Code hosted in the process can modify this setting as it feels it needs to.

While not 100% reliable - there are no guarantees some other code has not modified the property beforehand - your best chance at identifying the "Start In" location is to have an application module load on AutoCAD start-up and query it there.

Update:

From AutoCAD 2016 onwards there's now a STARTINFOLDER system variable:

Command: STARTINFOLDER

STARTINFOLDER = "C:\Users\walmslk\Documents\" (read only)

11 responses to “Getting AutoCAD's current directory from a .NET application”

  1. Wow, I wasn't expecting an entire post! Thanks a ton, this definitely confirms some of my earlier testing. I have a dll loading at startup so I'll be sure to check it there.

    Thanks again!
    -Danny

  2. Nikolay Poleshchuk Avatar
    Nikolay Poleshchuk

    Kean! There are real problems with AutoCAD default directory. Some months ago I put an article "Little Tricks of Default Directory" by S.Vasiliev at my site -
    private.peterlin...

  3. Hi Kean,

    Really interesting behavior.
    What about .NET DLLs placed into .NET Assembly Cache?

    BTW, this raises another question. Which is the best option for .NET DLLs. Place them inside AutoCAD's root folder or inside GAC?

    I have faced some issues regarding to NETLOAD loading the .NET DLL we expect...

    Best regards,
    Fernando.

  4. Hi Fernando,

    The recommendation I've heard is to use AutoCAD's root folder. I'm not sure of the benefits or disadvantages of using the GAC.

    Regards,

    Kean

  5. Kean,

    Yes. I'm doing this way. The problem is when you need to support multiple versions and flavors of AutoCAD. It's not a good idea to have the same DLL copied inside each AutoCAD folder.

    In this case would be the Autodesk Commom folder a better solution?

    Maybe place the DLLs at the product folder and add its path to each AutoCAD support path list?

    Regards,

  6. I don't know that it's "not a good idea"... we've gone back to a per-product install of lots of our "shared" files: it helps avoid compatibility issues if a shared file is badly "upgraded" by one of the sharing products. It also gives more flexibility to have per-product implementations.

    The choice is ultimately yours, of course.

    Kean

  7. Kean,

    Yes, it will be always a pain to support multiple versions and there is no magic solution. All solutions will always give you both good and bad things.

    In fact, in my opinion, GAC does not solve this problem once it allows several copies of the same named DLL but with different versions. This may confuse and create more problems than solutions. For me, the so called "DLL hell" was just renamed to "GAC Hell". For instance, in my machine I can see two copies of "Autodesk.AutoCAD.Interop". One has version 17.0.54.0 and the other 17.1.51.0. Even worst, there are 10 copies of "Microsoft.DirectX.Direct3DX" DLLs.

    You are 100% right. The most secure way is to keep specific versions, per product, inside its directory and only share global modules that may not affect the way each version works after each update or service pack.

    Thanks for sharing your (Autodesk) experience with this. This type of information is very important and should be at SDK documentation too. 🙂

    Regards,

  8. Can i use existing drawing for customization using .net to save time to redraw through .net.?
    Manoj

  9. Hi Manoj,

    It depends on the situation. There's not really enough information for me to know what you're trying to do...

    Kean

  10. Hi,

    That was really helpful to understand what is goofing up with the modules I was trying to load.

    Just wondering if there is any way in ACAD (ACAD Command, Don't want to set it from .net modules) to explicit set the CurrentDirectory to userdefined path.

    Thanks!

    Mudi

  11. I don't believe you can set the working folder after-the-fact for a running process: you can certainly adjust things like the support path (although perhaps even that requires a restart, I forget).

    You might try posting to the discussion groups, to get opinions from there.

    Kean

Leave a Reply to Mudi Cancel reply

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