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

Create Autocad vb.net applciation to work in all Autocad versions

15 REPLIES 15
SOLVED
Reply
Message 1 of 16
muthineni
7011 Views, 15 Replies

Create Autocad vb.net applciation to work in all Autocad versions

I have written an applciation in vb.net which interacts with AUTOCAD for 2011 version.

 

created object as,

 

Dim AcadApp As AcadApplication

Try
                AcadApp = GetObject(, "AutoCAD.Application.18.1")
            Catch ex As Exception
                AcadApp = CreateObject("AutoCAD.Application.18.1")
            End Try

 

now the applciation needs to be run in 2010 & lower versions.

Can anyone help me out on how to create a object which works for all versions.

 

Thank you.

15 REPLIES 15
Message 2 of 16
Alecia0001
in reply to: muthineni

On eof my friend is a CAd engineer, I think he will help you out for this, here is the profile I have shared this thread to him also, he will get back to in sometime. But if you have some urgency you can contact him directly.

Message 3 of 16
norman.yuan
in reply to: muthineni

In general, if you want the code to work with multiple version of AutoCAD, in the method CreateObject()/GetObject() you pass non-version speicific program ID:

 

           Try
                AcadApp = GetObject(, "AutoCAD.Application")
            Catch ex As Exception
                AcadApp = CreateObject("AutoCAD.Application")
            End Try

 

So, that the the code runs, it would try to run whatever version of AutoCAD installed in the running computer.

 

However, since your project is referenced to AutoCAD 2011 COM type library (because you delaration: Dim AcadApp As AcadApplication, e.g. early binding), therefore the application you are doing is depending on AutoCAD 2011. Whether the app works with other version of AutoCAD totally depends on Autodesk's decision of how AutoCAD is version compatible. In general, it is backward-compatible. That means, the app you are doing would likely work with a few later version of AutoCAD (AutoCAD 2012, 2013...), but very likely not with any earlier version (AutoCAD 2010, 2009...).

 

The usual approach is to use the earlest version of AutoCAD from your targeted AutoCAD versions your app want to work with for the development. Somtimes using late binding may help overcome potential issues, such as running the app with computers where multiple AutoCAD versions are installed.

 

Message 4 of 16
Hallex
in reply to: muthineni

Not sure about if this helps, just found my old project created for A2009

You can change references to your current release:

Imports System.Windows.Forms
Imports System.IO
'Reference to AutoCAD/ObjectDBX Common 17.0 Type Library:
Imports Autodesk.AutoCAD.Interop.Common
'Reference to AutoCAD 2009 Type Library:
Imports Autodesk.AutoCAD.Interop

' On form drop from Toolbox: FolderBrowserDialog1, 2 buttons , 3 labels and 4 text boxes
' (see picture)

Public Class Form1
    Dim folder As String = ""
    Dim files As List(Of String)

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        files = New List(Of String)
    End Sub
    'Button1 - Text "Batch"
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Try
            ChangeBlocksDBX(files, TextBox1.Text, TextBox2.Text, TextBox3.Text)
            MessageBox.Show("Done")
        Catch ex As Exception
            MessageBox.Show(ex.Message & vbCr & ex.StackTrace)
        End Try

    End Sub
    'Button2 - text "Select Folder"
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim dia As FolderBrowserDialog = Me.FolderBrowserDialog1
        With dia
            .SelectedPath = "C:\Test\BATM\" '<-- change default folder here
            .Description = "Select a folder: "
        End With

        Dim res As Windows.Forms.DialogResult = dia.ShowDialog()
        If res = Windows.Forms.DialogResult.OK Then
            folder = dia.SelectedPath
        End If
        TextBox4.Text = folder
        Try
            Dim dwgFiles() As String = Directory.GetFiles(folder, "*.dwg", SearchOption.TopDirectoryOnly) ''.Select(Function(ff) Path.GetFileName(ff))
            For Each dwgname As String In dwgFiles
                files.Add(dwgname)
            Next dwgname
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
        If files.Count = 0 Then
            MessageBox.Show("no files")

        End If


    End Sub
    Private Sub ChangeBlocksDBX(ByVal dwgFiles As List(Of String), ByVal blkname As String, ByVal atag As String, ByVal aValue As String)

        Dim AcadApp As Autodesk.AutoCAD.Interop.AcadApplication = Nothing
        Dim acadDoc As Autodesk.AutoCAD.Interop.AcadDocument = Nothing

        Dim oEnt As AcadEntity
        Dim oblkRef As AcadBlockReference
        Dim oAtt As AcadAttributeReference
        Dim oBlock As AcadBlock
        Dim oLayouts As AcadLayouts
        Dim oLayout As AcadLayout

        AcadApp = CType(GetObject(, "Autocad.Application"), Autodesk.AutoCAD.Interop.AcadApplication)

        acadDoc = CType(AcadApp.ActiveDocument, Autodesk.AutoCAD.Interop.AcadDocument)

        Dim dbxvers As String = "ObjectDBX.AxDbDocument." & AcadApp.ActiveDocument.GetVariable("acadver").ToString().Substring(0, 2)

        Dim dbxDoc As AxDbDocument

        dbxDoc = acadDoc.Application.GetInterfaceObject(dbxvers)

        Dim dwgName As String

        On Error Resume Next

        For Each dwgName In dwgFiles

            dbxDoc.Open(dwgName)

            oLayouts = CType(dbxDoc.Layouts, AcadLayouts)

            For Each oLayout In oLayouts

                For Each oEnt In oLayout.Block

                    If TypeOf oEnt Is AcadBlockReference Then

                        oblkRef = CType(oEnt, AcadBlockReference)

                        If oblkRef.EffectiveName = blkname Then
                            Dim attVar As Object
                            attVar = oblkRef.GetAttributes
                            Dim i As Integer
                            For i = 0 To UBound(attVar)
                                oAtt = CType(attVar(i), AcadAttributeReference)
                                If oAtt.TagString = atag Then
                                    oAtt.TextString = aValue
                                    Exit For
                                End If
                            Next i
                        End If
                    End If

                Next
            Next
            dbxDoc.SaveAs(dwgName, Nothing)

        Next

        On Error Resume Next
        dbxDoc = Nothing


    End Sub

