Is COM API still working and usable?

Is COM API still working and usable?

soonhui
Advisor Advisor
2,177 Views
12 Replies
Message 1 of 13

Is COM API still working and usable?

soonhui
Advisor
Advisor

I've trouble to get the COM API here working. In fact I'm not entirely sure whether the code snippet below still works ( I'm coming from C# background but the code is in VB.Net), and if it does, what are the references that are needed.

 

Dim oAcadApp As AcadApplication
Set oAcadApp = ThisDrawing.Application
' Specify the COM name of the object we want to access.
' Note that this always accesses the most recent version
' of Autodesk Civil 3D installed.
Const sCivilAppName = "AeccXUiLand.AeccApplication.6.0"
Dim oCivilApp As AeccApplication
Set oCivilApp = oAcadApp.GetInterfaceObject(sCivilAppName)
 
' Now we can use the AeccApplication object.
' Get the AeccDocument representing the currently
' active drawing.
Dim oDocument As AeccDocument
Set oDocument = oCivilApp.ActiveDocument
' Set the viewport of the current drawing so that all
' drawing elements are visible.
oCivilApp.ZoomExtents

 

Anyone can shed some light on this issue, and how I can go by investigating this?

 

 

 

##########

Ngu Soon Hui

##########

I'm the Benevolent Dictator for Life for MiTS Software. Read more here


I also setup Civil WHIZ in order to share what I learnt about Civil 3D
0 Likes
Accepted solutions (2)
2,178 Views
12 Replies
Replies (12)
Message 2 of 13

norman.yuan
Mentor
Mentor
Accepted solution

Yes, C3D's COM APIs still work. As matter of fact, sometimes, you have to use it because there are no equivalent .NET API counterparts for particular C3D features after all these years of .NET APIs emerged (well, some .NET API features also have no COM API counterparts, of course). So the 2 sets of APIs are complimentary to each other. The most common practice with C3D programming is to always use .NET APIs and only turn to COM API for whatever the .NET APIs lacks (however, it is not to suggest .NET + COM APIs combined would cover most, if not all, C3D features; no, they are from from it).

 

Since the custom C3D uses .NET API, the code would generally "C3D version" independent (except where C3D version breaks its compatibilities), so ideally, when COM APIs are user here and there for the .NET API-missing features, it is recommended to use late binding (VB.NET)/dynamic (C#).

 

If you need to take advantage of VS' intelli-sense of coding and choose early binding, you can add C3D's COM references. C3D installation comes with COM Interop assemblies installed, just as AutoCAD's COM interop assemblies. Go to C3D install folder and looking for DLLs named like "Autodesk.AECC.Interop.XXXXX.dll"s.

 

A quick critique of the code you posted:

Const sCivilAppName = "AeccXUiLand.AeccApplication.6.0"
Dim oCivilApp As AeccApplication
Set oCivilApp = oAcadApp.GetInterfaceObject(sCivilAppName)

 

In the code, "AeccXUiLandxxxxxxxx.6.0" is for very, very old C3D version. You must make sure the C3D version correct. For example, for C3D 2024, it is 13.6, or C3D 2025, it is 13.7. A hint: you can go to "C:\Program Files\Common Files\Autodesk Shared" folder, and look for folder "Civil Engineering 13X" where X is meant for "13.X". C3D has been in its "13.X" version for quite a well, and may stay that way for quite near future. It seems to me Autodesk does not have much interest to improve existing C3D API.

 

Another tip when using COM API is needed: most .NET API C3D class has a AcadObject property, which can be used to access the COM object countrerpart, which would save from go through the whole COM API object model to access particular COM API objects (so avoided the call to GetInterfaceObject([COM CLASS ID_NAME]) in many cases. For example, if you want to get ParcelSegment's details, the .NET API's ParcelSegment provides nothing, so you can:

 

var netParcelSeg=(ParcelSegment)tran.GetObject(....);

dynamic comPacelSeg = netPacelSeg.AcadObject;

int elementCount = comParcelSeg.Count

...

 

HTH

 

 

 

 

Norman Yuan

Drive CAD With Code

EESignature

Message 3 of 13

soonhui
Advisor
Advisor

@norman.yuan ,

 

Thank you for your insightful post! It contains a lot of critical details that the original documentation is missing ( and it makes me shudder to think that Autodesk want to "archive" AKA delete old forum posts including gems such as yours here, for whatever reasons; take note @Tiana_Y , @Tarek_K , @ChrisMitchell01  and all).

 

One comment I have regarding your code example ( which I think is super critical with regards to the discoverability of the API)

var netParcelSeg=(ParcelSegment)tran.GetObject(....);

dynamic comPacelSeg = netPacelSeg.AcadObject;

int elementCount = comParcelSeg.Count

 

It seems that you are using dynamic keyword, which presupposes that we already know about the methods, fields and properties of the COM object. But exactly how we are supposed to know? There is no intellisense to help

##########

Ngu Soon Hui

##########

I'm the Benevolent Dictator for Life for MiTS Software. Read more here


I also setup Civil WHIZ in order to share what I learnt about Civil 3D
0 Likes
Message 4 of 13

norman.yuan
Mentor
Mentor

You need to be familiar to the Aecc COM object model, as you do (or if you do) with plain AutoCAD COM object model. For those who haven't do anything with AutoCAD/Aecc COM API coding, you can add COM interop assembly references to the .NET project (thus, early binding), so that you can use Object Browser to explore COM API's interfaces/classes, and you get intelli-sense while coding in VS. Of course the mixed API project should work as long as the COM interop references are correct version (that is, for COM early binding, the code is version dependent). late binding/dynamic is recommended, not mandatory, for better version compatibilities.

 

 

Norman Yuan

Drive CAD With Code

EESignature

Message 5 of 13

soonhui
Advisor
Advisor

@norman.yuan ,

 

You said that we can use Object Browser to view the classes for the COM, but that's not my experience, see the two screenshots below for Object Browser and Assembly Explorer-- there is no properties or methods or fields that I can get from them.

 

 

OBject browser.png

 

 

assemblyexplorer.png

 

There is no intellisense in VS 2022 also, as shown below-- everything is ComObject, which is quite useless.

 

combject.png

 

BUT, I do find another angle of attack, I can see that when debugging, in the Watch Window, there are objects like ActiveDocument, Application, and so on, and therefore I can based on what I see in the Watch Window debugger, and use reflection to just call out the correct members. So it should work right? Alas it doesn't.

 

Here's my simple code snippet:

 

 

       [CommandMethod(nameof(SectionViewBandData))]

       public void SectionViewBandData()
       {
           
           
           var oAcadApp = (AcadApplication)Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication;
           var sCivilAppName = "AeccXUiLand.AeccApplication.13.7";

           var oCivilApp =oAcadApp.GetInterfaceObject(sCivilAppName);
           var activeDocument= oCivilApp.GetType().InvokeMember("ActiveDocument", 
               BindingFlags.InvokeMethod, null, oCivilApp, null);  //here it throws exception

       }

 

 

An exception will be thrown when I InvokeMember this way. 

##########

Ngu Soon Hui

##########

I'm the Benevolent Dictator for Life for MiTS Software. Read more here


I also setup Civil WHIZ in order to share what I learnt about Civil 3D
0 Likes
Message 6 of 13

norman.yuan
Mentor
Mentor

Well, you just one step/click short of seeing the COM object's properties/methods in the ObjectBrowser: they are exposed as IAeccXXXXX interface:

normanyuan_0-1740493012004.png

 Also, the video clip below shows the intelli-sense works as expected, as long as the COM interop assemblies are referenced:

(view in My Videos)

Norman Yuan

Drive CAD With Code

EESignature

Message 7 of 13

soonhui
Advisor
Advisor

I can verify both points that you raise ( the Object Browser contains members, and some Interop classes have intellisense). But still, for the code snippet below,

 

[CommandMethod(nameof(SectionViewBandData))]

       public void SectionViewBandData()
       {
           
           
           var oAcadApp = (AcadApplication)Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication;
           var sCivilAppName = "AeccXUiLand.AeccApplication.13.7";

           var oCivilApp =oAcadApp.GetInterfaceObject(sCivilAppName);
           var activeDocument= oCivilApp.GetType().InvokeMember("ActiveDocument", 
               BindingFlags.InvokeMethod, null, oCivilApp, null);  //here it throws exception

       }

 

I'm a bit unsure how to proceed ( because neither Object Browser nor intellisense gives any hints), you can shed lights?

##########

Ngu Soon Hui

##########

I'm the Benevolent Dictator for Life for MiTS Software. Read more here


I also setup Civil WHIZ in order to share what I learnt about Civil 3D
0 Likes
Message 8 of 13

Jeff_M
Consultant
Consultant

@soonhui  Try this:

 

var activeDocument= oCivilApp.ActiveDocument

 

  Note that ActiveDocument is a Property, not a Method.

Jeff_M, also a frequent Swamper
EESignature
Message 9 of 13

soonhui
Advisor
Advisor

@Jeff_M , thank you for your tips. Though your code can't compile but it gives me hints to figure it out.

 

It turns out that to access COM object, you will need to use dynamic keywords. This provided that you know the properties of the COM object, which you can get by either looking at Object Browser, or use the VS debugger and the watch window, like what I mention above.

 

Below is the code that I can get to work via the strategy outlined above:

 

    [CommandMethod(nameof(SectionViewBandData))]
    public void SectionViewBandData()
    {


        var oAcadApp = (AcadApplication)Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication;
        var sCivilAppName = "AeccXUiLand.AeccApplication.13.7";

        dynamic oCivilApp = oAcadApp.GetInterfaceObject(sCivilAppName);
        dynamic activeDocument = oCivilApp.ActiveDocument;
        dynamic generalCurve = activeDocument.GeneralCurveLabelStyles;
        int count = generalCurve.Count;
    }

 

##########

Ngu Soon Hui

##########

I'm the Benevolent Dictator for Life for MiTS Software. Read more here


I also setup Civil WHIZ in order to share what I learnt about Civil 3D
0 Likes
Message 10 of 13

norman.yuan
Mentor
Mentor


<QUOTE>
It turns out that to access COM object, you will need to use dynamic keywords.

</QUOTE>

 

Well, using "dynamic" is not NEEDED, it is an option between using early binding and late binding. The code you showed in your previous reply:

           var oCivilApp =oAcadApp.GetInterfaceObject(sCivilAppName);
           var activeDocument= oCivilApp.GetType().InvokeMember("ActiveDocument", 
               BindingFlags.InvokeMethod, null, oCivilApp, null);  //here it throws exception

is the old-fashion late binding with C# before "dynamic" keyword is introduced (I recall it was C# 4.0, .NET Framework 3.x?). In the regard of late binding, VB.NET coding was much easier then. Again, coding with late binding, one do not get intelli-sense help. 

 

If you are sure your app is C3D version specific, using early binding makes your coding much easier. But, hey, who wants his/her C3D app only work for single C3D version? That is why late binding is recommended whenever possible, because .NET app itself is rather version-independent mostly, so why mix it with version dependent COM API early binding, just because one can code with intelli-sense help?

 

For COM API beginner, you can added references to COM interops (thus early binding) during the development stage, so you can use the COM objects correctly. When the development is done, or almost is done, and all the COM API calls are tested, you can change the type declaration to "dynamic", remove the COM Interop references, to make an one-time change, so that the COM API calls become late binding. Again, this is only for the COM API beginners to code easier, to learn.

 

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 11 of 13

Jeff_M
Consultant
Consultant

@soonhui in addition to what @norman.yuan is saying, to work with COM and Intellisense you must have the references to the COM Interops in the project. For years I used the following code to initiate the AeccApplication, AeccDocument, and AeccDatabase which does not require to be updated for every release...only the Interop references need be updated.

 

   /// <summary>
    /// Utility class for accessing Civil-3D COM.
    /// </summary>
    public sealed class AeccAppConnection
    {
        private AeccApplication aeccApp = null;

        public AeccAppConnection() { }

        public AeccApplication AeccApp
        {
            get
            {
                if (aeccApp == null)
                {
                    aeccApp = new AeccApplication();
                    aeccApp.Init((AcadApplication)Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication);
                }
                return aeccApp;
            }
        }

        public AeccDocument AeccDoc
        {
            get
            {
                return (AeccDocument)AeccApp.ActiveDocument;
            }
        }

        public AeccDatabase AeccDb
        {
            get
            {
                return (AeccDatabase)AeccApp.ActiveDocument.Database;
            }
        }
    }

 

However, once you get the hang of what methods/properties are available you will find that moving to the use of dynamic and removing the Interops makes maintaining the code much easier.

These are the references you will want to add to the project:

C3D Interops.png

Jeff_M, also a frequent Swamper
EESignature
Message 12 of 13

soonhui
Advisor
Advisor
Accepted solution

Based on the discussion with @Jeff_M , @norman.yuan as well as my own testing, I've written a full post here

 

Hopefully it would be of use to everyone. 

##########

Ngu Soon Hui

##########

I'm the Benevolent Dictator for Life for MiTS Software. Read more here


I also setup Civil WHIZ in order to share what I learnt about Civil 3D
Message 13 of 13

Jeff_M
Consultant
Consultant

@soonhui There are a few other Interops that users should know about when working with Pipes (Gravity) and Corridors (Roadway). There is no COM API for PressurePipes. Those 2 Interops were not in the image I posted previously as that was from a project dealing with only survey and description key objects.

C3D Interops.png

 

Jeff_M, also a frequent Swamper
EESignature