Исключения прерываний для входа в приложение CLI С++

Я пытаюсь уловить любые и все исключения в приложении С++/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?... или есть какой-то другой (лучший) способ обойти это.

Забыв источник ошибки на мгновение (я занимаюсь средним циклом разработки и все еще отлаживаю), было бы неплохо уловить эти ошибки и создать аккуратную небольшую трассировку стека, которая могла бы оставаться в коде прямо вверх для развертывания и позволить пользователям узнать, когда все идет не так. В конце концов я бы обернул отчет об ошибке в сообщение, которое могло бы сообщать через Интернет.

Ответ 1

Я нашел решение (используя 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 );
      }
   };

Ответ 2

Если отражение происходит в другом потоке, оболочка не собирается ломать его.