Help - I'm using AutoCAD 2013 64 bit and MS Visual Basic 2010 Express (and Excel 2007), and I'm trying to write VB.NET code to list all xrefs attached to a group of drawings. The list of drawings is in column 1 of an Excel spreadsheet, and I want to list all xref filenames in columns 2 onwards - one row per drawing.
The Excel part works fine. I just wish it was as easy to extract information from DWG files.
I created a "Windows Form Application" project in VB 2010 and added a button to Form1. Clicking on the button runs the code.
When adding references I added "Microsoft Excel 12.0 Object Library" COM for Excel (as per Excel website tutorial), and "acdbmgd.dll" and "acmgd.dll" (both with Copy Local=False) as per AutoDesk .NET tutorial. But I got warning messages saying Acdbmgd.dll and Acmgd.dll target a different processor. Is this different to the Excel COM target processor, or do I need to change the target processor for the whole project (and if so, how)?
I tried adding "AutoCAD 2013 Type Library" COM reference instead of "acdbmgd.dll" and "acmgd.dll" which got rid of the target processor warning messages, and I could then open the dwg files successfully, but still the project crashes.
Here's the code so far...
Imports Excel = Microsoft.Office.Interop.Excel
' do I need to include Imports for AutoCAD here? Various websites list AutoDesk.AutoCAD... imports here, but AutoDesk isn't an available option when I try adding this here - maybe because I have the wrong references?
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim xlApp As Excel.Application
Dim xlWorkBook As Excel.Workbook
Dim xlWorkSheet As Excel.Worksheet
Dim rowDrawing As Integer, colmXref As Integer
Dim szFilename As String
Dim cadApp As AutoCAD.AcadApplication
Dim cadDwg As AutoCAD.AcadDocument
xlApp = New Excel.Application
xlWorkBook = xlApp.Workbooks.Open("c:\test.xlsx", [ReadOnly]:=True) ' ReadOnly is temporary as file is locked due to project crashing
xlWorkSheet = xlWorkBook.Worksheets("Sheet1")
rowDrawing = 1
Do
szFilename = xlWorkSheet.Cells(rowDrawing, 1).Value
If szFilename <> "" Then
cadApp = New AutoCAD.AcadApplication
cadDwg = cadApp.Documents.Open(szFilename, [ReadOnly]:=True)
colmXref = 2
For Each cadBlock As AutoCAD.AcadBlock In cadDwg.Database.Blocks ' crashes here
If cadBlock.IsXRef Then
xlWorkSheet.Cells(rowDrawing, colmXref).Value = cadBlock.Name
colmXref = colmXref + 1
End If
Next
cadDwg.Close()
cadApp.Quit()
releaseObject(cadApp)
releaseObject(cadDwg)
rowDrawing = rowDrawing + 1
End If
Loop Until szFilename = ""
'xlWorkBook.Save() 'temporarily commented out as can only open as ReadOnly as file is locked due to project crashing
xlWorkBook.Close()
xlApp.Quit()
releaseObject(xlApp)
releaseObject(xlWorkBook)
releaseObject(xlWorkSheet)
End Sub
Private Sub releaseObject(ByVal obj As Object) ' this subroutine is copied from Excel tutorial website
Try
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
obj = Nothing
Catch ex As Exception
obj = Nothing
Finally
GC.Collect()
End Try
End Sub
End Class
When I run the project I also get a "A first change exception of type 'System.Runtime.InteropServices.COMException' occurred in MyProject.exe" message. How can I rectify this?
Currently it crashes when it gets to the cadDwg.Database.Blocks line saying "Call was rejected by callee. (Exception from HRESULT: 0x80010001 (RPC_E_CALL_REJECTED))".
The xlsx file and the dwg files refered to in the xlsx file all exist. I've tried running it both with AutoCAD 2013 running and with AutoCAD 2013 not running. Still doesn't work
I feel so close, but what am I missing? I haven't downloaded the "ObjectARX for AutoCAD 2013 (32-bit and 64-bit)" from AutoDesk yet because (i) I have to get a licence, and (ii) it's a very large file, and (iii) I seem to be able to open drawing files without it, but just not access the data I want in the files.
Any help would be gratefully appreciated. I've got 1500+ drawings to look at by the end of the week. If this doesn't work it's back to AutoLisp (and maybe script files, but that's another headache).
Thanks
Since your doing COM automation from standalone EXE, you do not need to download ObjectARX SDK, nor you add reference to acdbmgd.dll (as you already found out. Acad managed APIs exposed in acdbmgd.dll can only be used inside AutoCAD, not from standalone EXE).
You need to change the line of code that crash AutoCAD from
For Each cadBlock As AutoCAD.AcadBlock In cadDwg.Database.Blocks
to
For Each cadBlock As AutoCAD.AcadBlock In cadDwg.Blocks
Norman Yuan
Thanks for such a swift response. Sadly it came up with the same error.
Not to worry, though. I created an AutoLisp file and Script file which work fine, although I'll have to tweak the results a bit once imported into Excel. I won't be bothering with VB.NET again.
(incidentally I have to carry out the same task on all our Microstation DGN files - yes half the office uses AutoCAD and the other half uses Microstation. Fortunately Microstation still comes with a VBA module, so 1000000 times easier)
Just for your interest, this code is working good on A2010
Public Sub TestForForum() Dim xlApp As Excel.Application Dim xlWorkBook As Excel.Workbook Dim xlWorkSheet As Excel.Worksheet Dim rowDrawing As Integer, colmXref As Integer Dim szFilename As String Dim cadApp As AcadApplication Dim cadDwg As AcadDocument xlApp = New Excel.Application xlWorkBook = xlApp.Workbooks.Open("c:\Test\Dwglist.xlsx", Nothing, False) xlWorkSheet = xlWorkBook.Worksheets("Sheet1") rowDrawing = 1 Do szFilename = xlWorkSheet.Cells(rowDrawing, 1).Value If szFilename <> "" Then cadApp = New AcadApplication Dim dwgmgr As AcadDocuments = cadApp.Documents cadDwg = dwgmgr.Open(szFilename, [ReadOnly]:=True) colmXref = 2 For Each cadBlock As AcadBlock In cadDwg.Blocks ' crashes here If cadBlock.IsXRef Then xlWorkSheet.Cells(rowDrawing, colmXref).Value = cadBlock.Name colmXref = colmXref + 1 End If Next cadDwg.Close() cadApp.Quit() releaseObject(cadApp) releaseObject(cadDwg) rowDrawing = rowDrawing + 1 End If Loop Until szFilename = "" xlWorkBook.SaveAs("c:\Test\Dwglist.xlsx") xlWorkBook.Close() xlApp.Quit() releaseObject(xlApp) releaseObject(xlWorkBook) releaseObject(xlWorkSheet) MsgBox("Done") End Sub Private Sub releaseObject(ByVal obj As Object) ' this subroutine is copied from Excel tutorial website Try System.Runtime.InteropServices.Marshal.FinalReleaseComObject(obj) ' this changed by me If obj IsNot Nothing Then obj = Nothing ' this changed by me Catch ex As Exception obj = Nothing Finally GC.Collect() End Try End Sub
~'J'~
Thanks for the revised code. It doesn't work in AutoCAD 2013.
What references did you use? I ask because I get errors with the lines:
Dim cadApp As AcadApplication
Dim cadDwg As AcadDocument
They only work when the Acad... are preceeded by AutoCAD.
Still crashes when it gets to the cadDwg.Blocks line.
(If it's any consolation, I'm now having problems with my Microstation VBA routine - apparently it's not possible to read the data in tags (attribute blocks in AutoCAD speak) in attachments (blocks in AutoCAD speak). CAD is fantastic until you're working on 1000+ drawings and need to automate basic tasks across all the drawings)
I'm using namespace AutoCAD XXX Type library
Then add in the "Imports" region:
Imports Autodesk.AutoCAD.Interop
Hth
~'J'~
Thanks for the reply. I'm using the AutoCAD 2013 namespace, but the text "Autodesk.AutoCAD.Interop" in the Import line gets a green squiggly line and the error message at the bottom of the screen.
"Warning 1 Namespace or type specified in the Imports 'Autodesk.AutoCAD.Interop' doesn't contain any public member or cannot be found. Make sure the namespace or the type is defined and contains at least one public member. Make sure the imported element name doesn't use any aliases. C:\Users\giles\Documents\Visual Studio 2010\Projects\AcadQuery\AcadQuery\Form1.vb 2 9 AcadQuery"
I'm getting AutoCAD 2012 installed on my machine today. So maybe that will avoid all these problems.
Just had AutoCAD 2012 installed on my machine, and even less works now - it doesn't even recognise AcadDocument.
Utterly disappointed. Looks like I'll have to carry out the task manually.
Hello,
I have attached a sample project which I have tried with AutoCAD 2013 and it worked ok.
It is your code that updates the excel file along with the changes outlined in this blog post :
Hope this helps.
Edited :
The sample project is in C# since I wanted to try your code using the sample project from the above blog post.
Converting this to VB.Net should be straight forward.
Hello,
Kindly, can you advise for a solution to the following:
If I build a .Net class library & import acdbmgd & acmgd, I am able to access an AutoCAD document's database & check the xrefs without opening AutoCAD & without opening the document.
What I need is to be able to do the same but from a .Net form application (Standalone), which does not run from within AutoCAD same as Cad's Reference Manager Tool functionality.
Please advise. Thanks.
acadmgd.dll/acmgd.dll can ONLY be used with managed DLL loaded INTO running AutoCAD session/process. So, you must run AutoCAD and netload your managed DLL int to AutoCAD, if your dll references acadmgd.dll/acmgd.dll. After NETLOAD your dll into AutoCAD, it is possible to access drawing information without open it in AutoCAD editor.
If your goal is to create a standalone app, then NO, you cannot use acdbmmd.dll/acmgd.dll. Your best bet would be use AutoCAD COM API. If you do not mind to make thing extra complicated, you could use AutoCAD managed .NET API (i.e. use acdbmgd/acmgd.dll) and expose it as COM. You still need to load the managed DLL into AutoCAD, though), but the extra effort may not be worth it.
In any case (COM, or .NET API as COM from external standalone app), you MUST have AutoCAD running for your task, unless you cough a lot of money for RealDwg license. Since you need AutoCAD running anyway, for your task, building a standalone app is hardly a good choice.
Norman Yuan
Hello Mona,
If you are using AutoCAD 2013, you have one more option. You can use the accoreconsole.exe in addition to the COM API as Norman suggested.
A script file that runs the command line version of the xref command can be used. The accoreconsole.exe can be driven by an external application. You can find an example of accoreconsole being invoked from an external application here :
http://adndevblog.typepad.com/autocad/2012/04/getting-started-with-accoreconsole.html
The script file to print all the existing xrefs can have this :
<<<<<
-xref
?
*
>>>>