错误捕捉器撤消太多
嘿我们的一些LISP例程,特别是错误捕捉器/处理程序,一直存在问题。问题是,有时出现“错误”时,会撤消太多操作。
我的假设是。。。(我很高兴有争议)。。。一个LISP例程的错误处理程序使用“UNDO”“BACK”,但例程本身没有放置“UNDO”“标记”。
因此,一旦出现“错误”,捕捉器将发出“UNDO”“BACK”并撤消到之前的标记集,而不是被崩溃的例程中的标记集。这听起来对吗?
说了这么多,有没有人对如何找出哪种例行程序会把事情搞砸有什么建议?下面是一个例程的代码,该例程在出现“错误”时取消了所有内容(返回到上一个标记)。但是这个例程确实有一个“撤消”“标记”集。。。所以它否定了我的理论。
不管怎样,我都在努力解决这个问题,如果能帮我摆脱罪恶感,我将不胜感激。
谢谢。
(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)
) 经过更多的调查(和教育-感谢李在这里的文章。。。http://www.lee-mac.com/errorhandling.html)我现在意识到,我的LISP例程都没有将临时的“错误”函数/符号定义为局部变量。因此,我的一些例程(我猜会有一些)将*error*定义为临时函数,特定于该例程,但不会将*error*恢复为其默认函数。
这解释了我在UNDO>BACK中遇到的问题(因为我有一个临时的*error*函数集,而它应该设置为默认值)。
虽然您没有遵循在函数本地声明*错误*符号的路线,但您当前的代码仍然遵循我在标题“函数本地化的替代方案”下描述的方法,因此之前的*错误*函数仍将恢复。 谢谢李。我认为我最初发布的示例代码可能不是一个令人讨厌的例程。
我有一些我认为还没有完全结束的常规动作。例如,我有一个启动块编辑的例程,我认为块编辑器是在例程调用将*错误*符号恢复为默认值之前启动的。我理解(或者,我希望我理解),“错误”符号的本地化将纠正这种特殊情况。
很高兴被引导到正确的方向。
非常感谢您的回复。 大家好。
我刚刚失去了一个长的,详细的帖子,所以请原谅我,如果这是一个有点简短。
我们仍然有这个问题。
我有点不知所措,随着时间的推移,我纠正了更多错误的惯例,我们应该越来越少地看到这个问题,但它仍然偶尔出现。现在我开始怀疑我是否真的理解了这个问题。
有人对解决这个问题的其他方法有什么建议吗?或者如何确定要修复的违规例程?
我在这里读到:http://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/misbehaving-undo-mark/td-p/863544... 在LISP例程中使用UNDO标记是不明智的。这是真的吗?我遵循了AFRALISP的错误处理程序示例UNDO MARK&BACK,我应该更改为UNDO BEGIN&END吗?
如有任何其他建议,将不胜感激。 我总是使用vla-EndUndoMark/vla-StartUndoMark方法,用李的描述检查这个片段:
(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
在开始和结束标记之间,必须找到表达式,这些表达式在图形上执行更改(如更改对象的特性值)。
我还认为,在使用UNDO命令时,当其在*error*函数内时,必须使用command-s调用,否则这样的调用就足够了:
(defun *error* ( msg )
(and acDoc (= 8 (logand (getvar 'undoctl) ) (vla-EndUndoMark acDoc))
(princ msg)
(princ)
) 我想我现在已经能够重现这个错误,并发现了一些令人困惑的线索/结果:
这些测试中使用了3个LISP例程,请参见以下内容:
代码#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)
)代码#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)
)代码#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)
)
错误处理程序
(defun MIerr (s)
(command "undo" "b")
(prompt "\n*Program Terminated***Mirror.lsp ERROR MESSAGE*")
(setq *error* exi)
(princ)
)测试1-未产生任何问题
在新图形中(没有撤消历史记录),如果我完全运行代码#1,则代码#2,但在提示第二点时退出例程。。。没问题。
测试2-没有问题
在新图形中(没有撤消历史记录),如果我完全运行代码#1,则代码#3,但在提示第二点时退出例程。。。没问题。
测试3-产生的问题
在新图形中(无撤消历史记录),如果我完全运行代码#1,然后单击RETURN&然后单击ESC,然后运行代码#2,但在提示第二点时退出例程。。。问题
测试4-没有问题
在新图形中(无撤消历史记录),如果我完全运行代码#1,然后单击RETURN&然后单击ESC,然后运行代码#3,但在提示第二点时退出例程。。。没问题。
我发现很难理解这一点,但我的观察结果是:如果我在退出代码#2之前退出代码#1,问题就会出现。但如果我在退出代码#3之前退出代码#1,则不会出现任何问题。代码#2和代码#3之间的唯一区别是代码#3的(命令“undo”“m”)行重复。似乎有可能忽略单个(命令“undo”“m”)行(或其他内容)。但是如果我在成功完成上一个命令后运行代码#2。。。没问题。
页:
[1]