OnExit

指定一个在脚本退出时自动运行的回调函数子程序.

OnExit() [v1.1.20+]

OnExit(Func , AddRemove)

参数

Func

脚本退出时调用的函数名称或函数对象. 该函数还可以有选择的定义参数, 请参考下面的例子. 如果 OnExit 调用的函数返回一个非零整数, 脚本将不会继续退出. 否则, 脚本将在所有注册函数运行完成之后退出.

ExitFunc(ExitReason, ExitCode)
AddRemove

下列值之一:
1(默认): 在所有之前注册的函数之后调用该函数.
-1: 在所有之前注册的函数之前调用该函数.
0 : 不调用该函数.

总是优先调用已注册的 label(标签)(子程序).

备注

新脚本使用函数替代原来的子程序 -- 这样可以降低脚本无法退出的风险, 并确保传递给 Exit 或 ExitApp 的退出码被保存.

OnExit 函数可以注册任意多个. 如果同时还注册了 label(子程序), 注册的这些函数会在子程序执行 ExitApp 命令之后被调用. 通常 OnExit 函数不需要调用 ExitApp 命令; 如果调用了, 脚本将会立即退出.

示例

; 脚本启动之后, 在托盘图标上点击鼠标右键和选择 Exit 来测试 OnExit 回调函数.
#Persistent  ; 防止脚本自动退出.

; 注册一个在退出时调用的函数:
OnExit("ExitFunc")

; 注册一个在退出时调用的对象:
OnExit(ObjBindMethod(MyObject, "Exiting"))

ExitFunc(ExitReason, ExitCode)
{
    if ExitReason not in Logoff,Shutdown
    {
        MsgBox, 4, , Are you sure you want to exit?
        IfMsgBox, No
            return 1  ; OnExit 函数必须返回非零值来防止退出.
    }
    ; 不要用 ExitApp -- 那会阻止其他 OnExit 函数被调用.
}

class MyObject
{
    Exiting()
    {
        MsgBox, MyObject is cleaning up prior to exiting...
        /*
        this.SayGoodbye()
        this.CloseNetworkConnections()
        */
    }
}

OnExit

不推荐: 不推荐在新脚本中使用此命令. 使用 OnExit 函数代替.

OnExit , Label

参数

Label

如果省略, 则脚本会返回到正常的退出行为. 否则, 请指定 label(标签) 的名称, 当脚本由于任意原因退出时将执行标签中的内容(作为新线程).

备注

重要提示: 由于指定的子程序被调用而不是退出脚本, 因此如果需要退出脚本, 子程序中必须使用 ExitApp 命令. (译者注: 每次遇到退出, 就执行子程序, 相当于退出命令被子程序取代了而不会被执行, 不过在子程序运行时(完成之前), 再次选择退出时, 不会再次调用子程序, 而是退出, 详情请参阅下面的备注.)

内置变量 A_ExitReason 为空, 除非 OnExit 子程序正在运行或者在之前的退出中至少调用过一次. 如果不是空的, 则它为下面表格中单词的其中一个.

示例

; 脚本启动之后, 在托盘图标上点击鼠标右键和选择 Exit 来测试 OnExit 回调函数.
#Persistent  ; 防止脚本自动退出.
OnExit, ExitSub  
return

ExitSub:
if A_ExitReason not in Logoff,Shutdown  ; 在这行语句中, 注意不要在逗号周围含有空格.
{
    MsgBox, 4, , Are you sure you want to exit?
    IfMsgBox, No
        return
}
ExitApp  ; 脚本含有 OnExit 子程序时不会立即终止, 除非子程序使用 ExitApp.

备注

当脚本以任何方式退出时, 将调用 OnExit 回调函数或子程序(除非被类似 "结束任务" 的方式强行终止). 每当 #SingleInstanceReload 命令请求前一个实例终止时, 也会调用它.

脚本可以通过 OnMessage(0x11, "WM_QUERYENDSESSION")(有关工作脚本, 请参阅 OnMessage 示例 #2) 检测并可选择地中止操作系统关闭或注销.

OnExit 线程并不受到 #MaxThreads 的限制(它总是在需要的时候启动). 此外, 当它运行时, 它不会被任何线程中断, 包括热键, 自定义菜单项计时器子程序. 不过, 它会在这些情况下被中断(终止)(且脚本也同时被终止了): 用户从托盘菜单或主菜单栏中选择 exit(退出), 或由于 Reload#SingleInstance 而要求脚本终止. 由于这些原因, OnExit 回调函数或子程序应该被设计为尽快结束, 除非用户知道它在做什么.

如果 OnExit 线程遇到失败条件, 比如运行时错误时, 脚本将会终止. 这可以防止有缺陷的 OnExit 回调函数或子程序使脚本无法终止.

如果 OnExit 线程ExitExitApp 启动并指定了退出码, 在 [v1.1.19] 和之前的版本中将被忽略, 且不再可用. 而从 [v1.1.20+] 开始, 除非使用 ExitApp 指定了新的退出码, 否则将使用最初的退出码.

每当进行一个退出尝试时, 每个 OnExit 回调函数或子程序都将以 SendMode 等设置的默认值启动. 这些默认值可以在自动执行段中更改.

ExitReason(退出原因)

logoff 用户正在注销.
Shutdown 正在关闭或重启系统, 例如使用 Shutdown 命令.
Close 脚本发送 WM_CLOSE 或 WM_QUIT 消息, 出现致命错误, 或者正在被其他方式关闭. 尽管这些情况都是很少见的, 然而 WM_CLOSE 可能是由于在脚本主窗口中使用 WinClose 命令而引起的. 要关闭(隐藏) 窗口而不终止脚本, 请使用 WinHide.
Error 在没有热键且不是持续运行的脚本中发生了运行时错误. 运行时错误的一个例子是 Run/RunWait 命令无法启动指定的程序或打开指定的文档.
Menu 用户在主窗口的菜单或标准托盘菜单中选择了退出.
Exit 使用了 ExitExitApp 命令(包括 自定义菜单项).
Reload 正通过 Reload 命令或菜单项重载脚本.
Single 由于 #SingleInstance 的结果, 脚本正被它自身的新实例代替.

相关

OnError(), OnMessage(), RegisterCallback(), OnClipboardChange, ExitApp, Shutdown, #Persistent, Threads, Gosub, Return, Menu