优雅地终止基于Boost Asio的Windows控制台应用程序

时间:2014-10-16 12:49:25

标签: c++ boost boost-asio windows-console taskkill

我正在开发基于boost.asio的HTTP服务器。它应该在外部停止。我们使用asio信号处理,它适用于ctrl-c,但不处理WM_CLOSE,因此没有直接的方法可以在外部优雅地关闭应用程序,例如通过taskkill。强行终止流程不是一种选择。有没有一种已知的方法呢?

1 个答案:

答案 0 :(得分:2)

<强>更新

只需使用“通常”使用的任何IPC方法

  1. 编写一个简单的过程控制实用程序,例如使用例如named_condition表示您的asio进程已关闭。

    请注意named_codition在某种程度上等同于Win32命名事件,以防您认为对于此固有平台特定的代码片段更简单

  2. 考虑制作一个Windows Service (NTService),因为它看起来像你想要的那样

  3. 作为远景,尝试从您的过程创建一个顶层窗口; AllocConsole CreateWindow 可以提供帮助。但是,您最终会得到更多特定于平台的内容


  4. 原始回答 ,处理如何监听控制台关闭事件:

    这与使用Boost Asio无关。当然,在POSIX平台上,您可以使用boost::asio::signal_set来处理SIG_INT和SIG_TERM信号。

    但是,你在Windows上,并没有可移植的方法来检测控制台关闭事件。

    您应该编写一个控制台处理程序例程来检测CTRL_CLOSE_EVENT(和CTRL_C_EVENT,如果需要),并使用SetConsoleCtrlHandler将处理程序例程添加到您的进程。

    #include <windows.h> 
    #include <stdio.h> 
    
    BOOL CtrlHandler( DWORD fdwCtrlType ) 
    { 
      switch( fdwCtrlType ) 
      { 
        // Handle the CTRL-C signal. 
        case CTRL_C_EVENT: 
          printf( "Ctrl-C event\n\n" );
          Beep( 750, 300 ); 
          return( TRUE );
    
        // CTRL-CLOSE: confirm that the user wants to exit. 
        case CTRL_CLOSE_EVENT: 
          Beep( 600, 200 ); 
          printf( "Ctrl-Close event\n\n" );
          return( TRUE ); 
    
        // Pass other signals to the next handler. 
        case CTRL_BREAK_EVENT: 
          Beep( 900, 200 ); 
          printf( "Ctrl-Break event\n\n" );
          return FALSE; 
    
        case CTRL_LOGOFF_EVENT: 
          Beep( 1000, 200 ); 
          printf( "Ctrl-Logoff event\n\n" );
          return FALSE; 
    
        case CTRL_SHUTDOWN_EVENT: 
          Beep( 750, 500 ); 
          printf( "Ctrl-Shutdown event\n\n" );
          return FALSE; 
    
        default: 
          return FALSE; 
      } 
    } 
    
    int main( void ) 
    { 
      if( SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE ) ) 
      { 
        printf( "\nThe Control Handler is installed.\n" ); 
        printf( "\n -- Now try pressing Ctrl+C or Ctrl+Break, or" ); 
        printf( "\n    try logging off or closing the console...\n" ); 
        printf( "\n(...waiting in a loop for events...)\n\n" ); 
    
        while( 1 ){ } 
      } 
      else 
      {
        printf( "\nERROR: Could not set control handler"); 
        return 1;
      }
    return 0;
    }
    

    要与Boost Asio协调,您可以让处理程序停止(全局)io_service对象,并可能为运行操作设置一些标志。最后,您可能必须取消飞行中的任何异步操作(例如deadline_timer s)。

    一旦你这样做,它应该很干净。