.NET

Reply
Contributor
bababarghi
Posts: 19
Registered: ‎05-01-2013
Message 1 of 17 (2,422 Views)

Retrieving block attribute using my VB.NET form application

2422 Views, 16 Replies
05-01-2013 06:28 PM

Hi all,

 

Sorry for my basic type of question in advance.:smileyindifferent:

 

I have already developed my VB.NET Windows Form app (.NET 4.0 in VS2012) which does some Windows operation on roughly hundreds of AutoCAD drawing files(e.g. purely copy/move/rename type of actions).

 

Now I need to tell my app to communicate with AutoCAD 2013 and collect some attributes from a specific existing block in all of these drawings and then replace the collected values with some other values passed to AutoCAD by my Form  application (see diagram below if that helps: )

 

 

img.jpg

 

I had a look to couple of AutoCAD .NET blogs and realised how to make DLL files and leverage NETLOAD tool in AutoCAD afterwards but I am afraid DLL files and NETLOAD are not what I am looking after (correct me if I am wrong).

 

At this stage I am not asking for any coding assistance but rather I would like to clearly know what is the best pathway to achieve my goal described above.

 

Regards

Moji

Mentor
santoshr0114
Posts: 161
Registered: ‎03-21-2012
Message 2 of 17 (2,366 Views)

Re: Retrieving block attribute using my VB.NET form application

05-06-2013 09:25 PM in reply to: bababarghi

Hi,

 

Usually to run a program on hundreds of files, user will not intend to open AutoCAD and run the program. He will expect a Windows Application which does the operation silently in the background without the graphical interface of AutoCAD.

 

But Autodesk recommends to run the program inside AutoCAD.

 

Hope this clears your pathway

Regards
Santosh
Contributor
bababarghi
Posts: 19
Registered: ‎05-01-2013
Message 3 of 17 (2,363 Views)

Re: Retrieving block attribute using my VB.NET form application

05-06-2013 09:35 PM in reply to: santoshr0114

Thanks for the reply  santoshr0114,

 

Well yes and no about being clarified.

 

I dont mind perofrming all operations behind the scene (even prefered) but don't know how to achive that.

 

Currently I have splited my goal to two section:

 

  1. WinForm app will do its job on each and every single input file. This app will load a dll file (developed in next section)
  2. A dll application generated by VB.NET is taking care of all drawing modifications in AutoCAD. Save & close the drawing.

 

Have no freaking idea how to combine these two steps though :smileysad:

 

Suggections welcomed.

 

Cheers

Mentor
santoshr0114
Posts: 161
Registered: ‎03-21-2012
Message 4 of 17 (2,360 Views)

Re: Retrieving block attribute using my VB.NET form application

05-06-2013 10:10 PM in reply to: bababarghi

Your Windows Form should load an instance of AutoCAD.

Once the AutoCAD instance is loaded. run your function to perfom the task

 

To do this outside of AutoCAD and by not using Netload you need to used AutoCAD Interop

 

The Below Sample might get you started

 

Imports Autodesk.AutoCAD.Interop
    Public Function GetAcadApp() As AcadApplication

        Dim progID As String = My.Settings.strAcadProgID
        Dim acApp As AcadApplication = Nothing
        Try
            acApp = DirectCast(Marshal.GetActiveObject(progID), AcadApplication)
        Catch ex As Exception
            Try
                Dim acType As Type = Type.GetTypeFromProgID(progID)
                acApp = DirectCast(Activator.CreateInstance(acType, True), AcadApplication)
            Catch ex2 As Exception
                MessageBox.Show("Cannot create object of type """ & progID & """")

            End Try
        End Try

        If acApp IsNot Nothing Then

        End If

        Return acApp
    End Function

 

 

 

Regards
Santosh
Contributor
bababarghi
Posts: 19
Registered: ‎05-01-2013
Message 5 of 17 (2,331 Views)

Re: Retrieving block attribute using my VB.NET form application

05-07-2013 05:31 PM in reply to: santoshr0114

There was a compilation error with your code:

 

'strAcadProgID' is not a member of '[...].My.Settings'. 

 

  

However, after replacing it by this:

 

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim AppComObj As AcadDocument = Nothing
        Dim ProgId As String = "AutoCAD.Application.19"
        Try
            AppComObj = GetObject(, ProgId)
        Catch ex As System.Exception
            Try
                ' Create a new instance of AutoCAD
                AppComObj = CreateObject(ProgId)
            Catch ex2 As Exception
                MsgBox(ex2.Message)
                Exit Sub
            End Try
        End Try
        AppComObj.Visible = True
    End Sub

I got no compilation error but sadly after triggering the code, this message pops up:

 

2013-05-08_102016.jpg

 

To be more precise, this is how my project reference setup looks like:

 

22.jpg

 

and I have imported followings:

Imports System.IO
Imports Autodesk.AutoCAD.Interop
Imports Autodesk.AutoCAD.Interop.Common

 

Mentor
santoshr0114
Posts: 161
Registered: ‎03-21-2012
Message 6 of 17 (2,315 Views)

Re: Retrieving block attribute using my VB.NET form application

05-07-2013 09:34 PM in reply to: bababarghi

That was just a sample code to get you started. You have to change the code as per your needs.

Anyways the below code works for me.

 

public void OpenAutoCAD()
        {
            const string progID = "AutoCAD.Application";           
            try
            {
                acApp = (AcadApplication)Marshal.GetActiveObject(progID);
            }
            catch
            {
                try
                {
                    Type acType = Type.GetTypeFromProgID(progID);
                    acApp = (AcadApplication)Activator.CreateInstance(acType, true);
                }
                catch
                {
                    MessageBox.Show("Cannot create object of type \"" + progID + "\"");
                }
            }
            if (acApp != null)
            {
                try
                {
                    // By the time this is reached AutoCAD is fully
                    // functional and can be interacted with through code                                       

                    acApp.Visible = false;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(this, "Problem executing component: " + ex.Message);
                }
            }
        }

 convert the same code to vb.net

 

Remove the references of AcCoreMgd, AcDbMgd, AcMgd. 

 

And you are creating a Windows Application(.exe) not a class library(.dll) right?

 

Regards
Santosh
Contributor
bababarghi
Posts: 19
Registered: ‎05-01-2013
Message 7 of 17 (2,309 Views)

Re: Retrieving block attribute using my VB.NET form application

05-07-2013 09:52 PM in reply to: santoshr0114

Thank you so much. Simply added following line to it and it works like a charm:

        Dim acApp As AcadApplication = Nothing

 Regarding your question, I am creating an EXE file at the end of the day. But as I mentioned in previous posts, this EXE application should be able to leverage NETLOAD command in AutoCAD and load my dll library.

 

So, now, can you please tell me how can I inject an OPEN functionality in my 'try...catch' block. i.e. I want to have s/th like this in my try..catch block:

 

OpenDWG("c:\test.dwg")

 

In other words I need to call function to open a dwg document in AutoCAD session which has been just launched invisible.

 

The last step would be calling "NETLOAD" command for my opened *.dwg file. 

 

 

Cheers

Mentor
santoshr0114
Posts: 161
Registered: ‎03-21-2012
Message 8 of 17 (2,311 Views)

Re: Retrieving block attribute using my VB.NET form application

05-07-2013 10:51 PM in reply to: bababarghi

Why do you need to call the netload command when all the fucnionality can be acieved without usig Netload.

 

to open just use AcadDocument doc = AcadApp.Documents.Open(DWGFILEPATH);

and then activate using doc.acivate();

 

then once the document / drawing is active you can perform your task to getting or updating the attributes.

 

Regards
Santosh
Mentor
santoshr0114
Posts: 161
Registered: ‎03-21-2012
Message 9 of 17 (2,278 Views)

Re: Retrieving block attribute using my VB.NET form application

05-09-2013 12:28 AM in reply to: bababarghi

Hi There,

 

Accept this as solution if it has clarified your query

 

 

Regards
Santosh
Contributor
bababarghi
Posts: 19
Registered: ‎05-01-2013
Message 10 of 17 (2,259 Views)

Re: Retrieving block attribute using my VB.NET form application

05-09-2013 08:35 PM in reply to: santoshr0114

Dealing with drawing via COM sounds more pleasant to me but I dont know how to convert my class library codes to be acceptable for COM. I had some codes in my DLL file to purge and also to update some attributes.

 

Here is the code which I was using to Purge (in DLL file):

 

Private Sub PurgeBlocks()
            Dim doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim ed As Editor = doc.Editor
            Dim db As Database = doc.Database
            Using trans As Transaction = db.TransactionManager.StartTransaction()
                Dim bt As BlockTable = TryCast(trans.GetObject(db.BlockTableId, OpenMode.ForWrite), BlockTable)
                For Each oid As ObjectId In bt
                    Dim btr As BlockTableRecord = TryCast(trans.GetObject(oid, OpenMode.ForWrite), BlockTableRecord)
                    If btr.GetBlockReferenceIds(False, False).Count = 0 AndAlso Not btr.IsLayout Then
                        btr.[Erase]()
                    End If
                Next
                trans.Commit()
            End Using
        End Sub

 And these ones to update some attributes(in DLL file):

 

Private Sub UpdateAttributesInDatabase(db As Database, blockName As String, attbName As String, attbValue As String)
            Dim doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim ed As Editor = doc.Editor
            ' Get the IDs of the spaces we want to process and simply call a function to process each
            Dim ModelSpaceId As ObjectId
            Dim PaperSpaceId As ObjectId
            Dim Transactn As Transaction = db.TransactionManager.StartTransaction()
            Using Transactn
                Dim bt As BlockTable = DirectCast(Transactn.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
                ModelSpaceId = bt(BlockTableRecord.ModelSpace)
                PaperSpaceId = bt(BlockTableRecord.PaperSpace)
                Transactn.Commit()  
            End Using
            UpdateAttributesInBlock(ModelSpaceId, blockName, attbName, attbValue)
            UpdateAttributesInBlock(PaperSpaceId, blockName, attbName, attbValue)
            ed.Regen()
        End Sub
'============================================================
        Private Sub UpdateAttributesInBlock(btRecordId As ObjectId, blockName As String, attbName As String, attbValue As String)
            Dim doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim db As Database = doc.Database
            Dim ed As Editor = doc.Editor
            Dim tr As Transaction = doc.TransactionManager.StartTransaction()
            Using tr
                Dim btRecord As BlockTableRecord = DirectCast(tr.GetObject(btRecordId, OpenMode.ForRead), BlockTableRecord)
                For Each entId As ObjectId In btRecord
                    Dim ent As Entity = TryCast(tr.GetObject(entId, OpenMode.ForRead), Entity)
                    If ent IsNot Nothing Then
                        Dim br As BlockReference = TryCast(ent, BlockReference)
                        If br IsNot Nothing Then
                            Dim bd As BlockTableRecord = DirectCast(tr.GetObject(br.BlockTableRecord, OpenMode.ForRead), BlockTableRecord)  'to see whether it's a block with the name we're after
                            If bd.Name.ToUpper() = blockName Then               ' Check each of the attributes...
                                For Each attReferenceId As ObjectId In br.AttributeCollection
                                    Dim obj As DBObject = tr.GetObject(attReferenceId, OpenMode.ForRead)
                                    Dim attReference As AttributeReference = TryCast(obj, AttributeReference)
                                    If attReference IsNot Nothing Then                    'to see whether it has the tag we're after
                                        If attReference.Tag.ToUpper() = attbName Then     ' If so, update the value and increment the counter
                                            attReference.UpgradeOpen()
                                            attReference.TextString = attbValue
                                            attReference.DowngradeOpen()
                                        End If
                                    End If
                                Next
                            End If
                            UpdateAttributesInBlock(br.BlockTableRecord, blockName, attbName, attbValue)    ' Recurse for nested blocks
                        End If
                    End If
                Next
                tr.Commit()
            End Using
        End Sub

 Any idea for getting their equivalent for COM mode? I dont mind using any other code as long as it provides my the following functionalies:

  • Purge
  • UpdateAttribute(TagName As String, NewValue As String)

 

Alternatively, if I could not find any solution for conversion, how can I load a DLL code using "NETLOAD" command?

You are not logged in.

Log into access your profile, ask and answer questions, share ideas and more. Haven't signed up yet? Register

Announcements
Are you familiar with the Autodesk Expert Elites? The Expert Elite program is made up of customers that help other customers by sharing knowledge and exemplifying an engaging style of collaboration. To learn more, please visit our Expert Elite website.

Need installation help?

Start with some of our most frequented solutions to get help installing your software.

Ask the Community