I have an old set of useful VBA functions, that I will enhance by adding some ObjectARX functionality, developed with Visual Basic .NET.
Essentially it will be a VBA project that calls fast ObjectArx functions.
So I built a small objectArx test class, it just adds simple objects to the drawing. DLL is loaded into Autocad (with NETLOAD), and activated through command line. It works great.
Next step is calling the ObjectARX methods from VBA. This can be achieved in 2 ways:
- Registering DLL for COM interop.
- Exporting DLL functions.
So first tried as COM object.
I compiled the ObjectARX project for COM interop, exposing the class. The resulting DLL was added to the old VBA project as COM reference, showing the ObjectARX class successfully. The class is now visible from VBA, I can instantiate it, I can call its methods.
Now comes the issue: The ObjectARX methods that do readonly operations work at full speed. However, the ObjectARX methods that do write operations into Autocad database FAIL (throwing eLockViolation exception). Seems like VBA is locking Autocad database, so that ObjectARX methods can't write.
For example, ObjectARX methods that have lines like this will fail when called from a VBA macro:
[...] Dim btr As BlockTableRecord = tm.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite, False) [...]
(Note that this line opens a database record for write operation).
When DLL is called by exporting its functions, for accessing them with the classic
DECLARE Sub myFunc LIB "myLibrary.dll" (byval param...)...
(BTW a complex process for me, achieved thanks to great tool "ExportDLL" for .NET)
then the result is the same: Methods that do write operations to Autocad database FAIL.
So, the problem is that VBA blocks all intents of ObjectArx methods to get write permissions to Autocad database, no matter if called through COM, or DLL exporting. And only when called from VBA!
If called from Autocad command line they work, without changing any line of code.
Why does VBA lock Autocad database for writing?
ObjectARX for Autocad 2012
Visual Studio 2010 (VB .NET)
Solved! Go to Solution.
A bit backwards? A gigabit backwards is more accurate.
And yes, of course you are right.
To help other people, I leave this sample to materialise your answer, please correct me if wrong:
Dim db As Database = Application.DocumentManager.MdiActiveDocument.Data
base Dim tm As Autodesk.AutoCAD.DatabaseServices.TransactionManag er = db.TransactionManager Dim lock As DocumentLock = Application.DocumentManager.MdiActiveDocument.Lock Document Dim ta As Transaction = tm.StartTransaction() Try Dim bt As BlockTable = tm.GetObject(db.BlockTableId, OpenMode.ForRead, False) Dim btr As BlockTableRecord = tm.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite, False, True) ' ... do whatever ... ta.Commit() Finally ta.Dispose() lock.Dispose() End Try
FYI You only have to lock the document when:
Whereever possible, you should run your commands from the Modal (document) context as the session will be automatically handled by AutoCAD for you.