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

Listing all xrefs attached to a group of (unopened) drawings

11 REPLIES 11
Reply
Message 1 of 12
gilesacad14
2767 Views, 11 Replies

Listing all xrefs attached to a group of (unopened) drawings

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

Tags (3)
11 REPLIES 11
Message 2 of 12
norman.yuan
in reply to: gilesacad14

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

Message 3 of 12
gilesacad14
in reply to: gilesacad14

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)

Message 4 of 12
Hallex
in reply to: gilesacad14

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'~

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 5 of 12
gilesacad14
in reply to: Hallex

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)

Message 6 of 12
Hallex
in reply to: gilesacad14

I'm using namespace AutoCAD XXX Type library

Then add in the "Imports" region:

 

Imports Autodesk.AutoCAD.Interop

Hth

 

~'J'~

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 7 of 12
gilesacad14
in reply to: Hallex

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.

Message 8 of 12
gilesacad14
in reply to: gilesacad14

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.

Message 9 of 12
Balaji_Ram
in reply to: gilesacad14

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 :

http://through-the-interface.typepad.com/through_the_interface/2010/02/handling-com-calls-rejected-b...

 

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.

 

 

 

 

 

 



Balaji
Developer Technical Services
Autodesk Developer Network

Message 10 of 12
mona.akkoush
in reply to: gilesacad14

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.

Message 11 of 12
norman.yuan
in reply to: mona.akkoush

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.

Message 12 of 12
Balaji_Ram
in reply to: mona.akkoush

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

?

*

>>>>



Balaji
Developer Technical Services
Autodesk Developer Network

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