# OnExit

当脚本退出时, 会自动调用指定的函数.

    OnExit Function , AddRemove

## 参数

Function

  类型: 函数对象

  脚本退出时调用的函数对象. 函数的参数和返回值如下所示.

AddRemove

  类型: 整数

  如果为空或省略, 则默认为 1(在所有之前注册的函数之后调用该函数). 否则, 请指定以下数字之一:

  - 1 = 在所有之前注册的函数之后调用该函数.
  - -1 = 在所有之前注册的函数之前调用该函数.
  - 0 = 不调用该函数.

## Function

函数应该接受两个参数:

    FunctionName(ExitReason, ExitCode)

ExitReason

  类型: 字符串

  下列单词之一:

  单词 | 意义
  --- | ---
  Logoff | 用户正在注销.
  Shutdown | 正在关闭或重启系统, 例如使用 Shutdown 函数.
  Close | 脚本发送 WM_CLOSE 或 WM_QUIT 消息, 出现致命错误, 或者正在被其他方式关闭. 尽管这些情况都是很少见的, 然而 WM_CLOSE 可能是由于在脚本主窗口使用 WinClose 而引起的. 要关闭(隐藏) 窗口而不终止脚本, 请使用 WinHide. 如果脚本因严重错误或其主窗口被被销毁而退出, 它将在 OnExit 线程完成后无条件终止. 如果主窗口正在被销毁, 它可能仍然存在, 但不能显示. 这个条件可以通过使用 OnMessage 监听 WM_DESTROY 消息来检测.
  Error | 在不是持续运行的脚本中发生了运行时错误. 运行时错误的一个例子是 Run/RunWait 无法启动指定的程序或打开指定的文档.
  Menu | 用户在主窗口的菜单或标准托盘菜单中选择了 Exit.
  Exit | 使用了 Exit 或 ExitApp 函数(包括自定义菜单项).
  Reload | 正通过 Reload 函数或菜单项重载脚本.
  Single | 由于 #SingleInstance 的原因, 脚本正被它自身的新实例代替.

ExitCode

  类型: 整数

  一个介于 -2147483648 和 2147483647 之间的整数, 在脚本退出时返回给它的调用者. 任何生成脚本的程序都可以访问此代码, 例如另一个脚本(通过 RunWait) 或批处理(.bat) 文件. 零通常被用来表示成功.

### 返回值

函数可以返回一个非零的整数, 以防止脚本退出(除了一些罕见的例外情况) 和后续函数被调用. 否则, 在所有注册的函数被调用后, 脚本退出.

## 备注

可以注册任意多个 OnExit 函数. OnExit 函数通常不应该调用 ExitApp; 如果调用了, 脚本将会立即退出.

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

脚本可以通过 `OnMessage(0x11, On_WM_QUERYENDSESSION)`(有关工作脚本, 请参阅 OnMessage 示例 #2) 来检测和是否选择中止系统关闭或注销.

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

如果 OnExit 线程遇到失败条件, 比如运行错误时, 脚本将会终止.

如果 OnExit 线程是由 Exit 或 ExitApp 函数启动并指定了退出码, 则将使用该退出码, 除非 OnExit 函数返回 true(阻止退出) 或调用了 ExitApp.

每当进行一个退出尝试时, 每个 OnExit 函数都使用 SendMode 等设置的默认值重新启动. 这些默认值可以在自动执行段中更改.

## 相关

OnError, OnMessage, CallbackCreate, OnClipboardChange, ExitApp, Shutdown, Persistent, 线程, Return

## 示例

在退出脚本之前询问用户. 要测试它们, 右击托盘图标然后单击 Exit(退出).

    Persistent  ; 阻止脚本自动退出.
    OnExit ExitFunc

    ExitFunc(ExitReason, ExitCode)
    {
        if ExitReason != "Logoff" and ExitReason != "Shutdown"
        {
            Result := MsgBox("Are you sure you want to exit?",, 4)
            if Result = "No"
                return 1  ; OnExit 函数必须返回非零值来阻止退出.
        }
        ; 不要调用 ExitApp -- 这会阻止其他 OnExit 函数的调用.
    }

注册一个在退出时调用的对象.

    Persistent  ; 阻止脚本自动退出.
    OnExit(ObjBindMethod(MyObject, "Exiting"))

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

dftg