1

我有一个应用程序服务器(JBoss,但这也发生在 Tomcat 中)作为 Windows Server 2003 中的服务运行。它使用-Xrs标志运行。

在应用服务器下运行的 Java 应用程序通过 JNI 调用用 C++ 编写的可自定义接口(意味着我们可以更改此代码),引用第三方 DLL 文件来处理图像(Lincoln用于转换 PostScript)。

mstsc /console当我们在控制台( )或管理员( )模式下通过远程桌面连接登录服务器mstsc /admin时,当我们注销时,如果林肯 DLL 文件已经加载,应用服务器将确认注销信号,服务进程将立即终止,而不偏见。

我相信信号是CTRL_LOGOFF,但我可能是不正确的。

关于信号处理的 JavaJiggle 文章之后,显然在处理 DLL 文件时将信号处理程序传递给 DLL 文件。这意味着第三方 DLL 文件(在本例中为林肯)CTRL_LOGOFF通过注销来监听并响应信号。

我相信,我应该能够在我的 DLL 的 C++ 接口中编写一个信号捕获器,以CTRL_LOGOFF在它到达 DLL 之前拦截它,如果是这样,那么当有人从控制台/管理员 RDP 注销时,我们就不会经常死掉。

这是我需要的:

  1. 我在控制台/管理员注销/注销时收到的信号是否正确CTRL_LOGOFF

  2. 我可以在 C++ 接口中编写信号拦截器吗?

  3. 如何编码该信号拦截器,或者是否有预先存在的代码?我正在使用 32 位 DLL。

我找到了 Microsoft 文章Registering a Control Handler Function,这可能有助于回答这个问题。

4

1 回答 1

0

我似乎已经通过每次调用第三方DLL时向堆栈添加一个忽略处理程序来解决它,但我担心每次调用我的方法时,我们都会不断向堆栈添加处理程序,显然第三方DLL没有删除其处理程序。我不知道这是否会造成内存泄漏。

有没有办法首先防止第三方处理程序被放置?我问了一个后续问题来回答这个问题: 如何防止我的控制台控制处理程序被覆盖?.

这是我自定义的 JNI 类方法,它调用了第三方 DLL 文件:

JNIEXPORT jint JNICALL Java_com_company_ConvertProxy_convertToImageType(JNIEnv *env, jclass cls, jstring input, jstring output) {

    jboolean isCopy;
    inFilename = env->GetStringUTFChars(input, &isCopy);
    outFilename = env->GetStringUTFChars(output, &isCopy);

    // I tried to call SetConsoleCtrlHandler() here, but failed;
    // it turns out third-party code in ConvertImage() also
    // calls SetConsoleCtrlHandler and overrides it if placed here.

    int value = ConvertImage();

    // Deafen Control Logoffs set by third-party ConvertImage.
    // SetConsoleCtrlHandler( NULL, TRUE ); // DOES NOT WORK, must use custom CtrlHandler.
    SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE );

    return value;
}

BOOL CtrlHandler( DWORD fdwCtrlType ) {
    switch( fdwCtrlType )
    {
        // Handle the CTRL-C signal.
        case CTRL_C_EVENT:
          return( TRUE );

        // CTRL-CLOSE: confirm that the user wants to exit.
        case CTRL_CLOSE_EVENT:
          return( TRUE );

        case CTRL_BREAK_EVENT:
          return( TRUE );

        case CTRL_LOGOFF_EVENT:
          return( TRUE );

        case CTRL_SHUTDOWN_EVENT:
          return( TRUE );

        default:
          return FALSE;
      }
}
于 2011-10-12T22:21:39.560 回答