End Class

 

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 5 of 16
CADbloke
in reply to: muthineni

See my answer at http://forums.autodesk.com/t5/NET/Visual-Studio-2010-Project-Save-As/m-p/4780201#M38907 - basically, use extension methods to cater for API changes and build configs to cater for project references.
- - - - - - -
working on all sorts of things including www.tvCAD.tv & www.CADreplace.com
Message 6 of 16
muthineni
in reply to: CADbloke

I have got it now. I wrote as,

 

Try
                AcadApp = GetObject(, "AutoCAD.Application")
                Threading.Thread.Sleep(500)
            Catch ex As Exception
                AcadApp = CreateObject("AutoCAD.Application")
            End Try

 

I used threading.thread.sleep(500), then it is working in all versions.

 

Thanks alot for all for oyur immediate responses.

Message 7 of 16
seyyed.reza.10
in reply to: muthineni

How can i do this with c#?

Message 8 of 16
_gile
in reply to: seyyed.reza.10

Hi,

 

A C# equivalent would be:

 

string progId = "AutoCAD.Application";
dynamic acadApp;
try
{
    acadApp = Marshal.GetActiveObject(progId);
}
catch
{
    acadApp = Activator.CreateInstance(Type.GetTypeFromProgID(progId));
}


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 9 of 16
seyyed.reza.10
in reply to: _gile

Hi 

Thanks a lot for your solution. i tried your code but AcadApp does not get any value.

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
AcadCircle Circle = default(AcadCircle);
AcadApplication AcadApp = default(AcadApplication);
string progId = "AutoCAD.Application";
dynamic acadApp;
try
{
acadApp = (AcadApplication)Marshal.GetActiveObject(progId);
}
catch
{
acadApp = (AcadApplication)Activator.CreateInstance(Type.GetTypeFromProgID(progId));
}
Double r = Convert.ToDouble(txtboxradius.Text);
Double x = Convert.ToDouble(txtboxX.Text);
Double y = Convert.ToDouble(txtboxY.Text);
Double z = Convert.ToDouble(txtboxZ.Text);
double[] CenterOfCircle = new double[3];
CenterOfCircle[0] = x;
CenterOfCircle[1] = y;
CenterOfCircle[2] = z;
Circle = AcadApp.ActiveDocument.ModelSpace.AddCircle(CenterOfCircle, r);
}
}
}

 

Message 10 of 16
_gile
in reply to: seyyed.reza.10

Hi

 

Take care, C# is case sensitive

 

You declare variable: AcadApp of type AcddApplication but never initialize it (assign it a value).

You declare and initialize a dynamic variable: acadApp.

You try to use the non initialized variable.

 

