Hello to everybody.
I have tried to write a code that can update attribute data in block of autocad file.
I found alot of example in this forum, but i dont know why my programe can not work.
My PC is winXP, VS2008, autocad2009.
1. This code is work ofcouse:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
MsgBox("hello")
End Sub
2. But this one does not work:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
MsgBox("hello")
Dim myBT As DatabaseServices.BlockTable
End Sub
As long as i insert in the code which relative to reference .dll; i got error: "The specified module could not be found. (Exception from HRESULT: 0x8007007E)"
It means that problem is my PC sysem, sofware... not about the code.
Please help me to fix it, i spent two but still not found the reason.
Here the code i used:
Function PopulateOIDCs(ByVal BlockName As String) _
As DatabaseServices.ObjectIdCollection
Dim myBT As DatabaseServices.BlockTable
Dim myBTR As DatabaseServices.BlockTableRecord
Dim myBTRE As DatabaseServices.SymbolTableEnumerator
Dim myDB As DatabaseServices.Database
Dim myTransMan As DatabaseServices.TransactionManager
Dim myTrans As DatabaseServices.Transaction
Dim myOIDs As New DatabaseServices.ObjectIdCollection
Dim myOIDs2 As DatabaseServices.ObjectIdCollection
Dim I As Long
Dim acDoc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
myDB = acDoc.Database
myTransMan = myDB.TransactionManager
myTrans = myTransMan.StartTransaction
myBT = myDB.BlockTableId.GetObject(DatabaseServices.OpenMode.ForRead)
myBTR = myBT(BlockName).GetObject(DatabaseServices.OpenMode.ForRead)
myOIDs2 = myBTR.GetBlockReferenceIds(True, False)
For I = 1 To myOIDs2.Count
myOIDs.Add(myOIDs2.Item(I - 1))
Next
myBTRE = myBT.GetEnumerator
While myBTRE.MoveNext
myBTR = myBTRE.Current.GetObject(DatabaseServices.OpenMode.ForRead)
If myBTR.IsLayout = False Then
Select Case myBTR.IsAnonymous
Case True
myOIDs2 = myBTR.GetBlockReferenceIds(True, False)
If myOIDs2.Count > 0 Then
Dim myBRef As DatabaseServices.BlockReference
myBRef = myOIDs2(0).GetObject(DatabaseServices.OpenMode.ForRead)
Dim myBTR2 As DatabaseServices.BlockTableRecord
myBTR2 = myBRef.DynamicBlockTableRecord.GetObject( _
DatabaseServices.OpenMode.ForRead)
If myBTR2.Name.CompareTo(BlockName) = 0 Then
For I = 1 To myOIDs2.Count
myOIDs.Add(myOIDs2.Item(I - 1))
Next
End If
End If
End Select
End If
End While
myTrans.Dispose()
myTransMan.Dispose()
Return myOIDs
End Function
When you say "but this doesn't work" I assume you mean that's when you are getting the COM error HRESULT: 0x8007007E? If yes, make sure that
1. acdbmgd in your project references is pointing to the correct autocad version's directory.
2. your DLL is registered with COM (regasm /tlb yourdll.dll) and you are netloading the registered version not some old version.
Just my guess:
You are doing an stand-alone EXE application, aren't you? If so, you CANNOT use AutoCAD managed .NET API DLLs (acadmgd.dll/acmgd.dll).
Norman Yuan
Dear sszabo;
"but this doesn't work" I assume you mean that's when you are getting the COM error HRESULT: 0x8007007E? -> Right.
1. acdbmgd in your project references is pointing to the correct autocad version's directory. --> I add .dll reference from the folder that install autocad.
2. your DLL is registered with COM (regasm /tlb yourdll.dll) and you are netloading the registered version not some old version. -> could you explain more?
Note: i format my PC, install VS and autocad. Can not happen that there is old .dll version.
Please help!
Dear mornan.yuan
Yes, im making an stand-alone .exe application.
Which case i can use "AutoCAD managed .NET API DLLs (acadmgd.dll/acmgd.dll)"?
Now, for my application / stand-alone .exe which way i should follow?
Please help!
I assumed you were working on an in-process DLL project. norman.yuan is correct: you cannot do this from standalone EXE. If you must control ACAD session from standalone EXE you have several options:
1. Write an In - PROC COM dll and expose it through .NET remoting or WCF to standalone applications
2. Write in proc .NET dll and do the same as above.
There is no way you can avoid the NETLOAD command either way. You cannot use acdbmgd, accoremgd acmgd etc from standalone exe projects.
Just my opinion:
1. Doing an EXE to automate AutoCAD is rarely an best solution, especailly the target user is AutoCAD user: If they use AutoCAD with their computer, why they have to run another application, which requires AutoCAD being running?
2. If you determined the external EXE app is the way to go, you can easily talk to AutoCAD from your app via AutoCAD's COM API. For your task (update attribute in block), the COM API is easy enough and more than enough to your task;
3. If you do not mind to make thing unnecessarily complicated, you can create DLL in .NET API and expose it to COM. Then you need to NETLOAD the DLL into AutoCAD before your app can communicate to your code running inside AutoCAD via COM.
4. You can also do DLL in .NET API and expose it via WCF endpoint. Then you can create a pure NET EXE app that communicate to your code in AutoCAD via WCF. Again, if you do not mind to make things more complicated to the task in hand.
Better and easy solution might be just doing it inside AutoCAD, because you need to run AutoCAD anyway.
Norman Yuan
Dear norman and sszabo
The reason is i want to have a programe that automactic open alot of autocad drawing and take data from database and put data to attribute value.
And also after change attribute value, it can connect to printer to print.
Could you help me to define which way is the best?
Just write your code that calls into ACAD core functionality as a COM DLL, register it using regasm yourdll.dll and write a standalone APP that connects to the running ACAD session, netloads your DLL and calls your functions such as PopulateOIDCs inside that DLL either via COM or .NET:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim progID As String = "AutoCAD.Application.17"
Dim acApp As AcadApplication
acApp = Marshal.GetActiveObject(progID)
acApp.Visible = True
acApp.ActiveDocument.SendCommand("(command " & Chr(34) + "NETLOAD" & Chr(34) & ConvertToDoubleSlash("yourfull/path/to/yourdll.dll") & ")")
End Sub
You might have to fiddle with the exact command syntax, haven't actually ran it.
Dear sszabo
The code got this error: "ConvertToDoubleSlash is not declared". Could you fix it?
Honestly, im newbie with this.
Thank so much.
Dear friends,
I have solved problem with this code:
--------------------------
Const progID As String = "AutoCAD.Application.17"
Dim acApp As AcadApplication = Nothing
Try
' Intentar obtener la instancia activa
acApp = DirectCast(Marshal.GetActiveObject(progID), _
AcadApplication)
Catch
' Si se produce un error
Try
' Crear una instancia
Dim acType As Type = Type.GetTypeFromProgID(progID)
acApp = DirectCast(Activator.CreateInstance(acType, True), _
AcadApplication)
Catch
' Error ¿Esta Acad instalado?
End Try
End Try
If acApp IsNot Nothing Then
acApp.Documents.Open("E:\drawing1a.dwg")
acApp.ActiveDocument.SendCommand("(command " & Chr(34) & "NETLOAD" & Chr(34) & " " & Chr(34) & "C:/Program Files/AutoCAD 2009/AcDx.dll" & Chr(34) & ") ")
End If
----------------------------------
But now how i can change the value of attribute through my .exe application? Please help me? ^^ thank alots.
sszabo,
But now how i can change the value of attribute through my .exe application? Please help me? ^^ thank alots.
1st method.
You can place your function in a new class project that has an interface exposing your function, compile the DLL yourdll.DLL and register it with COM. Once ready you can create a new project for your exe, add your dll as a reference and you can get the COM interface with GetInterfaceObject() or with GetActiveObject() just as you did above. Then you can either netload yourdll.DLL (not ac*.dll as you did above!) manually from ACAD or programatically via COM API using your interface object and then call your function. That's the easiest.
2nd method.
You can also create an in proc WCF server runnning inside autocad and talk to it from a WCF client running anywhere in the world as described in this video:
http://au.autodesk.com/?nd=event_class&jid=610987&session_id=7182
If you have problems let me know I might have some time this weekend to code up a simple example or find something on the web.
sszabo,
Thank for your help!
I would like to use solution 1, but not clear understand. Cuold you help me to make a code example.
Please!!!!!
http://through-the-interface.typepad.com/through_the_interface/2007/12/launching-autoc.html
for more google: acad progID
or: acad Marshal.GetActiveObject
Thereare other ways too, for instance you could use acCtrl.dll:
http://through-the-interface.typepad.com/through_the_interface/2008/03/embedding-autoc.html
Dear sszabo,
Now i know how to make it.
I will inform if my programe can work fullly.
Thank alot.
If one day you come to VietNam, please contact me! ^^
Can't find what you're looking for? Ask the community or share your knowledge.