捕获在C ++ CLI应用程序中登录的异常

时间:2009-07-15 10:59:06

标签: debugging exception exception-handling c++-cli targetinvocationexception

我正在尝试在C ++ / CLI应用程序中捕获任何和所有异常,以便我可以记录和记录它们(包括堆栈跟踪)。到目前为止,我有一些看起来很有希望的代码:

[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
    // Enabling Windows XP visual effects before any controls are created
    Application::EnableVisualStyles();
    Application::SetCompatibleTextRenderingDefault(false); 

    // Create the main window and run it
    try
    {
        Application::Run(gcnew MainForm());
    }
    catch( System::Exception^ e )
    {
        String^ message = gcnew String("");
        System::Exception^ exceptionRecursor = e;

        message = "ERROR: Uncaught exception encountered!\n\n";
        while( exceptionRecursor )
        {
            message += exceptionRecursor->Source+"\n\t";
            message += exceptionRecursor->Message+"\n\t";
            message += exceptionRecursor->StackTrace+"\n\n";
            exceptionRecursor = exceptionRecursor->InnerException;
        }
        MessageBox::Show(message);
    }

    return 0;
}

...但是我没有删除带有我整理错误的对话框,而是获得了其他内容:

An unhandled exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll

Additional information: Exception has been thrown by the target of an invocation.

这是因为Run命令试图以某种方式处理异常吗?我是否需要处理MainForm内的某些内容? ......还是有其他(更好)的方式来解决这个问题。

暂时忘记错误的来源(我在开发周期中期并且仍在调试中),能够捕获这些错误并产生一个整齐的小堆栈跟踪,这可能会保留在代码中部署并让用户知道什么时候出错了。最终,我将错误报告包装成可以通过网络报告的内容。

2 个答案:

答案 0 :(得分:0)

如果反射发生在另一个线程中,那么包装器不会发现它失败。

答案 1 :(得分:0)

我找到了一个解决方案(使用Application::ThreadException):

// Creates a class to throw the error.
public:
   ref class ErrorHandler: public System::Windows::Forms::Form
   {
      // Inserts the code to create a form with a button.

      // Programs the button to throw an exception when clicked.
   private:
      void button1_Click( Object^ /*sender*/, System::EventArgs^ /*e*/ )
      {
         throw gcnew ArgumentException( "The parameter was invalid" );
      }

   public:
      static void Main()
      {
         // Creates an instance of the methods that will handle the exception.
         CustomExceptionHandler ^ eh = gcnew CustomExceptionHandler;

         // Adds the event handler to to the event.
         Application::ThreadException += gcnew ThreadExceptionEventHandler( eh, &Form1::CustomExceptionHandler::OnThreadException );

         // Runs the application.
         Application::Run( gcnew ErrorHandler );
      }
   };

// Creates a class to handle the exception event.
internal:
   ref class CustomExceptionHandler
   {
      // Handles the exception event.
   public:
      void OnThreadException( Object^ /*sender*/, ThreadExceptionEventArgs^ t )
      {
         System::Windows::Forms::DialogResult result = ::DialogResult::Cancel;
         try
         {
            result = this->ShowThreadExceptionDialog( t->Exception );
         }
         catch ( Exception^ ) 
         {
            try
            {
               MessageBox::Show( "Fatal Error", "Fatal Error", MessageBoxButtons::AbortRetryIgnore, MessageBoxIcon::Stop );
            }
            finally
            {
               Application::Exit();
            }
         }

         // Exits the program when the user clicks Abort.
         if ( result == ::DialogResult::Abort )
         {
            Application::Exit();
         }
      }

      // Creates the error message and displays it.
   private:
      System::Windows::Forms::DialogResult ShowThreadExceptionDialog( Exception^ e )
      {
         String^ errorMsg = "An error occurred please contact the adminstrator with the following information:\n\n";
         errorMsg = String::Concat( errorMsg, e->Message, "\n\nStack Trace:\n", e->StackTrace );
         return MessageBox::Show( errorMsg, "Application Error", MessageBoxButtons::AbortRetryIgnore, MessageBoxIcon::Stop );
      }
   };