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

How Can i Get specific Running AutoCAD instance for automation?

10 REPLIES 10
Reply
Message 1 of 11
Anonymous
1081 Views, 10 Replies

How Can i Get specific Running AutoCAD instance for automation?

Hello! everyone!
 

 
It's AutoCAD program,Now I want to automate it by COM in my app.
 
Now the problem is GetActiveObject(clsid, NULL, &pUnk); I cann't get more control on it.
i.e
IF the user have several AutOCAD instances running . And How I can guarantee that always get the most newly created one?
 
And if my app startup the autocad by ShellExecuteEX then I can get the Hanlde of it.
 
By this Handle, May I get it's corresponding Com's object?

10 REPLIES 10
Message 2 of 11
fenton.webb
in reply to: Anonymous

use the ROT

 

http://stackoverflow.com/questions/11835617/understanding-the-running-object-table




Fenton Webb
AutoCAD Engineering
Autodesk

Message 3 of 11
Anonymous
in reply to: fenton.webb

thanks for you reply!

I have read the link -page, But I still cann't find a way to accomplish it.

I use C++ ,Can you give more instance in detais ?

 

I have google and look up MSDN,But I don't get more useful info to realize it.\

 

regards!

Message 4 of 11
fenton.webb
in reply to: Anonymous

no problem - search for ROT and AutoCAD e.g. http://adndevblog.typepad.com/autocad/2012/12/dumping-the-com-running-object-table-rot-in-objectarx....




Fenton Webb
AutoCAD Engineering
Autodesk

Message 5 of 11
Anonymous
in reply to: fenton.webb

yes~!

But I have accomplish similar function.

 

Now I can get the IMonike of the acad.exe. And by pMoniker->IsSystemMoniker() I know both(I start 2 acad instances)

IMonikes are  Item moniker. They GetDispName is the same. So pMoniker->isEqual() is return Yes!

 

So Now I just don't know How to distinguish this 2 CAD instances?

 

I have tried using IMonike::GetTimeOfLastChange() but failed.

 

BTW,Actually I start CAD using a stand-alone exe by shellExcuteEx() Then I know the process handle and it's process's ID.  I just want my app to start CAD as a companion,and do some communication by IPC.

 

But the user may have start 1 or more CAD instance even after my app started,the user still may start another CADs,So I want to my app always can attach to the CAD instance as my app's companion by COM.

 

(GetActiveObject() always attach to the first CAd instance)

 

Thanks !

Message 6 of 11
fenton.webb
in reply to: Anonymous

When you start AutoCAD simply pass in a fake identifying parameter when you shellexecute e.g

Acad c:\mydrawing.dwg /myid 2334456677

Then, you can find all exes which have a command line parameter that matches



Fenton Webb
AutoCAD Engineering
Autodesk

Message 7 of 11
Anonymous
in reply to: fenton.webb

good!
But How can i get the command line parameter of a running ACAD ?
Message 8 of 11
fenton.webb
in reply to: Anonymous

there are many posts online about how to obtain the command line parameters from an external exe... From .NET you can do this

       

using (ManagementObjectSearchersearcher = newManagementObjectSearcher("SELECT * FROM Win32_Process"))

        {

         

ManagementObjectCollectioncollection = searcher.Get();

         

foreach (ManagementObject @object in collection)

          {

           

try

            {

             

objectcommandLine = @object["CommandLine"];




Fenton Webb
AutoCAD Engineering
Autodesk

Message 9 of 11
Anonymous
in reply to: fenton.webb

OK!

For now ,assume I have get the acad.exe's that match.

 

I know it's processId and clsid(AutoCAD.Application),And How can i get the Com's IUnknow interface that match my processID?

 

 

 

Message 10 of 11
fenton.webb
in reply to: Anonymous

I'm not sure, I have never done it. I would play around with Marshal.GetActiveObject() or at least research the methods in the Marshal namepsace.




Fenton Webb
AutoCAD Engineering
Autodesk

Message 11 of 11

Here is some code I wrote in C# to access the ROT, if useful to anyone...

 

[DllImport("ole32.dll")]
static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc);

[DllImport("ole32.dll")]
public static extern void GetRunningObjectTable(
    int reserved, 
    out IRunningObjectTable prot);

//Requires Using System.Runtime.InteropServices.ComTypes
//Get all running AutoCAD instance by querying ROT
private List<object> GetAcadInstances(string[] progIds)
{
    List<string> clsIds = new List<string>();

    //get the autocad clsid
    foreach (string progId in progIds)
    {
        Type type = Type.GetTypeFromProgID(progId);

        if(type != null)
            clsIds.Add(type.GUID.ToString().ToUpper());
    }

    //Get Running Object Table ...
    IRunningObjectTable Rot = null;
    GetRunningObjectTable(0, out Rot);
    if (Rot == null)
        return null;

    //get enumerator for ROT entries
    IEnumMoniker monikerEnumerator = null;
    Rot.EnumRunning(out monikerEnumerator);
    if (monikerEnumerator == null)
        return null;

    monikerEnumerator.Reset();

    List<object> instances = new List<object>();

    IntPtr pNumFetched = new IntPtr();
    IMoniker[] monikers = new IMoniker[1];

    //Go through all entries and identifies ACAD instances
    while (monikerEnumerator.Next(1, monikers, pNumFetched) == 0)
    {
        IBindCtx bindCtx;
        CreateBindCtx(0, out bindCtx);
        if (bindCtx == null)
            continue;

        string displayName;
        monikers[0].GetDisplayName(bindCtx, null, out displayName);
                
        foreach (string clsId in clsIds)
        {
            if (displayName.ToUpper().IndexOf(clsId) > 0)
            {
                object ComObject;
                Rot.GetObject(monikers[0], out ComObject);

                if (ComObject == null)
                    continue;

                instances.Add(ComObject);
                break;
            }
        }
    }

    return instances;
}

private void TestROT()
{
    //look for acad 2009 & 2010 & 2011
    string[] progIds = 
    { 
        "AutoCAD.Application.17.2", 
        "AutoCAD.Application.18",
        "AutoCAD.Application.19.1"
    };

    List<object> instances = GetAcadInstances(progIds);

    foreach (object acadObj in instances)
    {
        try
        {
            //Late bind property "AcadApplication.Preferences.Profiles.ActiveProfile"

            object Preferences = acadObj.GetType().InvokeMember("Preferences",
                System.Reflection.BindingFlags.GetProperty,
                null, acadObj,
                null, null, null, null);

            object Profiles = Preferences.GetType().InvokeMember("Profiles",
                System.Reflection.BindingFlags.GetProperty,
                null, Preferences,
                null, null, null, null);

            string ActiveProfile = Profiles.GetType().InvokeMember("ActiveProfile",
                System.Reflection.BindingFlags.GetProperty,
                null, Profiles,
                null, null, null, null) as string;

            //...
        }
        catch
        {
            continue;
        }
    }
}

 



Philippe Leefsma
Developer Technical Services
Autodesk Developer Network

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

Post to forums  

Autodesk Design & Make Report

”Boost