lamensterms Posted February 10, 2016 Share Posted February 10, 2016 Hey, We're having an ongoing issue with some of our LISP routines, specifically the error trapper/handler. The problem is that sometimes upon 'error', too many actions will be undone. My assumption is... (and I'm happy to have this disputed)... one LISP routine's error handler is using "UNDO" "BACK", but the routine itself does not place an "UNDO" "MARK". So upon 'error' the trapper is issuing "UNDO" "BACK" and undoing to the previous MARK set, not one that should be in the routine being crashed. Does this sound right? Having said all that, does anyone have any suggestions on how to find which routine would be stuffing it up? Below is the code for a routine that undid everything (well.. back to the previous mark) upon 'error'. But this routine does have a "UNDO" "MARK" set... so it shoot my theory down. Either way, I'm struggling to solve this one and would greatly appreciate any help in uneathing the guilty routine. Thanks a lot. (defun uzerr (s) (command "undo" "b") (prompt "\n*Program Terminated***UZ.lsp ERROR MESSAGE*") (setq *error* exi) (princ) ) (Defun c:UZ (/ pnt1 pnt2 os orth) (setq uzcmde (getvar "cmdecho")) (setvar "cmdecho" 0) (command "undo" "m") (setq exi *error*) (setq *error* uzerr) (setq OS (getvar "osmode")) (setq ORTH (getvar "orthomode")) (setvar "osmode" 512) (command "UCSICON" "ON") (setq PNT1 (getpoint "\nPick first point, nearest to - or press enter to turn off nearest osnap...")) (setvar "orthomode" 0) (if (= PNT1 nil) (progn (setvar "osmode" OS) (prompt "\nPick two points to align X axis...") (command "ucs" "z" pause pause) ) (progn (initget 1) (setq PNT2 (getpoint PNT1 "\nPick second point - Nearest to ...")) (setvar "osmode" 0) (command "ucs" "z" PNT1 PNT2) (setvar "osmode" OS) ) ) (setvar "orthomode" ORTH) (setq *error* exi) (setvar "cmdecho" uzcmde) (princ) ) Quote Link to comment Share on other sites More sharing options...
lamensterms Posted March 30, 2016 Author Share Posted March 30, 2016 After a little more investigation (and education - thanks to Lee Mac's article here... http://www.lee-mac.com/errorhandling.html) I have now realised that none of my LISP routines have the temporary *error* function/symbol defined as a local variable. So some (and I'm guessing there will be a few) of my routines are defining *error* as the temporary function, specific to that routine, but are then not restoring *error* to its default function. This explains the issues I've had with UNDO > BACK (being that I have had a temporary *error* function set, while it should be set to default). Quote Link to comment Share on other sites More sharing options...
Lee Mac Posted March 30, 2016 Share Posted March 30, 2016 After a little more investigation (and education - thanks to Lee Mac's article here... http://www.lee-mac.com/errorhandling.html) I have now realised that none of my LISP routines have the temporary *error* function/symbol defined as a local variable. So some (and I'm guessing there will be a few) of my routines are defining *error* as the temporary function, specific to that routine, but are then not restoring *error* to its default function. Although you are not following the route of declaring the *error* symbol local to the function, your current code still follows the method I describe under the heading 'An Alternative to Function Localisation', so the previous *error* function will still be restored. Quote Link to comment Share on other sites More sharing options...
lamensterms Posted March 30, 2016 Author Share Posted March 30, 2016 Thanks Lee. I think the example code I originally posted may not be an offending routine. I've got some routines that I believe are not closing out completely. For example, I've got a routine that initiates Block Edit, and I think the Block Editor is launched before the routine calls for the *error* symbol to be restored to default. I understand (or, I hope I understand), that localising of the *error* symbol will remedy that particular case. Happy to be steered in the right direction though. Thanks a lot for the reply. Quote Link to comment Share on other sites More sharing options...
lamensterms Posted January 9, 2017 Author Share Posted January 9, 2017 Hey again guys. I just lost a long, detailed post so forgive me if this one is a little brief. We are still having this issue. I'm at a bit of a loss, as time goes on, and I correct more erroneous routines, we should be seeing this problem less and less, but it still pops up occasionally. Now I'm starting to doubt if I actually understand the problem at all. Does anyone have any advice on another approach to correct this problem? Or how to identify the offending routines to fix? I have read here: http://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/misbehaving-undo-mark/td-p/863544 ... that it's not wise to use UNDO MARK in LISP routines. Is there any truth to that? I followed AFRALISP's error handler example for UNDO MARK & BACK, should I change to UNDO BEGIN & END? Any other advice would be greatly appreciated. Quote Link to comment Share on other sites More sharing options...
Grrr Posted January 9, 2017 Share Posted January 9, 2017 I always use the vla-EndUndoMark/vla-StartUndoMark methods, check this fragment with description from Lee: (setq doc (vla-get-activedocument (vlax-get-acad-object))) (if (= 8 (logand 8 (getvar 'undoctl))) ;; If an undo group is already open (vla-endundomark doc) ;; close it ) ;; end if (vla-startundomark doc) ;; Open a new undo group (vla-endundomark doc) ;; Close the open undo group Where between Start and Endundomark must be located the expressions, that perform changes on the drawing (like changing object's property value). Also I think that when using the UNDO command, a command-s call must be used when its within the *error* function, otherwise something like this is enough: (defun *error* ( msg ) (and acDoc (= 8 (logand (getvar 'undoctl) ) (vla-EndUndoMark acDoc)) (princ msg) (princ) ) Quote Link to comment Share on other sites More sharing options...
lamensterms Posted January 10, 2017 Author Share Posted January 10, 2017 I think I've been able to reproduce this error now, and have found some confusing clues/results: There are 3 LISP routines used in these tests, please see below: CODE#1 (defun C:BI2NOSCALING (/) (SETVAR "CMDECHO" 0) (prompt "\nPICK INSERTION POINT. ") (SETQ SCALE "1") (SETVAR "CMDECHO" 1) (COMMAND "INSERT" BLOCK pause "" scale pause) (SETVAR "CMDECHO" 0) (command "explode" "L") (terpri) ) CODE#2 (defun c:mi ( / *error* MIss MIpt1 MIpt2 OROS ORORT) (SETQ OROS (GETVAR "OSMODE")) (SETQ ORORT (GETVAR "ORTHOMODE")) (command "undo" "m") ;(command "undo" "m") (SETVAR "OSMODE" 0) (SETVAR "ORTHOMODE" 1) (SETVAR "cmdecho" 0) ;(COMMAND "undo" "END") (setq exi *error*) (setq *error* MIerr) (setq MIss (ssget)) (setq MIpt1 (getpoint)) (command "ucs" "O" MIpt1) (setq MIpt2 '( 0 0 0)) (SETVAR "cmdecho" 1) (command "mirror" MIss "" MIPT2 pause pause) (command "ucs" "P") (SETVAR "OSMODE" OROS) (SETVAR "ORTHOMODE" ORORT) (SETVAR "cmdecho" 0) (setq *error* exi) (princ) ) CODE#3 (defun c:mi ( / *error* MIss MIpt1 MIpt2 OROS ORORT) (SETQ OROS (GETVAR "OSMODE")) (SETQ ORORT (GETVAR "ORTHOMODE")) (command "undo" "m") (command "undo" "m") (SETVAR "OSMODE" 0) (SETVAR "ORTHOMODE" 1) (SETVAR "cmdecho" 0) ;(COMMAND "undo" "END") (setq exi *error*) (setq *error* MIerr) (setq MIss (ssget)) (setq MIpt1 (getpoint)) (command "ucs" "O" MIpt1) (setq MIpt2 '( 0 0 0)) (SETVAR "cmdecho" 1) (command "mirror" MIss "" MIPT2 pause pause) (command "ucs" "P") (SETVAR "OSMODE" OROS) (SETVAR "ORTHOMODE" ORORT) (SETVAR "cmdecho" 0) (setq *error* exi) (princ) ) Error Handler (defun MIerr (s) (command "undo" "b") (prompt "\n*Program Terminated***Mirror.lsp ERROR MESSAGE*") (setq *error* exi) (princ) ) Test 1 - No Problem Produced In a new drawing (no undo history), if I run CODE#1 completely, then CODE#2 but ESC out of routine at prompt for 2nd point... No problem. Test 2 - No Problem Produced In a new drawing (no undo history), if I run CODE#1 completely, then CODE#3 but ESC out of routine at prompt for 2nd point... No problem. Test 3 - Problem Produced In a new drawing (no undo history), if I run CODE#1 completely, then hit RETURN & then ESC, then run CODE#2 but ESC out of routine at prompt for 2nd point... Problem. Test 4 - No Problem Produced In a new drawing (no undo history), if I run CODE#1 completely, then hit RETURN & then ESC, then run CODE#3 but ESC out of routine at prompt for 2nd point... No Problem. I'm finding it hard to make sense out of this, but my observations are: if I ESC out of CODE#1 before ESCing out of CODE#2, the problem occurs. But it I ESC out of CODE#1 before ESCing out of CODE#3, no problem occurs. The only difference between CODE#2 & CODE#3 is that CODE#3 has the (command "undo" "m") line duplicated. It seems that there is a possibility that a single (command "undo" "m") line will be ignored (or something). But if I run CODE#2 after successfully completing the previous command... no problem. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.