Connect VS Code to Autocad

Connect VS Code to Autocad

Ahmadi_rad
Enthusiast Enthusiast
1,967 Views
12 Replies
Message 1 of 13

Connect VS Code to Autocad

Ahmadi_rad
Enthusiast
Enthusiast

Hello

 I saw this link in autocad development guides that shows VSCode can be connected to autocad and edit/debug visual lisp. is it possible to use it for c# debugging also? I have some c# plugins and aim to connect vs code to those plugins, if you are thinking about exact connection point in Autocad side.

 

If possible, how does this connection work, which technologies are involved and if not possible, what is the obstacles in terms of .Net.

 

Thanks in advance

0 Likes
1,968 Views
12 Replies
Replies (12)
Message 2 of 13

Ed__Jobe
Mentor
Mentor

I don't know about debugging lisp ( may have heard something new about it), but to me the lack of debugging in C# is a big drawback for VSC. You can use the Community version of Visual Studio for free as long as you're not developing commercial apps. The latest version is fine as long as you target NET Framework 4.8. You can follow this tutorial for info on how to set up debugging.

Ed


Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
How to post your code.

EESignature

0 Likes
Message 3 of 13

Ahmadi_rad
Enthusiast
Enthusiast

Hello

As far as know, you can debug c# in vsc but first you need to install c# extension, but my point is something else and with your answer, it is going clear in my mind.

Assume we have a static instance called csharpprojectdata in autacad memory.

Now, if this is available from outside world, using com or .net facilities (which i don't know these facilities if any), you may inport it to vs or vsc project and manipulate it by user scripts. 

Point is if the static class is visible from outside and how to pipeline external code to that static member.

 

 

 

0 Likes
Message 4 of 13

Ed__Jobe
Mentor
Mentor

1. Installing the C# extension allows you to write code and run it. That's not the same as an interactive debugger like Visual Studio has.

2. Your second point has nothing to do with number 1. You need to start a new thread.

Ed


Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
How to post your code.

EESignature

Message 5 of 13

daniel_cadext
Advisor
Advisor

Also interested in this, I found I can debug python wrappers I’ve been working on

for swampers  https://www.theswamp.org/index.php?topic=58162.msg614785#msg614785

 

It seems there’s some sort of listener in AutoCAD when vscode is the lisp default editor, because it doesn’t work in BricsCAD.

Nor does it work if the old vlide is used.

 

Anyway, I didn’t not expect I would be able to debug python, so I assume it would work for all languages ..??.. I used the attach to

process. One caveat, I had to initiate the debug session with python’s breakpoint() function. Not sure if this puts python in debug mode or what the deal is, still need to investigate.

 

edit, attached a pic for the non swampers, if there are any :).  I embedded the python interpreter, and wxWidgets in a native ARX,  I can debug in .PY files, you can see the locals, stack and everything..

 

 

 

Python for AutoCAD, Python wrappers for ARX https://github.com/CEXT-Dan/PyRx
0 Likes
Message 6 of 13

daniel_cadext
Advisor
Advisor
Sure, why not, you will have to create the API, or write an interface to expose your classes to COM.
If you use COM, you could in theory use Lisp + VSCODE to debug
Python for AutoCAD, Python wrappers for ARX https://github.com/CEXT-Dan/PyRx
0 Likes
Message 7 of 13

Ahmadi_rad
Enthusiast
Enthusiast

So, if I develop a plugin (which is run inside autocad), how can I expose it's interface to outside of autocad, or where is the default connection point in autocad?

0 Likes
Message 8 of 13

daniel_cadext
Advisor
Advisor

I’ve actually never tried this from .NET.

 

COM and ActiveX Automation as described in .. talks about handling out of process requests.

https://help.autodesk.com/view/OARX/2024/ENU/?guid=GUID-DA0AABA4-BED8-433A-864E-EBCE43195FF5

 

Create COM interface, use ClassInterfaceAttribute and ComVisibleAttribute in System.Runtime.InteropServices.

 

Out of process, you would attach to whatever process is running your script.

For COM, where ever you call Marshal.GetActiveObject(progID)

 

Python for AutoCAD, Python wrappers for ARX https://github.com/CEXT-Dan/PyRx
Message 9 of 13

Ahmadi_rad
Enthusiast
Enthusiast

Thanks, This link (a sub node of your link) starts with this sentence:

"You can make functions, objects, or entities coded in ObjectARX available to developers who access an ActiveX object model through VBA or another programming environment."

So, basically this is possible to expose extended object model from inside Autocad, but reference documents are all in c++ and ObjectARX.

 

By the way I tried this piece of code, hopelessly that it works and not surprisingly it didn't!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace BuildingApp_Client
{

    public interface iComObject
    {
        void Test();
    }

    [ClassInterface( ClassInterfaceType.AutoDispatch)]
    [ComDefaultInterface(typeof(iComObject))]
    public class ComObject: MarshalByRefObject, iComObject
    {
        public ComObject()
        {

        }

        [ComVisible(true)]
        public void Test()
        {
            System.Windows.Forms.MessageBox.Show("ComTest");
        }
    }
}

Instance of class in AutoCAD environment

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.AutoCAD.Geometry;
using System.Collections;
using System.Runtime.InteropServices;


namespace BuildingApp_Client
{
    [ClassInterface(ClassInterfaceType.AutoDispatch)]
    public static class BuildingAppGlobal
    {
        public static ComObject testcom = new ComObject();
    }
}

 

Client side, late bound, without importing type library

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Reflection;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Type objType = Type.GetTypeFromProgID("AutoCAD.Application");
            object objSum = Activator.CreateInstance(objType);
            object[] myArgument = {};
            object c = objType.InvokeMember("Test", BindingFlags.InvokeMethod, null, objSum, myArgument);
        }
    }
}

 

and this is the object model I can see

Untitled.jpg

 

And part of your answer:

"Create COM interface, use ClassInterfaceAttribute and ComVisibleAttribute in System.Runtime.InteropServices.

Out of process, you would attach to whatever process is running your script.

For COM, where ever you call Marshal.GetActiveObject(progID)"

 

I think you meant connecting from my code (inside of Autocad) to script running environment, not from script environment to AutoCAD, isn't it? it may also work and good Idea, but wanted to make sure.

 

0 Likes
Message 10 of 13

norman.yuan
Mentor
Mentor

In your code:

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Type objType = Type.GetTypeFromProgID("AutoCAD.Application");
            object objSum = Activator.CreateInstance(objType);
            object[] myArgument = {};
            object c = objType.InvokeMember("Test", BindingFlags.InvokeMethod, null, objSum, myArgument);
        }
    }
}

 

objectType is the type of AcadApplication (AutoCAD COM object), it DOES NOT HAVE a member called "Test".

You need to create an instance of your COM Type (ComObject class), and then invoke the Test() method from the instance.

 

Furthermore, since the ComObject class has reference to the AutoCAD .NET assembly, the COM API would only be exposed AFTER the managed DLL is loaded into running AutoCAD session, that is your console test app would only work in the conditions:

 

1. AutoCAD runs;

2. the managed DLL that exposes its objects as COM-able has to be loaded into AutoCAD.

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 11 of 13

Ahmadi_rad
Enthusiast
Enthusiast

Hello  and thanks for your reply

 

"You need to create an instance of your COM Type (ComObject class)":

This is what I unfortunately don't understand. Comobject instance is a variable instantiated inside of AutoCAD, this is not a stand alone executable that I can create an instance of it, or even if I can, that would be different from the version running inside auto cad. So, this is the question, while we cant inject something to Acad.application object model, how can I create instance of my class that refers to the version inside of cad? 

 

Other points are observed

 

0 Likes
Message 12 of 13

Ahmadi_rad
Enthusiast
Enthusiast

Answer is here

https://www.keanw.com/2009/05/interfacing-an-external-com-application-with-a-net-module-in-process-t... 

in client side we use AcadApplication.GetInterfaceObject which exposes com object to outside world. 

Method is there but still couldn't get the interface, probably problem is from my implementation of com interface, working on it. 

Message 13 of 13

Ahmadi_rad
Enthusiast
Enthusiast

And I will be grateful if somebody helps me on details or if necessary I will start a new thread

 

This server code worked for a few minutes and I don't know what I changed and I cant get it to work anymore. Problem may be combination of attributes.

 

And somewhere I read that this dll must be loaded from the same folder as acad.exe which is observed.

using System;
using System.Runtime.InteropServices;

namespace BuildingApp_Client
{
    [Guid("5B5B731C-B37A-4aa2-8E50-42192BD51B17")]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    [ComVisible(true)]
    public interface iComTest
    {
        [ComVisible(true)]
        void Test();
    }

    [ClassInterface( ClassInterfaceType.None)]
    //[ComDefaultInterface(typeof(iComObject))]
    [Guid("44D8782B-3F60-4cae-B14D-FA060E8A4D01")]
    [ComVisible(true)]
    [ProgId("BuildingApp_Client.ComTest")]
    public class ComTest : /*System.EnterpriseServices.ServicedComponent,*/ iComTest
    {
        public ComTest()
        {

        }

        [ComVisible(true)]
        public void Test()
        {
            System.Windows.Forms.MessageBox.Show("ComTest");
        }
    }
}

 

client side code:

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int i = 0;
            AcadApplication acApp = (AcadApplication)Marshal.GetActiveObject("AutoCAD.Application.24");
            object o = acApp.GetInterfaceObject("BuildingApp_Client.ComTest");

            //BuildingApp_Client.ComObject C = (BuildingApp_Client.ComObject)o;
        }
    }
}

 get interface throws exceptiion of "problem loading application". finally I want to run test method.

0 Likes