Gerando despejos de colisão do .NET automaticamente

Eu sei como gerar arquivos Crash Dump com ADPlus ou DebugDiag, mas eu estou querendo saber se há uma maneira de fazer isso no computador de um cliente sem instalar essas ferramentas … especificamente, eu gostaria de ser capaz de configurar o meu aplicativo ( usando um valor de registro, por exemplo) para gerar um despejo de memory em caso de falha crítica. Mais especificamente, eu preciso ser capaz de fazer isso a partir de um aplicativo c #, mas não me importo P / Invoke’ing se necessário. Obrigado!

Observe que a criação de um minidespejo de dentro do processo de “falha” (ou até de thread) em si não é trivial ou pode não ser precisa (também os comentários da function MiniDumpWriteDump ).

Além disso, se o seu processo estiver em tal raiva que você pode precisar escrever um despejo de memory, a situação toda é tipicamente feita, que até mesmo tentar criar um crash dump poderia causar outro travamento (situações como ficar de lado – mas podem ser até mais difícil de “pegar” de dentro do processo atual).

A melhor coisa que você pode fazer, se não puder instalar aplicativos separados nos sistemas do seu cliente, é iniciar um processo externo (que também pode falhar em situações críticas!) E deixar que isso crie um crashdump a partir do seu processo atual (consulte Superassert. NET de John Robbins ). Você pode até ir tão longe, como colocar o binário externo nos resources do seu aplicativo, extraí-lo de lá na boot (como minimizar a falha em situtations críticas) para o disco (se você ousar).

Você pode configurar o Relatório de Erros do Windows (WER) para criar um despejo de memory em um diretório específico usando o seguinte script de registro:

 Windows Registry Editor versão 5.00
 [Relatório de erros do HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ Windows \ LocalDumps]
 "DumpFolder" = "C: \\ Dumps"
 "DumpCount" = dword: 00000064
 "DumpType" = dword: 00000002
 "CustomDumpFlags" = dword: 00000000

O despejo vai para C: \ Dumps com um nome que reflete o nome do processo que caiu. DumpType = 2 fornece um despejo de memory completo. DumpType = 1 fornece um mini dump. Em máquinas de 64 bits, você não precisa colocá-las sob os nós do Wow32. O WER usa apenas a chave de registro não WOW especificada acima.

Dependendo do tipo de falha, esse método pode não funcionar. Eu ainda tenho que descobrir por que ou quais tipos de falhas ele não captura. Alguém?

Eu acho que se o seu aplicativo é escolhido, então você pode tentar criar um arquivo de mini dump, o que é pior o que vai acontecer, seu aplicativo irá travar? Está fazendo isso de qualquer maneira, então você pode também tentar.
O código no fórum do MSDN mencionado pelo VoiDed parece bastante sólido. Eu precisava de uma versão VB.Net, então aqui está uma versão do VB para qualquer um que precise dela:

Friend Class MiniDump 'Code converted from C# code found here: http://social.msdn.microsoft.com/Forums/en-US/clr/thread/6c8d3529-a493-49b9-93d7-07a3a2d715dc Private Enum MINIDUMP_TYPE MiniDumpNormal = 0 MiniDumpWithDataSegs = 1 MiniDumpWithFullMemory = 2 MiniDumpWithHandleData = 4 MiniDumpFilterMemory = 8 MiniDumpScanMemory = 10 MiniDumpWithUnloadedModules = 20 MiniDumpWithIndirectlyReferencedMemory = 40 MiniDumpFilterModulePaths = 80 MiniDumpWithProcessThreadData = 100 MiniDumpWithPrivateReadWriteMemory = 200 MiniDumpWithoutOptionalData = 400 MiniDumpWithFullMemoryInfo = 800 MiniDumpWithThreadInfo = 1000 MiniDumpWithCodeSegs = 2000 End Enum  _ Private Shared Function MiniDumpWriteDump( _ ByVal hProcess As IntPtr, _ ByVal ProcessId As Int32, _ ByVal hFile As IntPtr, _ ByVal DumpType As MINIDUMP_TYPE, _ ByVal ExceptionParam As IntPtr, _ ByVal UserStreamParam As IntPtr, _ ByVal CallackParam As IntPtr) As Boolean End Function Friend Shared Sub MiniDumpToFile(ByVal fileToDump As String) Dim fsToDump As IO.FileStream = Nothing If (IO.File.Exists(fileToDump)) Then fsToDump = IO.File.Open(fileToDump, IO.FileMode.Append) Else fsToDump = IO.File.Create(fileToDump) End If Dim thisProcess As Process = Process.GetCurrentProcess() MiniDumpWriteDump(thisProcess.Handle, _ thisProcess.Id, _ fsToDump.SafeFileHandle.DangerousGetHandle(), _ MINIDUMP_TYPE.MiniDumpNormal, _ IntPtr.Zero, _ IntPtr.Zero, _ IntPtr.Zero) fsToDump.Close() End Sub End Class 

Apenas certifique-se de que você está solucionado com as chamadas e você deve estar relativamente seguro.

Você poderia P / Invoque a function MiniDumpWriteDump do MiniDumpWriteDump no evento AppDomain.UnhandledException .

Nesse caso, você poderia despejar um log dos dados de exceção do .NET e gravar um minidump no arquivo.

Há também um thread nos fóruns do MSDN, que descreve a assinatura P / Invoke e o uso adequado.

Dependendo do tipo de informação que você precisa, você poderia adicionar um manipulador para o evento AppDomain.UnhandledException ? (Eu sei que não é exatamente o que você está procurando, mas definitivamente está disponível nas máquinas clientes.)

Você usa uma estrutura de log como log4net? Normalmente, você desativa as mensagens no nível do debug para uma liberação. No entanto, você pode pensar em escrever um appender especial que registra em um arquivo apenas em determinados casos (como uma falha). Esse appender escreve primeiro em um ringbuffer de memory apenas, que pode ser gravado em um arquivo, mais tarde – acionado, por exemplo, por um exceptionhandler como sugerido por 280Z28.

Você pode chamar Environment.FailFast , que irá:

O método FailFast grava a seqüência de mensagem no log de events do aplicativo do Windows, cria um despejo do seu aplicativo e, em seguida, encerra o processo atual. A sequência de mensagens também está incluída no relatório de erros para a Microsoft.

Entre outras coisas.