Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Testing for the validity of an ActiveX Object

10 REPLIES 10
Reply
Message 1 of 11
Gary_J_Orr
759 Views, 10 Replies

Testing for the validity of an ActiveX Object

I have tried many approaches to testing for the validity of an ActiveX Object while running a "remote" acad session from a Vlisp program... IE: I run a function in a loop to process files in turn, all using the remote session to do the work on each file while controlling the whole from the initial session. If the remote application gets shut down while processing file 1, I want to check for the application's validity prior to attempting to process file 2.

 

I have tried using vl-catch-all-apply to test against the validity of a property call:

 

(setq TestAcad (vl-catch-all-apply 'vla-get-FullName (list GJO_NewAcadObj)))

(if (/= T (vl-catch-all-error-p TestAcad))

...

 

This worked about 80% of the time. But sometimes the thing would just freak out on the evaluation of the ActiveX Object, (even when just creating the list for the call). Along the way I discovered that when an Object became invalid/disconnected it would lose the object type from the reference...

 

Valid objects:

_$ (eval GJO_DwgObj)

#<VLA-OBJECT IAcadDocument 09bd837c>

_$ (eval GJO_DocsObj)

#<VLA-OBJECT IAcadDocuments 15c980fc>

_$ (eval GJO_NewAcadObj)

#<VLA-OBJECT IAcadApplication 1e8f8a3c>

 

Invalid objects (after remote session was manually closed):

_$ (eval GJO_DwgObj)

#<VLA-OBJECT 09bd837c>

_$ (eval GJO_DocsObj)

#<VLA-OBJECT 15c980fc>

_$ (eval GJO_NewAcadObj)

#<VLA-OBJECT 1e8f8a3c>

 

So I changed my test method to:

(if (wcmatch (vl-prin1-to-string (eval GJO_NewAcadObj)) "*IAcadApplication*")

...

 

This approach works perfectly since I can then test to see if the objects have become disconnected by evaluating the string expression of the object's current status.... connected/valid vs disconnected /invalid

 

With one MAJOR exception: processing speed. It always works if I'm running "line-by-line" in testing, or if I'm animating the evaluation, or if I put a breakpoint to test the values manually, or anything that slows the process down. And it always works for the Document Object itself.

But...

It sometimes takes the ACAD Application Object longer to shut down (and therefore become disconnected/invalid) than it takes for the routine to make the next call to the object, by which time it could have become disconnected/invalid... My goal is to catch the "disconnection" immediately so I can take additional actions (short of relying on the error handler, which could be launched by any other number of possible problems)

 

I can't use events because I'm controlling one session of Acad from within another and I can't access the remote session's events via ActiveX, especially through Vlisp... or at least not in any way that I have found (I could if I went to a VB/C++ utility but not from within Lisp...)

I tried using the Document Collection Object hoping that it would shut down as quickly as a Document Object does, but to no avail... it, too, takes too long to become invalid/disconnected during shutdown of the remote session...

So, the question is: how can I monitor for the BeginQuit event of a remote session without an event reactor (or is there a way to monitor such events from a remote session that I have yet to find)?

Or...

How do I test to see if the remote session has been shutdown in a manner that will always work as quickly as the controlling function is running?

Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
10 REPLIES 10
Message 2 of 11
dbroad
in reply to: Gary_J_Orr

Gary,

 

Could you define "remote" autocad session? Is it another term for using the multiple document access within the current application session, interfacing with a second autocad session, using objectDBX, AutoCAD Core, or using Autodesk remote

(as here:  http://www.autodesk.com/products/remote/overview )?

Architect, Registered NC, VA, SC, & GA.
Message 3 of 11
Gary_J_Orr
in reply to: dbroad

dbroad:
Per your response it would be "interfacing with a second autocad session"
Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 4 of 11
dbroad
in reply to: Gary_J_Orr

Thanks.  Perhaps if I understood the purpose for running a remote session via LISP, I might be able to help.  I have only used ObjectDBX other than running within the current session.  Are you trying to monitor other users?  Are you trying to override or support a drafter's actions?  If not, why the connection between sessions?

 

Just a gut feeling but LISP (which is basically a single document language) is poorly suited for the purpose.

Architect, Registered NC, VA, SC, & GA.
Message 5 of 11
Gary_J_Orr
in reply to: dbroad

this could take a while through the discussion group so feel free to email me directly until we get to something that could be beneficial to anyone else but...
I'm building my own version of "scriptpro" (and the like) for processing either script files or a given function from a lisp file on all the files in a given directory and or sub-directories... along with logging the results, including where it gets to before bombing out if such happens... yet robust enough that the user can close a document in the secondary session and the routine will log that failure and continue processing the remainder...
By using Lisp over building a standalone app I gain the power of the integrated interface so I don't have to build different versions for different versions of acad, etc...
Not to mention not having to build installers and the like...
By launching a seperate session of Acad to do the actual work I can compensate for SDI vs MDI...
I only have the one scenario to address (and even it is currently covered by my error handler), but I'm a perfectionist and want that potential "final" failure to be added to my log files...
Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 6 of 11
dbroad
in reply to: Gary_J_Orr

Another question: How are you accessing the remote autocad session vlax-create-object, vlax-get-object, or vlax-get-or-create-object?

It would seem that for your application, the vlax-create-object would create a more stable connnection that would more likely run in the background. I assume your code would do something similar to the following

 

(setq xacapp (vlax-create-object "Autocad.Application"))
(setq xdocs (vla-get-documents xacapp))
(setq xdoc (vla-item xdocs 0))
(setq xmsp (vla-get-modelspace xdoc))
(setq xl (vla-addline xmsp (vlax-3d-point '(0 0 0)) (vlax-3d-point '(1 1 0))))
(vla-saveas xdoc "c:\\Mytest")
(vla-close xdoc)
(mapcar 'vlax-release-object (list xl xmsp xdoc xdocs xacapp))

 If so, in what case would you unexpectedly see the external AutoCAD application closing without you knowing about it?

Architect, Registered NC, VA, SC, & GA.
Message 7 of 11
Anonymous
in reply to: dbroad

Total stab in the dark here, but...

 

(if (vla-sendcommand doc# "...?)

Message 8 of 11
Gary_J_Orr
in reply to: dbroad

I'm including a description of the process (and what you'll find in the attached "GJO_FLA.lsp" file)

C:GJO_FLA

Is the primary function. It gathers user options (process sub folders?,  if sub folders flag was set it gets the Logging preference (main folder or each subfolder), Log file name and starting directory, routine type (Lisp or script), routine path, command string in "lisp" format (if required), and then launches the secondary Acad Session.

Once setup options are complete and ACAD has been acquired it passes control over to:

 

GJO_FLA_runfiles

-gathers the files in the current directory then passes each file name to one of two functions to actually perform the work:

GJO_FLA_Process_SDI – for processing the file in a SDI environment

GJO_FLA_Process_MDI – for processing in an MDI environment

Logging information is returned to GJO_FLA_runfiles

Once all files in the directory have been processed the results are logged

If the "recurse" flag has been set to process sub-directories each directory is sent back through GJO_FLA_runfiles for processing

 

I've been fighting this for so long now that I created another function that allows me to pass a string to it to predefine all of the user option variables and pass them on to the primary function.

GJO_FLA_Runquiet

 

I have provided a set of test files in a zip file attachment and attached the file "GJO_FLA.lsp", which is the function that I'm building.

 

After unzipping the files you can open the file "shortcuts.txt" and replace all strings of " E:\\Resource\\Source\\ " with the path (lisp formatted) to where you unzipped the "Parser" zip file to.

 

You can then load "GJO_FLA.lsp" file. After loading you can copy each line in turn from the edited "shortcuts.txt" file and paste each into the command line of your autocad (or into the Vlisp console) to see them function.

 

When you get to the line that ends in "(ForceError)") the secondary ACAD session will need to be activated (it should be in your Windows command bar) and you will have to make decisions as to what to do for the routine that caused the "hang-up"...

 

On the first drawing you may choose to enter a point to complete the command that erred out, on the next you may just hit enter or cancel to cancel that command, on the next (if in MDI) you may choose to simply close the active document or (if in SDI) you could hit "new" from a toolbar button to force close the current doc and log the failure and start a new one to allow processing to continue... on the next you may decide that you are encountering too many errors and have a serious flaw in the routine that you are scripting and decide to close the secondary application entirely to stop the processing...

 

This is where I want to catch the error, before the runfiles function tries to process the next file...

Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 9 of 11
Gary_J_Orr
in reply to: Anonymous

any kind of VLA call on the application Object will cause an error, even when I include it within a vl-catch-all-apply stmt, if the object has become invalid due to it's having been closed...

the problem that I'm facing is that, while I have found a few ways to test against the validity of the object itself, it sometimes reports as still being valid just long enough to get to some other point and some other call due to how long it takes for the app to close enough to actually become invalid... The same is true for the docs collection object as well...

the only thing that seems to become invalid immediately is an actual document object, and since that may have already closed but I want to continue processing the next file, I can't use that as my test to see if the app is still available....

I've tried testing for the availability of a given property or method but the VLAX-method-available-p and VLAX-Property-Available-P (ware typos?) functions both always return nil on the application object (even when it is still valid) for some reason
Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 10 of 11
dbroad
in reply to: Gary_J_Orr

Gary,

Just to let you know I've seen your posts and briefly scanned your code.  I can't see any obvious flaws except a possible vulnerability by setting the background autocad process visible.

 

Is it possible, instead of running all your code in the primary AutoCAD session through to the secondary session, to have the secondary session just load it from within that background session and run all your code from the background processs?  The background code would no longer need to rely completely on being synchronous and could report results by writing to a text file.  I could imagine a scenario where the code run in the main program launches a command within the background acad process to load and run the code within the document being processed. 

Architect, Registered NC, VA, SC, & GA.
Message 11 of 11
Gary_J_Orr
in reply to: dbroad


@Anonymous wrote:

... possible vulnerability by setting the background autocad process visible...

 


That is actually intentional... it provides a way to correct the "occassional" error of a script/routine glitching on a few files but processing the rest ok... makes for a more robust app for me. If I'm processing a couple of hundred blocks and the script/function only errors on 6 I can either manually escape the function or close the drawing on each of those six manually without the app bailing entirely... not to mention the possibility of a poorly written routine causing the function to pause for user input that it never gets because the user can't see what is going on and causing everything to hang...

as for:


@Anonymous wrote:

Is it possible, instead of running all your code in the primary AutoCAD session through to the secondary session, to have the secondary session just load it from within that background session and run all your code from the background processs?  The background code would no longer need to rely completely on being synchronous and could report results by writing to a text file.  I could imagine a scenario where the code run in the main program launches a command within the background acad process to load and run the code within the document being processed. 


My goal is to build this as an "open" single-source lsp file for easy portability. I'll put in secondary checks at different levels if I need to... or even a timed pause after each file... before I go that route. Not that it isn't a valid suggestion mind you, just that it contradicts one of my primary goals.

Truth is I could do this in VB easily enough because I could create the ACAD Object "With Events" and simply monitor for the "BeginClose" event... but, again... ease of portability between environments and versions is a goal.

Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost