</head> <body> <h1>OnExit</h1> <p>OnExit 可以用作<a href="#function">函数</a>或<a href="#command">命令</a>, 但建议在新脚本中使用前者. 作为一个函数, 它注册一个 <em>函数</em>, 以便在脚本退出时自动调用. 作为一个命令, 它注册一个 <em>子程序</em>, 以便在脚本退出时自动调用.</p> <h2 id="function">OnExit 函数 <span class="ver">[v1.1.20+]</span></h2> <p>注册一个在脚本退出时自动调用的<a href="../Functions.htm">函数</a>.</p> <pre class="Syntax"><span class="func">OnExit</span>(Callback <span class="optional">, AddRemove</span>)</pre> <h3 id="Function_Parameters">参数</h3> <dl> <dt>Callback</dt> <dd> <p>要调用的函数或<a href="../misc/Functor.htm">函数对象</a>的名称. 若要传递原义的函数名称, 将其括在双引号中.</p> <p>回调函数接受两个参数, 可以<a href="../Functions.htm#intro">定义</a>如下:</p> <pre class="NoIndent">MyCallback(ExitReason, ExitCode) { ...</pre> <p>虽然你给参数的名称并不重要, 但是下面的值会依次赋值给它们:</p> <ol> <li>退出原因(<a href="#ExitReason">下表</a>中的一个单词).</li> <li>传递给 <a href="Exit.htm">Exit</a> 或 <a href="ExitApp.htm">ExitApp</a> 的退出代码.</li> </ol> <p>如果不需要相应的信息, 可以从回调函数的参数列表末尾省略一个或多个参数.</p> <p>回调可以返回一个非零的整数来阻止脚本退出(除了一些<a href="#close">罕见的例外</a>), 也不会再调用其他回调. 否则, 脚本将在调用所有注册回调之后退出.</p> </dd> <dt>AddRemove</dt> <dd><p>如果省略, 则默认为 1. 否则, 指定下列数字之一:</p> <ul> <li>1 = 在所有之前注册的回调之后调用该回调.</li> <li>-1 = 在所有之前注册的回调之前调用该回调.</li> <li>0 = 不调用该回调.</li> </ul> <p>如果下面的 <a href="#command">OnExit 命令</a>已经注册了子程序, 则总是首先调用该子程序.</p> </dd> </dl> <h3 id="Function_Remarks">备注</h3> <p>可以注册任意数量的回调. 如果还注册了子程序(通过下面的 <a href="#command">OnExit 命令</a>), 则在子程序调用 <a href="ExitApp.htm">ExitApp</a> 之后调用回调. 回调通常不应该调用 ExitApp; 如果调用了, 则脚本立即终止.</p> <h2 id="command">OnExit 命令</h2> <p>注册要在脚本退出时自动调用的<a href="../Language.htm#subroutines">子程序</a>.</p> <p class="warning"><strong>过时的:</strong> 不推荐在新脚本中使用此命令. 使用上面描述的 <a href="#function">OnExit()</a> 函数来减少意外创建无法退出的脚本的风险,并确保传递给 <a href="Exit.htm">Exit</a> 或 <a href="ExitApp.htm">ExitApp</a> 的退出码被保存.</p> <pre class="Syntax"><span class="func">OnExit</span> <span class="optional">, Label</span></pre> <h3 id="Command_Parameters">参数</h3> <dl> <dt>Label</dt> <dd><p>如果为空或省略, 任何先前注册的子程序将取消注册. 否则, 请指定子程序的 <a href="../misc/Labels.htm">label(标签)</a>, 当脚本由于任意原因退出时其内容将被执行(作为一个新的<a href="../misc/Threads.htm">线程</a>).</p></dd> </dl> <h3 id="Command_Remarks">备注</h3> <p>由于注册的子程序被调用而不是退出脚本, 因此如果需要退出脚本, 子程序中必须使用 <a href="ExitApp.htm">ExitApp</a>. (译者注: 每次遇到退出, 就执行子程序, 相当于退出命令被子程序取代了而不会被执行, 不过在子程序运行时(完成之前), 再次选择退出时, 不会再次调用子程序, 而是退出, 详情请参阅下面的备注.)</p> <p>内置变量 <strong>A_ExitReason</strong> 为空, 除非注册的子程序正在运行或者在之前的退出中至少调用过一次. 如果不是空的, 则它为<a href="#ExitReason">下面表格</a>中单词的其中一个.</p> <h2 id="Remarks">备注</h2> <p>当脚本以任何方式退出时, 将调用回调或子程序(除非被类似 "结束任务" 的方式强行终止). 每当 <a href="_SingleInstance.htm">#SingleInstance</a> 和 <a href="Reload.htm">Reload</a> 请求前一个实例终止时, 也会调用它.</p> <p>脚本可以通过 <code>OnMessage(0x0011, "WM_QUERYENDSESSION")</code>(有关工作脚本, 请参阅 <a href="OnMessage.htm#shutdown">OnMessage 示例 #2</a>) 检测并可选择地中止操作系统关闭或注销.</p> <p>OnExit <a href="../misc/Threads.htm">线程</a>并不受到 <a href="_MaxThreads.htm">#MaxThreads</a> 的限制(它总是在需要的时候启动). 此外, 当它运行时, 它不会被任何<a href="../misc/Threads.htm">线程</a>中断, 包括<a href="../Hotkeys.htm">热键</a>, <a href="Menu.htm">自定义菜单项</a>和<a href="SetTimer.htm">计时器子程序</a>. 不过, 它会在这些情况下被中断(终止)(且脚本也同时被终止了): 用户从托盘菜单或主菜单栏中选择 exit(退出), 或由于 <a href="Reload.htm">Reload</a> 或 <a href="_SingleInstance.htm">#SingleInstance</a> 而要求脚本终止. 由于这些原因, 回调或子程序应该被设计为尽快结束, 除非用户知道它在做什么.</p> <p>如果 OnExit <a href="../misc/Threads.htm">线程</a>遇到失败条件, 比如运行时错误时, 脚本将会终止. 这可以防止有缺陷的回调或子程序使脚本无法终止.</p> <p>如果 OnExit <a href="../misc/Threads.htm">线程</a>由 <a href="Exit.htm">Exit</a> 或 <a href="ExitApp.htm">ExitApp</a> 启动并指定了退出码, 在 [v1.1.19] 和之前的版本中将被忽略, 且不再可用. 而从 <span class="ver">[v1.1.20+]</span> 开始, 除非使用 <a href="ExitApp.htm">ExitApp</a> 指定了新的退出码, 否则将使用最初的退出码.</p> <p>每当进行一个退出尝试时, 每个回调或子程序都将以 <a href="SendMode.htm">SendMode</a> 等设置的默认值启动. 这些默认值可以在<a href="../Scripts.htm#auto">自动执行段</a>中更改.</p> <h2 id="ExitReason">ExitReason(退出原因)</h2> <table class="info"> <tr> <th>原因</th> <th abbr="Descr">描述</th> </tr> <tr id="logoff"> <td>logoff</td> <td>用户正在注销.</td> </tr> <tr> <td>Shutdown</td> <td>正在关闭或重启系统, 例如使用 <a href="Shutdown.htm">Shutdown</a> 命令.</td> </tr> <tr id="close"> <td>Close</td> <td> <p>脚本发送 WM_CLOSE 或 WM_QUIT 消息, 出现致命错误, 或者正在被其他方式关闭. 尽管这些情况都是很少见的, 然而 WM_CLOSE 可能是由于在脚本主窗口使用 <a href="WinClose.htm">WinClose</a> 命令而引起的. 要关闭(隐藏) 窗口而不终止脚本, 请使用 <a href="WinHide.htm">WinHide</a>.</p> <p>如果脚本因严重错误或其<a href="../Program.htm#main-window">主窗口</a>被被销毁而退出, 它将在 OnExit 线程完成后无条件终止.</p> <p>如果主窗口正在被销毁, 它可能仍然存在, 但不能显示. 这个条件可以通过使用 <a href="OnMessage.htm">OnMessage()</a> 监听 WM_DESTROY 消息来检测.</p> </td> </tr> <tr> <td>Error</td> <td>在没有热键且不是<a href="_Persistent.htm">持续运行的</a>脚本中发生了运行时错误. 运行时错误的一个例子是 <a href="Run.htm">Run/RunWait</a> 命令无法启动指定的程序或打开指定的文档.</td> </tr> <tr> <td>Menu</td> <td>用户在<a href="../Program.htm#main-window">主窗口</a>的菜单或标准托盘菜单中选择了退出.</td> </tr> <tr> <td>Exit</td> <td>使用了 <a href="Exit.htm">Exit</a> 或 <a href="ExitApp.htm">ExitApp</a>(包括<a href="Menu.htm">自定义菜单项</a>).</td> </tr> <tr> <td>Reload</td> <td>正通过 <a href="Reload.htm">Reload</a> 命令或菜单项重载脚本.</td> </tr> <tr> <td>Single</td> <td>由于 <a href="_SingleInstance.htm">#SingleInstance</a> 的结果, 脚本正被它自身的新实例代替.</td> </tr> </table> <h2 id="Related">相关</h2> <p><a href="OnError.htm">OnError()</a>, <a href="OnMessage.htm">OnMessage()</a>, <a href="RegisterCallback.htm">RegisterCallback()</a>, <a href="OnClipboardChange.htm">OnClipboardChange</a>, <a href="ExitApp.htm">ExitApp</a>, <a href="Shutdown.htm">Shutdown</a>, <a href="_Persistent.htm">#Persistent</a>, <a href="../misc/Threads.htm">Threads</a>, <a href="Gosub.htm">Gosub</a>, <a href="Return.htm">Return</a>, <a href="Menu.htm">Menu</a></p> <h2 id="Examples">示例</h2> <div class="ex" id="ExFnVsCmd"> <p><a class="ex_number" href="#ExFnVsCmd"></a> 函数 vs. 命令.</p> <p>尽管语法不同, 但这两个例子都有相同的效果; 即它们在退出脚本之前询问用户. 要测试它们, 右击<a href="../Program.htm#tray-icon">托盘图标</a>然后单击 Exit(退出).</p> <pre class="NoIndent"><a href="_Persistent.htm">#Persistent</a> <em>; 防止脚本自动退出.</em> OnExit("ExitFunc") ExitFunc(ExitReason, ExitCode) { if ExitReason not in Logoff,Shutdown <em>; 避免逗号周围的空格.</em> { MsgBox, 4, , Are you sure you want to exit? IfMsgBox, No return 1 <em>; 回调必须返回非零值来避免退出.</em> } <em>; 不要调用 ExitApp -- 那会阻止其他回调被调用.</em> }</pre> <pre><a href="_Persistent.htm">#Persistent</a> <em>; 防止脚本自动退出.</em> OnExit, ExitSub return ExitSub: if A_ExitReason not in Logoff,Shutdown <em>; 注意不要在逗号周围含有空格.</em> { MsgBox, 4, , Are you sure you want to exit? IfMsgBox, No return } ExitApp <em>; 脚本含有注册的子程序时不会终止, 除非子程序使用 ExitApp.</em></pre> </div> <div class="ex" id="ExFnObj"> <p><a class="ex_number" href="#ExFnObj"></a> 注册一个在退出时调用的对象.</p> <pre><a href="_Persistent.htm">#Persistent</a> <em>; 防止脚本自动退出.</em> OnExit(<a href="ObjBindMethod.htm">ObjBindMethod</a>(MyObject, "Exiting")) class MyObject { Exiting() { MsgBox, MyObject is cleaning up prior to exiting... <em>/* this.SayGoodbye() this.CloseNetworkConnections() */</em> } }</pre> </div> </body> </html>