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.
Solved! Go to Solution.
Solved by muthineni. Go to Solution.
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.
Norman Yuan
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
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.
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); } } }
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); }
hi thank you very much
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?
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
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
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
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