Перехват исключений для входа в приложение C ++ CLI - PullRequest
0 голосов
/ 15 июля 2009

Я пытаюсь перехватить все исключения в приложении 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 голосов
/ 04 августа 2009

Я нашел решение (используя 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 голосов
/ 15 июля 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...