web-dev-qa-db-fra.com

Génération automatique de dumps sur crash .NET

Je sais comment générer des fichiers Crash Dump avec ADPlus ou DebugDiag, mais je me demande s’il existe un moyen de le faire sur l’ordinateur d’un client sans installer ces outils ... précisément, j'aimerais pouvoir configurer mon application utilisant une valeur de registre, par exemple) pour générer un vidage sur incident en cas de défaillance critique. Plus précisément, je dois être capable de faire cela à partir d’une application C #, mais cela ne me dérange pas si P/Invoke’ing est nécessaire. Merci!

38
Michael Bray

Notez que la création d'un minidump à partir du processus "défaillant" (ou même du thread) n'est pas anodine ou peut ne pas être exacte (également MiniDumpWriteDump Remarques de la fonction).

En outre, si votre processus est dans une telle colère que vous pourriez avoir besoin d'écrire un vidage sur incident, la situation est généralement si compliquée que même tenter de créer un vidage sur incident peut provoquer un autre blocage (des situations telles que celles qui sont suspendues, plus difficile à "attraper" dans le processus actuel).

La meilleure chose à faire, si vous ne pouvez pas installer d’applications séparées sur les systèmes de votre client, est de démarrer un processus externe (qui peut également échouer dans des situations critiques!) Et de laisser cela créer un crash pour votre processus actuel (voir Superassert.NET de John Robbins ). Vous pouvez même aller jusqu'à mettre le binaire externe dans les ressources de votre application, puis extrayez-le au démarrage (de manière à minimiser les pannes dans les situations critiques) sur le disque (si vous osez).

14
Christian.K

Vous pouvez configurer Windows Error Reporting (WER) pour créer un vidage sur incident dans un répertoire spécifique à l'aide du script de registre suivant:

 Editeur de registre Windows, version 5.00 .__ [Rapport d'erreur\HKEY_LOCAL_MACHINE\LOGICIEL\Microsoft\Windows\Windows\LocalDumps]. 
 "DumpType" = dword: 00000002 
 "CustomDumpFlags" = dword: 00000000 

Le vidage ira dans C:\Dumps avec un nom qui correspond au nom du processus qui s'est bloqué. DumpType = 2 donne une image mémoire complète. DumpType = 1 donne un mini-vidage. Sur les machines 64 bits, vous n'avez pas besoin de les placer sous les nœuds Wow32. WER utilise uniquement la clé de registre non-WOW spécifiée ci-dessus.

Selon le type d'accident, cette méthode peut ne pas fonctionner. Je n'ai pas encore compris pourquoi ni quels types d'accidents ne sont pas pris en compte. N'importe qui?

14
Charles

Je pense que si votre application est bloquée, vous pourriez aussi bien tenter votre chance pour créer un fichier mini-dump. Quel est le pire qui puisse arriver, votre application va planter? De toute façon, c'est ce que vous faites, alors autant essayer.
Le code dans le forum MSDN mentionné par VoiDed semble plutôt solide. J'avais besoin d'une version VB.Net alors voici une version VB pour tous ceux qui pourraient en avoir besoin:

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

    <Runtime.InteropServices.DllImport("dbghelp.dll")> _
    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

Assurez-vous simplement que vous répondez fermement aux appels et vous devriez être relativement en sécurité.

7
Scott

Vous pouvez P/Invoke la fonction MiniDumpWriteDump de dbghelp.dll dans l'événement AppDomain.UnhandledException.

Dans ce cas, vous pouvez vider un journal des données d'exception .NET et écrire un minidump dans un fichier.

Il existe également un thread sur les forums MSDN qui décrit la signature P/Invoke et son utilisation appropriée.

5
Ryan Stecker

Vous pouvez appeler Environment.FailFast , ce qui:

La méthode FailFast écrit la chaîne de message dans le journal des événements de l'application Windows, crée un cliché de votre application, puis termine le processus en cours. La chaîne de message est également incluse dans les rapports d’erreurs à Microsoft.

Entre autres.

0
jack

Utilisez-vous un cadre de journalisation tel que log4net? Normalement, vous désactivez les messages de niveau débogage pour une version. Cependant, vous pouvez penser à écrire un appender spécial qui enregistre dans un fichier uniquement dans certains cas (comme un crash). Cet appender écrit d'abord dans un tampon de mémoire contenant uniquement de la mémoire, qui peut être écrit dans un fichier, déclenché plus tard, par exemple par un gestionnaire d'exception comme suggéré par 280Z28.

0
tanascius

En fonction du type d'informations dont vous avez besoin, vous pouvez ajouter un gestionnaire pour l'événement AppDomain.UnhandledException? (Je sais que ce n'est pas exactement ce que vous recherchez, mais il est définitivement disponible sur les ordinateurs clients.)

0
Sam Harwell