$ETRAP
处理错误当出现错误陷阱并且设置了$ETRAP
时,Caché将执行以下步骤:
$ECODE
和$ZERROR
的值。$ETRAP
的命令。默认情况下,每个DO
、XECUTE
或用户定义的函数上下文都继承调用它的帧的$ETRAP
错误处理程序。这意味着在任何上下文级别指定的$ETRAP
错误处理程序都是最后定义的$ETRAP
,即使该定义是从当前级别向下几个堆栈级别进行的。
$ETRAP
错误处理程序$ETRAP
特殊变量可以包含一个或多个在发生错误时执行的ObjectScript命令。使用SET
命令将$ETRAP
设置为一个字符串,该字符串包含一个或多个将控制转移到错误处理例程的Caché命令。此示例将控制转移到LogError
代码标签(它是例程ErrRoutine
的一部分):
SET $ETRAP="DO LogError^ErrRoutine"
$ETRAP
特殊变量中的命令后面总是隐式的QUIT
命令。在需要带参数退出的用户定义函数上下文中调用$ETRAP
错误处理程序时,隐式QUIT
命令使用空字符串参数退出。
$ETRAP
具有全局作用域。这意味着设置$ETRAP
之前通常应该有 New $ETRAP
。否则,如果在当前上下文中设置了$ETRAP
的值,则在超出该上下文的范围后,存储在$ETRAP
中的值仍然存在,而控制位于更高级别的上下文中。因此,如果不指定新的$ETRAP
,则$ETRAP
可能会在设置它的上下文不再存在的意外时间执行。
$ETRAP
错误处理程序任何上下文都可以通过执行以下步骤来建立其自己的$ETRAP
错误处理程序:
new
命令创建$ETRAP
的新副本。$ETRAP
设置为新值。如果例程在没有首先创建$ETRAP
的新副本的情况下设置$ETRAP
,则会为当前上下文、调用它的上下文以及可能已保存在调用堆栈上的其他上下文建立新的$ETRAP
错误处理程序。因此,建议在设置$ETRAP
之前创建一个新副本。
请记住,创建$ETRAP
的新副本不会清除$ETRAP
。新命令保持$ETRAP
的值不变。
下图显示了创建$ETRAP
错误处理程序堆栈的$ETRAP
赋值序列。如图所示:
A
创建$ETRAP
的新副本,将其设置为“GOTO^ERR
”,并包含调用例程B
的do
命令。B
不对$ETRAP
执行任何操作(从而继承例程A
的$ETRAP
错误处理程序),并包含调用例程C
的do
命令。C
创建$ETRAP
的新副本,将其设置为“GOTO^CERR”
,并包含调用例程D
的do
命令。D
创建$ETRAP
的新副本,然后将其清除,不为其上下文留下$ETRAP
错误处理程序。如果例程D
(其中未定义$ETRAP
错误处理程序的上下文)中出现错误,则Caché从调用堆栈中移除例程D
的DO
帧,并将控制转移到例程C
的$ETRAP
错误处理程序。例程C
的$ETRAP
错误处理程序依次分派给^CERR
来处理错误。如果例程C
中出现错误,则Caché会将控制转移到例程C
的$ETRAP
错误处理程序,但不会展开堆栈,因为错误发生在定义了$ETRAP
错误处理程序的上下文中。
$ETRAP
错误处理程序$ETRAP
控制选项流当调用$ETRAP
错误处理程序来处理错误并执行任何清理或错误日志记录操作时,它具有以下控制流选项:
当调用$ETRAP
错误处理程序来处理错误时,Caché会将错误条件视为活动的,直到错误条件被清除。可以通过将$ECODE
特殊变量设置为空字符串来消除错误条件:
SET $ECODE=""
清除$ECODE
还会清除进程的错误堆栈。
通常,在消除错误条件后,可以使用GOTO
命令将控制转移到应用程序中的预定重新启动或继续点。在某些情况下,可能会发现在消除错误条件后退回到以前的上下文级别会更方便。
如果错误条件没有解除,当Quit
命令终止调用$ETRAP
错误处理程序的上下文时,Caché会将控制传递给调用堆栈上的另一个错误处理程序。因此,通过在不清除$ECODE
的情况下从$ETRAP
上下文执行退出,可以将控制传递给上一级错误处理程序。
如果从例程C
调用的例程D
包含将控制转移到^CERR
的错误,则^CERR
中前面没有将$ECODE
设置为“”
(空字符串)的QUIT
命令将控制权转移到前一个上下文级的$ETRAP
错误处理程序。相反,如果通过清除$ECODE
来消除错误条件,则从^CERR
退出会将控制转移到例程B
中do^C
命令之后的语句。
如果调用堆栈上不存在上一级错误处理程序,并且$ETRAP
错误处理程序在不消除错误条件的情况下执行退出,则应用程序将终止。在应用程序模式下,然后运行Caché并将控制权传递给操作系统。然后出现终端提示符。
请记住,无论是否解除错误条件,都可以使用QUIT
命令终止$ETRAP
错误处理程序上下文。由于可以在需要无参数退出的上下文级别和需要带参数退出的上下文级别(用户定义的函数上下文)调用相同的$ETRAP
错误处理程序,因此提供$QUIT
特殊变量来指示特定上下文级别所需的退出命令形式。
对于需要带参数退出的上下文,$QUIT
特殊变量返回1(1);对于需要无参数退出的上下文,$QUIT
特殊变量返回0(零)。
$ETRAP
错误处理程序可以使用$QUIT
为任一情况提供支持,如下所示:
Quit:$QUIT "" Quit
如果合适,$ETRAP
错误处理程序可以使用HALT
命令终止应用程序。
当错误处理程序中发生错误时,执行流取决于当前正在执行的错误处理程序的类型。
$ETRAP
错误处理程序中的错误如果新错误出现在$ETRAP
错误处理程序中,则Caché会展开调用堆栈,直到调用$ETRAP
错误处理程序的上下文级别被删除。然后,Caché将控制传递给调用堆栈上的下一个错误处理程序(如果有的话)。
$ZTRAP
错误处理程序中的错误如果新错误出现在$ZTRAP
错误处理程序中,则Caché会将控制权传递给它遇到的第一个错误处理程序,仅在必要时才展开调用堆栈。因此,如果$ZTRAP
错误没有在当前堆栈级清除$ZTRAP
,并且错误处理程序中随后出现另一个错误,则会在相同的上下文级别再次调用$ZTRAP
处理程序,从而导致无限循环。要避免这种情况,请将$ZTRAP
设置为错误处理程序开头的另一个值。
$ZERROR
和$ECODE
特殊变量中的错误信息如果在处理原始错误期间出现另一个错误,则有关第二个错误的信息将替换$ZERROR
特殊变量中有关原始错误的信息。但是,Caché会将新信息附加到$ECODE
特殊变量。根据第二个错误的上下文级别,Caché也可以将新信息附加到进程错误堆栈。如果$ECODE
特殊变量的现有值非空,则Caché会将新错误的代码作为新逗号附加到当前$ECODE
值。在发生以下任一情况之前,$ECODE
特殊变量中会累积错误代码:
$ECODE
,例如: SET $ECODE = ""
$ECODE
的长度超过了最大字符串长度。$ECODE
中的当前错误代码列表。当发生错误并且错误堆栈已经存在时,除非错误堆栈上的上下文级别已经存在有关另一个错误的信息,否则Caché会在发生错误的上下文级别记录有关新错误的信息。在这种情况下,信息被放在错误堆栈的下一级(不管那里可能已经记录了哪些信息)。
因此,根据新错误的上下文级别,错误堆栈可以扩展(添加一个或多个上下文级别),或者可以重写现有错误堆栈上下文级别的信息以容纳关于新错误的信息。
请记住,可以通过清除$ECODE
特殊变量来清除进程错误堆栈。
可以设置$ECODE
特殊变量或使用ZTRAP
命令在受控环境下导致错误发生。
$ECODE
可以将$ECODE
特殊变量设置为任何非空字符串以导致错误发生。当例程将$ECODE
设置为非空字符串时,Caché会将$ECODE
设置为指定的字符串,然后生成错误条件。此情况下的$ZERROR
特殊变量设置为以下错误文本:
然后,控制传递给错误处理程序,就像它对正常的应用程序级错误所做的那样。
可以向错误处理程序添加逻辑,以检查设置$ECODE
导致的错误。错误处理程序可以检查$ZERROR
中是否有
错误(例如,“$ze[”ECODETRAP“
”),或者错误处理程序可以检查$ECODE
中选择的特定字符串值。
请记住,$ECODE
的ANSI标准格式是一个或多个错误代码的逗号括起来的列表:
Z
”的错误是特定于实现的错误U
”的错误是特定于应用程序的错误可以按照ANSI标准创建自己的错误代码,方法是让错误处理程序将$ECODE
设置为以“U
”为前缀的相应错误消息。
SET $ECODE=",Upassword expired,"
如果在未设置错误处理程序的情况下在终端提示符下登录到Caché后生成错误,则当输入的代码行出现错误时,Caché将执行以下步骤:
作为错误消息,Caché显示三行:
^
)指向导致错误的命令。$ZERROR
内容的行。在以下终端提示示例中,第二个SET命令具有未定义的局部变量错误:
DHC-APP>WRITE "hello",! SET x="world" SET y=zzz WRITE x,!
hello
WRITE "hello",! SET x="world" SET y=zzz WRITE x,!
^
<UNDEFINED> *zzz
DHC-APP>
在下面的示例中,同一行代码位于从终端提示符处执行的名为mytest
的程序中:
USER>DO ^mytest
hello
WRITE "hello",! SET x="world" SET y=zzz WRITE x,!
^
<UNDEFINED>WriteOut+2^mytest *zzz
USER 2d0>
在本例中,$ZERROR
表示mytest
中的错误发生在距名为WriteOut
的标签偏移2行的位置。请注意,提示符已更改,表示已启动新的程序堆栈级别。
默认情况下,终端提示指定当前命名空间。如果一个或多个事务处于打开状态,则它还包括$TLEVEL
事务级别计数。此默认提示符可以配置不同的内容,如ZNSPACE
命令文档中所述。以下示例显示了默认值:
USER>
TL1:USER>
如果在例程执行期间发生错误,系统将保存当前程序堆栈并启动新的堆栈帧。将显示扩展提示,例如:
USER 2d0>
这个扩展提示表示程序堆栈上有两个条目,最后一个是调用do
(由“d”表示)。
请注意,此错误在程序堆栈上放置了两个条目。下一个DO执行错误将导致终端提示:
USER 4d0>
然后,可以执行以下任一步骤:
这些步骤中的任何一个甚至都可能导致额外的错误。
执行完这些步骤后,最有可能的做法是恢复执行或删除全部或部分程序堆栈。
通过在终端提示符下输入无参数GOTO
,可以在导致错误的命令之后的下一个命令恢复执行:
USER>DO ^mytest
hello
WRITE "hello",! SET x="world" SET y=zzz WRITE x,!
^
<UNDEFINED>WriteOut+2^mytest *zzz
USER 2d0>GOTO
world
USER>
可以通过在终端提示符下发出带有LABEL参数的GOTO
命令,在另一行恢复执行:
USER 2d0>GOTO ErrSect
USER 4d0>QUIT
USER>
可以在终端提示符下发出带有整数参数的Quit n
命令,以删除最后一个(或最后几个)程序堆栈条目:
USER 8d0>QUIT 1
USER 7E0>QUIT 3
USER 4d0>QUIT 1
USER 3E0>QUIT 1
USER 2d0>QUIT 1
USER 1S0>QUIT 1
USER>
请注意,在本例中,因为程序错误创建了两个程序堆栈条目,所以必须位于“d”堆栈条目上,才能通过发出goto
来恢复执行。根据发生的其他情况,“d”堆栈条目可以是偶数(用户2d0>)或奇数(用户3d0>)。
通过使用NEW $ESTACK
,可以退出到指定的程序堆栈级别:
USER 4d0>NEW $ESTACK
USER 5E1>
/* more errors create more stack frames */
USER 11d7>QUIT $ESTACK
USER 4d0>
请注意,新的$ESTACK
命令将向程序堆栈添加一个条目。
%ETN
记录应用程序错误%ETN
实用程序将异常记录到应用程序错误日志中,然后退出。可以将%ETN
(或其入口点之一)作为实用程序调用:
DO ^%ETN
或者,可以将$ZTRAP
特殊变量设置为%ETN
(或其入口点之一):
SET $ZTRAP="^%ETN"
可以指定%ETN
或其入口点之一:
FORE^%ETN
(前台)在标准应用程序错误日志中记录异常,然后暂停退出。这将调用回滚操作。这与%ETN的操作相同。
BACK^%ETN
(后台)将异常记录到标准应用程序错误日志,然后退出。这不会调用回滚操作。
LOG^%ETN
将异常记录到标准应用程序错误日志,然后退出。这不会调用回滚操作。异常可以是标准%Exception.SystemException
,也可以是用户定义的异常。
要定义异常,请在调用LOG^%ETN
之前将$ZERROR
设置为有意义的值;该值将用作日志条目中的错误消息字段。还可以在LOG^%ETN:do LOG^%ETN("This is my custom exception")
中直接指定用户定义的异常;该值将用作日志条目中的错误消息字段。如果将$ZERROR
设置为空字符串(SET $ZERROR=“”
),LOG^%ETN
会记录
错误。如果将$ZERROR
设置为
,LOG^%ETN
会记录一个
错误。
LOG^%ETN
返回包含两个元素的%
列表结构:$HOROLOG
日期和错误号。
下面的示例使用推荐的编码实践,即立即将$ZERROR
复制到变量中。LOG^%ETN
返回%
列表值:
SET err=$ZERROR
SET rtn = $$LOG^%ETN(err)
WRITE "logged error date: ",$LIST(rtn,1),!
WRITE "logged error number: ",$LIST(rtn,2)
调用LOG^%ETN
或BACK^%ETN
会自动增加可用的进程内存,完成工作,然后恢复原始的$ZSTORAGE
值。但是,如果在
错误之后调用log^%ETN
或back^%ETN
,恢复原始$ZSTORAGE
值可能会触发另一个
错误。因此,当因
错误调用这些%etn
入口点时,系统会保留增加的可用内存。
从管理门户中,依次选择系统操作、系统日志和应用程序错误日志。这将显示具有应用程序错误日志的命名空间的命名空间列表。可以使用标题对列表进行排序。
选择命名空间的日期以显示存在应用程序错误日志的日期,以及该日期记录的错误数。可以使用标题对列表进行排序。可以使用筛选器将字符串与日期和数量值匹配。
选择日期的错误以显示该日期的错误。Error#
按时间顺序将整数分配给错误。Error#*com
是应用于该日期所有错误的用户注释。您可以使用标题对列表进行排序。您可以使用筛选器来匹配字符串。
选择“错误的详细信息”可打开“错误详细信息”窗口,该窗口显示错误发生时的状态信息,包括特殊变量、值和堆栈详细信息。您可以为单个错误指定用户注释。
命名空间、日期和错误列表包括允许删除相应一个或多个错误的错误日志的复选框。选中要删除的内容,然后选择删除按钮。
%ERN
查看应用程序错误日志%ETN
实用程序检查%ETN
错误捕获实用程序记录的应用程序错误。%ETN
返回为当前命名空间记录的所有错误。
DO ^%ERN
实用程序,请执行以下步骤:该实用程序的名称区分大小写;对该实用程序中的提示的响应不区分大小写。在提示下,你可以输入吗?列出提示符的语法选项,或?L
列出所有已定义的值。可以使用Enter键退出到上一级。?L列出所有发生错误的日期,最近的第一个日期,以及记录的错误数量。
(T)列表示多少天前,其中(T)=今天,(T-7)=七天前。如果为当天的所有错误定义了用户注释,则它会显示在方括号中。列出后,它将重新显示for date:提示符。您可以输入日期或T-n。
[TEXT列出包含子字符串TEXT的所有错误。text列出在错误名称组件中包含子字符串文本的所有错误。^TEXT列出错误位置组件中包含子字符串文本的所有错误。列出后,它将重新显示for date:提示符。输入日期。
可以在ERROR:PROMPT FOR COMMENTS时指定*。*显示应用于当天所有错误的当前用户指定备注。然后,它会提示提供新注释,以替换所有这些错误的现有注释。
You may enter ?要列出变量的其他语法选项:PROMPT。
*A:在Variable:Prompt中指定时,显示DEVICE:PROMPT;按Return键在当前终端设备上显示结果。
*V:在Variable:提示下指定时,显示变量:提示。在此提示下,指定无下标局部变量或无下标局部变量的逗号分隔列表;有下标的变量将被拒绝。%ERN然后显示Device:Prompt;按Return在当前终端设备上显示结果。%ern返回每个指定变量(如果已定义)及其所有子节点的值。
翻译:
注意:%ER是%ERN的旧名称。它们的功能是相同的,尽管%ern的效率略高一些。