0

我试图在 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某个地方处理里面的东西吗?...或者是否有其他(更好的)方法来解决这个问题。

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

4

2 回答 2

0

如果反射发生在不同的线程中,则包装器不会捕获它失败。

于 2009-07-15T11:05:40.960 回答
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 );
      }
   };
于 2009-08-04T10:13:49.800 回答