.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Determine active AutoCAD session

2 REPLIES 2
Reply
Message 1 of 3
keithjk
1109 Views, 2 Replies

Determine active AutoCAD session

I have a standalone program that engineering uses to do some design calculations.  We decided recently to pass some of the results to blocks in AutoCAD (which works great).  However, I found that some of the users run multiple sessions of AutoCAD.  The problem is my program always connects to the first session of AutoCAD that was opened.  (See snippet below).

 

My thoughts are I could change the code below to find ALL open sessions of AutoCAD and then have a user variable set to flag that it is the correct session.  I just don't know how to loop through all of the sessions.  Any suggestions on how to do this?

 

 

Const progID AsString = "AutoCAD.Application.18.2"

 acadapp =Nothing

Try

 acadapp = DirectCast(Marshal.GetActiveObject(progID), AcadApplication)

Catch

  Debug.Print("AutoCAD not open")

EndTry

2 REPLIES 2
Message 2 of 3
khoa.ho
in reply to: keithjk

To loop through all AutoCAD sessions, we can use System.Diagnostics.Process.GetProcessesByName("acad") to get all AutoCAD processes.

 

Marshal.GetActiveObject("AutoCAD.Application") always gets the last open instance of AutoCAD (which is lately active), so it would not use to get a specific session of AutoCAD.

 

Each AutoCAD process (session) has its own handle (MainWindowHandle) in Windows processes (Windows Task Manager -> Processes tab), so we will get an AutoCAD handle and get its COM object from there.

 

To get a COM object from a Windows handle number, we can use an import method AccessibleObjectFromWindow from Oleacc.dll. With the main inspiration from Andrew Whitechapel's blog, I rewrite the similar code trying to get an AutoCAD application using late binding.

 

The code is not working now, so everyone welcome to work more on this. The problem may come from the incorrect OBJID_NATIVEOM and Guid. The Guid I used in this code is for AutoCAD 2013. But I don’t know how to get OBJID_NATIVEOM (native object model) for AutoCAD. This is a very interesting topic for AutoCAD's late binding.

 

using System;
using System.Runtime.InteropServices;
using System.Text;
using AutoCAD;

namespace AcadLateBinding
{
    class Program
    {
        static void Main(string[] args)
        {
            ConnectAutoCAD();
        }

        public delegate bool EnumChildCallback(int hwnd, ref int lParam);

        private static EnumChildCallback _callback;

        [DllImport("User32")]
        public static extern bool EnumChildWindows(
            int hWndParent, EnumChildCallback lpEnumFunc, ref int lParam);

        // AccessibleObjectFromWindow gets the IDispatch pointer of an object
        // that supports IAccessible, which allows us to get to the native OM.
        [DllImport("Oleacc.dll")]
        private static extern int AccessibleObjectFromWindow(
            int hwnd, uint dwObjectID,
            byte[] riid,
            out AcadApplication ptr);

        [DllImport("User32.dll")]
        public static extern int GetClassName(
              int hWnd, StringBuilder lpClassName, int nMaxCount);

        public static bool EnumChildProc(int hwndChild, ref int lParam)
        {
            StringBuilder buf = new StringBuilder(128);
            GetClassName(hwndChild, buf, 128);
            if (buf.ToString() == "MDIClient")
            {
                lParam = hwndChild;
                return false;
            }
            return true;
        }

        public static void ConnectAutoCAD()
        {
            // Get the first AutoCAD's main window handle.
            int hwnd = (int)System.Diagnostics.Process.GetProcessesByName("acad")[0].MainWindowHandle;

            // We need to enumerate the child windows to find one that
            // supports accessibility. To do this, instantiate the
            // delegate and wrap the callback method in it, then call
            // EnumChildWindows, passing the delegate as the 2nd arg.
            if (hwnd != 0)
            {
                int hwndChild = 0;
                _callback = new EnumChildCallback(EnumChildProc);
                EnumChildWindows(hwnd, _callback, ref hwndChild);

                // If we found an accessible child window, call
                // AccessibleObjectFromWindow, passing the constant
                // OBJID_NATIVEOM (defined in winuser.h) and
                // IID_IDispatch - we want an IDispatch pointer
                // into the native object model.
                if (hwndChild != 0)
                {
                    const uint OBJID_NATIVEOM = 0xFFFFFFF0;
                    //Guid IID_IDispatch = new Guid("{00020400-0000-0000-C000-000000000046}");
                    Guid IID_IDispatch = new Guid("{070AA05D-DFC1-4E64-8379-432269B48B07}");
                    AcadApplication ptr;

                    int hr = AccessibleObjectFromWindow(hwndChild, OBJID_NATIVEOM, IID_IDispatch.ToByteArray(), out ptr);
                    if (hr >= 0)
                    {
                        // If we successfully got a native OM IDispatch pointer, we can QI this for
                        // an AutoCAD application (using the implicit cast operator supplied in the PIA).

                        var acadApp = ptr.Application;
                    }
                }
            }
        }
    }
}

 

-Khoa

 

Message 3 of 3
DiningPhilosopher
in reply to: keithjk

The most foolproof and least-confusing way (for the user) is to expose a COM server on your standalone application and write a simple AutoCAD plug-in extension.dll that exposes a command that the user would invoke to initiate the process from within the AutoCAD session that is to be used.

 

The AutoCAD extension dll would be minimal, exposing only one command that would connect to your standalone application via COM, and pass it the instance of the AcadApplication (or AcadDocument) object that should be used by the standalone app, to work with the instance of AutoCAD in which the process was initiated by the user.

 

 

 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost