0

我试图在C++/CLI应用程序中捕获任何和所有异常,以便我可以记录并记录它们(包括堆栈跟踪)。到目前为止,我有一些代码,看起来前途无量:捕获用于登录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; 
} 

...但不是disaplying一个对话框,我收拾了错误,我得到别的东西:

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的某个地方处理东西吗? ...还是有其他(更好)的方式去做这件事。

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

回答

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); 
     } 
    }; 
0

如果反射发生在另一个线程中,则包装程序不会捕获它失败。

+0

难道这就是应用::运行用途?文档[http://msdn.microsoft.com/en-us/library/system.windows.forms.application.run.aspx]没有提到有关新线程的任何内容? – 2009-07-15 11:19:08

相关问题