I am writing a VB application that loads Autocad, opens a drawing, reads drawing and then closes it.
I open Autocad using CreateObject.
I open drawing using AcadApp.Documents.Open(FileName, True)
I then wait for the AcadApp.EndOpen event to fire
I then read drawing
I then try to close drawing using AcadApp.ActiveDocument.Close(False)
but it fails with Call was rejected by callee. (Exception from HRESULT: 0x80010001 (RPC_E_CALL_REJECTED))
Solved! Go to Solution.
imho you don't need to wait for EndOpen-event (as long you are not working with multithreading).
The code after the line "...Documents.Open..." will continue with the next code-line after the drawing is loaded into editor (and not before). So I see no necessarity for handling that with an event.
And the event may be the source of your problem, because when you try to start the "...ActiveDocument.Close...." while you are in the event-handler, don't forget that this event-handler is (indirectly) part of your document-object ==> you can't close the doc while you are "in the document" - or with other words - the document is locked because a document-based-event is active.
Try to rewrite the code without this event-handler and that may be the solution. If not ... let use see a minimum code snippet that makes it for us possible to reproduce the problem.
Good luck, - alfred -
Thanks to you both, and so I decided to write the code as an inprocess class.
The code is this:
Friend WithEvents AcadDoc As Document Friend WithEvents DocCol As DocumentCollection <CommandMethod("OMREADTITLES")> Public Sub OMREADTITLES() fls = Directory.GetFiles(cFolder) For Each n As String In fls If n.ToUpper.EndsWith("DWG") Then AcadDoc = DocCol.Open(n) GetTitleSheets() End If Next For Each doc As Document In Application.DocumentManager doc.CloseAndDiscard() Next End Sub
GetTitleSheets is a routine that reads title blocks and extracts their attributes. All works well.
CloseAndDiscard returns error - Drawing Busy
I don't understand why. Each drawing is opened as Read Only. I don't alter the database (at least I don't think so)
if you don't use the events remove the "WithEvents" phrase in the declaration.
>> BUT [...] CloseAndDiscard returns error - Drawing Busy
That is not a save way: to close all documents, also that one that has an open command ... your command!
However you can try to change the calling-attributes in that way:
<CommandMethod("OMREADTITLES", Autodesk.AutoCAD.Runtime.CommandFlags.Session)> _
Just as an additional input: I would open one drawing, do the modifications needed and close it then. Don't open all documents parallel. It's not only a question of memory and performance, it's also a questions of how save will your documents be if the file 150 crashes AutoCAD because of any defect ==> so all your previously opened files are unsave in this case.
And one more input: why opening the drawings in the editor? Do you do some Zoom-modifications .... or any functions that need the editor? Because opening just the database will be much more efficient than loading the drawings into the editor.
For that look to "New Autodesk.AutoCAD.DatabaseServices.Database(....)" and "...Database.ReadDwgFile(..."
- alfred -
Thanks for this - food for thought! Never thought about just using the database.
The withevents is used as a also trap events.
I did originally try to close the dwg in the main loop - same error.
But logically, my command will be active so how to close.
So I tried this:-
<CommandMethod("OMREADTITLES", Autodesk.AutoCAD.Runtime.CommandFlags.Session)> Public Sub OMREADTITLES() fls = Directory.GetFiles(cFolder) For Each n As String In fls If n.ToUpper.EndsWith("DWG") Then AcadDoc = DocCol.Open(n) GetTitleSheets() AcadDoc.CloseAndDiscard() End If Next End Sub
Still get the Drawing Busy
This statement defines your current doc:
AcadDoc = DocCol.Open(n)
Save your current drawing e.g. "Drawing1" previously in a varaible and before closing the "AcadDoc" make your "Drawing1" active.
Plus ,,, have you tried changing the CommandMethod-Attributes?
>> The withevents is used as a also trap events.
As long as your routine "GetTitleSheets" does all modifications you can disable the eventhandling .... just for test! Do you get the exceptions then also or not.
- alfred -
Thanks very much - solved!
For Each n As String In fls If n.ToUpper.EndsWith("DWG") Then Dim db As New Database(False, True) db.ReadDwgFile(n, FileOpenMode.OpenForReadAndAllShare, False, "") GetTitleSheets(db) End If Next
No need to close drawings etc. I have got this right?
well there are some parts to be done after opening a database:
plus don't forget to save ;-)
Have a nice day, - alfred -
OK and thanks again.
Actually I don't save, but I do write data to an external file.
BUT - now I have a new question.
OK. The code works great inside AutoCAD. I also can attach VS to the Acad process and check every line. All seems fine.
However I actually have an app that loads Autocad using CreateObject etc. I will not be showing it when debugged.
Now I really want to execute the code from my app which I do by sending message to acad.
App.ActiveDocument.SendCommand(cnEsc & cnEsc & "OMREADTITLES ")
AutoCad receives message and executes BUT I get a file sharing error.
If I stop VS, and execute the command inside Acad, it does work properly.