You can try like this:

 

        private void button1_Click(object sender, EventArgs e)
        {
            string progId = "AutoCAD.Application";
            AcadApplication acadApp;
            try
            {
                acadApp = (AcadApplication)Marshal.GetActiveObject(progId);
            }
            catch
            {
                acadApp = (AcadApplication)Activator.CreateInstance(Type.GetTypeFromProgID(progId));
            }
            while (true)
            {
                try
                {
                    acadApp.Visible = true;
                    break;
                }
                catch { }
            }
            double r = Convert.ToDouble(txtboxradius.Text);
            double x = Convert.ToDouble(txtboxX.Text);
            double y = Convert.ToDouble(txtboxY.Text);
            double z = Convert.ToDouble(txtboxZ.Text);
            double[] centerOfCircle = new double[3];
            centerOfCircle[0] = x;
            centerOfCircle[1] = y;
            centerOfCircle[2] = z;
            AcadCircle circle = acadApp.ActiveDocument.ModelSpace.AddCircle(centerOfCircle, r);
            acadApp.Visible = true;
        }

 

But the OP was about "working in all AutoCAD versions", this is why I purposed the using of late binding with the dynamic type:

 

        private void button1_Click(object sender, EventArgs e)
        {
            string progId = "AutoCAD.Application";
            dynamic acadApp;
            try
            {
                acadApp = Marshal.GetActiveObject(progId);
            }
            catch
            {
                acadApp = Activator.CreateInstance(Type.GetTypeFromProgID(progId));
            }
            while (true)
            {
                try
                {
                    acadApp.Visible = true;
                    break;
                }
                catch { }
            }
            double r = Convert.ToDouble(txtboxradius.Text);
            double x = Convert.ToDouble(txtboxX.Text);
            double y = Convert.ToDouble(txtboxY.Text);
            double z = Convert.ToDouble(txtboxZ.Text);
            double[] CenterOfCircle = new double[3];
            CenterOfCircle[0] = x;
            CenterOfCircle[1] = y;
            CenterOfCircle[2] = z;
            acadApp.ActiveDocument.ModelSpace.AddCircle(CenterOfCircle, r);
        }

 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 11 of 16
seyyed.reza.10
in reply to: _gile

 hi   thank you very much  Heart

 

it work correct when the Autocad  is open but some time when  the Autocad is not open its not working correct and show error.

and i have one more question that how can i put the code that get active object or creat it in one class and use acadApp variable in other class or method?

 

Message 12 of 16
rmcefr
in reply to: norman.yuan

Dear Sir;

Is there any documentation to show each AutoCAD reference library what versions can include,?

for example if Application used AutoCAD 2021 reference library ? what is the AutoCAD versions can be run here? and so on with other versions?

 

generally is there AutoCAD Reference Library can be compatible with all AutoCAD version? or let say most of AutoCAD versions?

 

thanks

Message 13 of 16
JamesMaeding
in reply to: rmcefr

@rmcefr 

Hold on, you are thinking one dll for all versions makes things simpler.

Its actually one of the trickiest things, and makes life hard because you have to be careful about api changes between versions.

I would say to start with the simple case, where you make one dll for each acad version.

It does not mean a copy of the code for each version, you would have the same code files for all versions.

You would simply copy the project and solution files, and change the references to each acad version. You can batch compile all at once using code like:

MSBuild /m "C:\Programming\DotNet\Myprog\AcadXtraR21.sln" /t:Clean;Rebuild /p:Configuration=Release /noconsolelogger

One for each version.

The fact that you are asking how to make one dll implies to me you don't have the skills yet to support such an approach, so don't. I would argue it will be no fun anyway, and am already seeing you ask about api differences.

Catching those is done by trying past code on new versions, and seeing what does not work. Reading documentation and forum posts is part of it too.

Try sticking to "no .com api usage", and just use .net api, and things will go better IMO.

I'm guessing others will have comments about multiple dll's being simpler than one, and posted this because I'm curious of their experience.

thx

 


internal protected virtual unsafe Human() : mostlyHarmless
I'm just here for the Shelties

Message 14 of 16
rmcefr
in reply to: JamesMaeding

@JamesMaeding

Thanks Sir for Comments,

.NET API as I understand need to use commands in AutoCAD environment, 

What about if need to control all commands in "Windows Application" ?

 

Regards

 

Message 15 of 16
JamesMaeding
in reply to: rmcefr

@rmcefr 

It will be easy once you spend about 3 months researching and trying things. You can't just start with the complex case and hope it works. You must be able to untangle the issue that arise, and be confident in the fixes.


internal protected virtual unsafe Human() : mostlyHarmless
I'm just here for the Shelties

Message 16 of 16
rmcefr
in reply to: JamesMaeding

Much appreciated for advise and help
thanks

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