Pergunta

Eu estou querendo saber qual a melhor maneira é ter um "se tudo mais falhar pegá-lo".

Quer dizer, você está segurando o máximo de exceções possível em sua aplicação, mas ainda não estão vinculados a ser erros, então eu preciso ter algo que captura todas as exceções não tratadas para que eu possa coletar informações e armazenar -los em um banco de dados ou submetê-los a um serviço web.

Será que o AppDomain.CurrentDomain.UnhandledException evento captura de tudo? Mesmo se o aplicativo é multithreaded?

Nota lateral: Windows Vista expõe funções de API nativas que permitem que qualquer aplicativo para recuperar-se após um acidente ... não consigo pensar do nome agora ... mas eu prefiro não usá-lo, como muitos dos nossos usuários ainda estão usando o Windows XP.

Foi útil?

Solução

Eu apenas joguei com o comportamento UnhandledException do AppDomain, (Esta é a última etapa da excepção não está registrado no)

Sim, depois de processar os manipuladores de eventos a sua aplicação será terminada e o desagradável "... programa parou de diálogo de trabalho" mostrado.

:) Você ainda pode evitar isso.

Confira:

class Program
{
    void Run()
    {
        AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

        Console.WriteLine("Press enter to exit.");

        do
        {
            (new Thread(delegate()
            {
                throw new ArgumentException("ha-ha");
            })).Start();

        } while (Console.ReadLine().Trim().ToLowerInvariant() == "x");


        Console.WriteLine("last good-bye");
    }

    int r = 0;

    void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        Interlocked.Increment(ref r);
        Console.WriteLine("handled. {0}", r);
        Console.WriteLine("Terminating " + e.IsTerminating.ToString());

        Thread.CurrentThread.IsBackground = true;
        Thread.CurrentThread.Name = "Dead thread";            

        while (true)
            Thread.Sleep(TimeSpan.FromHours(1));
        //Process.GetCurrentProcess().Kill();
    }

    static void Main(string[] args)
    {
        Console.WriteLine("...");
        (new Program()).Run();
    }
}

P.S. Do lidar com o não manipulado para Application.ThreadException (WinForms) ou DispatcherUnhandledException (WPF) no nível superior.

Outras dicas

Em ASP.NET, você usa a função Application_Error no arquivo Global.asax.

No WinForms, você usa o MyApplication_UnhandledException no arquivo ApplicationEvents

Ambas as funções são chamadas, se uma exceção não tratada ocorre em seu código. Você pode registrar a exceção e apresentar uma mensagem agradável para o usuário destas funções.

Para aplicações WinForm, além de AppDomain.CurrentDomain.UnhandledException Eu também uso Application.ThreadException e Application.SetUnhandledExceptionMode (w / UnhandledExceptionMode.CatchException). Esta combinação parece captura tudo.

No segmento principal, você tem as seguintes opções:

Para outros tópicos:

  • tópicos secundária não têm exceções não tratadas-; usar SafeThread
  • segmentos de trabalho: (temporizador, ThreadPool) não há nenhuma rede de segurança em tudo

Tenha em mente que esses eventos não alça exceções, eles simplesmente relatório -los para a aplicação - muitas vezes quando é tarde demais para fazer qualquer coisa útil / sane sobre eles

Registro de exceções é bom, mas aplicações de monitoramento é melhor; -)

Aviso: Eu sou o autor do artigo SafeThread

Para WinForms, não se esqueça de anexar ao evento não manipulado exceção do segmento atual também (especialmente se você estiver usando multi threading).

Alguns links em melhores práticas aqui e aqui e aqui (provavelmente a melhor manipulação artigo exceção para .net)

Há também uma coisa legal chamado ELMAH que irá registrar todos os erros ASP.NET que ocorrer em uma aplicação web. Eu sei que você está perguntando sobre uma solução Winform App, mas eu senti isso poderia ser benéfico para qualquer pessoa que necessite deste tipo de coisa em uma aplicação web. Vamos utilizá-lo onde eu trabalho e tem sido muito útil na depuração (especialmente em servidores de produção!)

Aqui estão algumas características que ele tem (puxado para a direita fora da página):

  • Registro de quase todas as exceções não tratadas.
  • A página da web para visualizar remotamente todo o log de exceções recodificados.
  • A página da web para visualizar remotamente os detalhes completos de qualquer registrado exceção.
  • Em muitos casos, você pode rever a tela original amarelo da morte que ASP.NET gerado para uma dada exceção, mesmo com o modo customErrors desligada.
  • Uma notificação de cada erro no momento em que ocorre e-mail.
  • Um feed RSS dos últimos 15 erros do registro.
  • Uma série de implementações de armazenamento de apoio para o registo, incluindo in-memory, Microsoft SQL Server e vários contribuído pela comunidade.

Você pode monitorar a maioria das exceções em que manipulador mesmo em aplicativos multithreaded, mas .NET (começando com 2,0) não permitirá que você para cancelar exceções não tratadas a menos que você ativar o modo de compatibilidade 1.1. Quando isso acontece o AppDomain será encerrado, não importa o quê. O melhor que você pode fazer é iniciar o aplicativo em um AppDomain diferente para que você pode lidar com essa exceção e criar um novo AppDomain para reiniciar o aplicativo.

Eu estou usando a seguinte abordagem, que trabalha e reduz consideravelmente a quantidade de código (ainda não tenho certeza se existe uma maneira melhor ou o que as armadilhas do que poderia ser. Sempre que você ligar: I quess os quys dando contras seria suficiente educado para esclarecer suas ações; )

try 
{
    CallTheCodeThatMightThrowException()
 }
catch (Exception ex)
{
    System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace ();
    Utils.ErrorHandler.Trap ( ref objUser, st, ex );
} //eof catch

E aqui está o código ErrorHandler: Apenas para tornar clara-: objUser - é o objeto modelar os appusers (que você pode obter informações como nome de domínio, departamento, região, etc., para fins de registro Ilog registador - é o objecto de log - e.g. a uma realizar as actividades de abate StackTrace st - o objeto StackTrace dando-lhe informações de depuração para o aplicativo

using System;
using log4net; //or another logging platform

namespace GenApp.Utils
{
  public class ErrorHandler
  {
    public static void Trap ( Bo.User objUser, ILog logger, System.Diagnostics.StackTrace st, Exception ex )
    {
      if (ex is NullReferenceException)
      { 
      //do stuff for this ex type
      } //eof if

      if (ex is System.InvalidOperationException) 
      {
        //do stuff for this ex type
      } //eof if

      if (ex is System.IndexOutOfRangeException) 
      {
        //do stuff for this ex type
      } //eof if

      if (ex is System.Data.SqlClient.SqlException)
      {
        //do stuff for this ex type
      } //eof if

      if (ex is System.FormatException)
      {
        //do stuff for this ex type
      } //eof if

      if (ex is Exception)
      {
        //do stuff for this ex type
      } //eof catch

    } //eof method 

  }//eof class 
} //eof namesp

Em um aplicativo GUI manged, por padrão, as exceções que se originam no segmento de GUI são manipulados por tudo o que é atribuído ao Application.ThreadException.

As excepções que se originam em outros tópicos são tratados por AppDomain.CurrentDomain.UnhandledException.

Se você quer que seus GUI exceções de rosca para trabalho apenas como seus-não os GUI, de modo que eles são manipulados por AppDomain.CurrentDomain.UnhandledException, você pode fazer isso:

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);

Uma vantagem de pegar as exceções thread de GUI usando ThreadException é que você pode dar o uso das opções de deixar o aplicativo continuar. Para certificar-se há arquivos de configuração estão substituindo o comportamento padrão, você pode ligar no:

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

Você ainda são vulneráveis ??a excepções DLLs nativas mal comportados. Se uma dll nativa instala seu próprio manipulador usando Win32 SetUnhandledExceptionFilter, supõe-se para salvar o ponteiro para o filtro anterior e chamá-lo também. Se ele não fizer isso, a sua não vai manipulador' chamado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top