gpt4 book ai didi

java - 从 bat 脚本运行的 Java 应用程序上的 Windows 关闭 Hook

转载 作者:太空狗 更新时间:2023-10-29 22:39:41 27 4
gpt4 key购买 nike

我有一个运行 java 应用程序的 bat 脚本。如果我在其上按 ctrl+c,应用程序将正常终止,并调用所有关闭 Hook 。但是,如果我只是关闭 bat 脚本的 cmd 窗口,则永远不会调用关闭 Hook 。

有办法解决吗?也许有一种方法可以告诉 bat 脚本如何在其窗口关闭时终止调用的应用程序?

最佳答案

来自 addShutdownHook文档:

In rare circumstances the virtual machine may abort, that is, stop running without shutting down cleanly. This occurs when the virtual machine is terminated externally, for example with the SIGKILL signal on Unix or the TerminateProcess call on Microsoft Windows.

不幸的是,我认为这里无事可做。


CTRL-CLOSE Windows 控制台中的信号。似乎不可调整。

引用上面的链接:

The system generates a CTRL+CLOSE signal when the user closes a console. All processes attached to the console receive the signal, giving each process an opportunity to clean up before termination. When a process receives this signal, the handler function can take one of the following actions after performing any cleanup operations:

  • 调用 ExitProcess 终止进程。
  • 返回FALSE。如果所有已注册的处理程序函数均未返回 TRUE,则默认处理程序将终止进程。
  • 返回TRUE。在这种情况下,不会调用其他处理程序函数,并且会弹出一个对话框询问用户是否终止该进程。如果用户选择不终止进程,则系统不会关闭控制台,直到进程最终终止。

更新。如果您可以接受 native 调整,则 WinAPI SetConsoleCtrlHandler 函数为抑制默认行为开辟了道路。

UPD2Revelations on Java signal handling and termination相对较旧的文章,但编写 Java 信号处理程序部分确实可能包含您需要的内容。


UPD3。我尝试了上面文章中的 Java 信号处理程序。它可以很好地与 SIGINT 配合使用,但这不是我们所需要的,因此我决定将其与 SetConsoleCtrlHandler 配合使用。结果有点复杂,可能不值得在您的项目中实现。无论如何,它可以帮助其他人。

所以,这个想法是:

  1. 保留对关闭处理程序线程的引用。
  2. 使用 JNI 设置自定义 native 控制台处理程序。
  3. CTRL+CLOSE 信号上调用自定义 Java 方法。
  4. 从该方法调用关闭处理程序。

Java代码:

public class TestConsoleHandler {

private static Thread hook;

public static void main(String[] args) {
System.out.println("Start");
hook = new ShutdownHook();
Runtime.getRuntime().addShutdownHook(hook);
replaceConsoleHandler(); // actually not "replace" but "add"

try {
Thread.sleep(10000); // You have 10 seconds to close console
} catch (InterruptedException e) {}
}

public static void shutdown() {
hook.run();
}

private static native void replaceConsoleHandler();

static {
System.loadLibrary("TestConsoleHandler");
}
}

class ShutdownHook extends Thread {
public void run() {
try {
// do some visible work
new File("d:/shutdown.mark").createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Shutdown");
}
}

native replaceConsoleHandler:

JNIEXPORT void JNICALL Java_TestConsoleHandler_replaceConsoleHandler(JNIEnv *env, jclass clazz) {
env->GetJavaVM(&jvm);
SetConsoleCtrlHandler(&HandlerRoutine, TRUE);
}

和处理程序本身:

BOOL WINAPI HandlerRoutine(__in DWORD dwCtrlType) {
if (dwCtrlType == CTRL_CLOSE_EVENT) {
JNIEnv *env;
jint res = jvm->AttachCurrentThread((void **)(&env), &env);
jclass cls = env->FindClass("TestConsoleHandler");
jmethodID mid = env->GetStaticMethodID(cls, "shutdown", "()V");
env->CallStaticVoidMethod(cls, mid);
jvm->DetachCurrentThread();
return TRUE;
}
return FALSE;
}

而且它有效。在 JNI 代码中,所有的错误检查都被省略了。关机处理程序创建空文件 "d:\shutdown.mark" 以指示正确关机。

带有已编译测试二进制文件的完整源代码 here .

关于java - 从 bat 脚本运行的 Java 应用程序上的 Windows 关闭 Hook ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9277630/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com