2009-06-24 11 views
13

In primo luogo, il problema: Ho diversi progetti gratuiti e come ogni software contengono bug. Alcuni utenti quando incontrano un bug mi inviano segnalazioni di bug con tracce dello stack. Per semplificare la ricerca di un errore, voglio vedere i numeri di riga in questo stack. Se l'applicazione viene spedita senza file .pdb, tutte le informazioni sulla linea vengono perse, quindi al momento tutti i miei progetti sono distribuiti con file .pdb e quindi le tracce dello stack generate hanno questi numeri. Ma! Ma non voglio vedere questi file in distribuzione e voglio rimuovere tutti i .pdb. Essi confondono gli utenti, consumano spazio nel programma di installazione, eccRicrea traccia di stack con i numeri di riga del rapporto bug utente in .net?

soluzione Delphi: Molto tempo fa, quando ero un programmatore Delphi, ho usato la seguente tecnica: il mio cammino eccezione applicazione su stack e raccogliere indirizzi. Quindi, quando ricevo il bug report, ho usato uno strumento che ricostruisce la traccia dello stack valida con nomi di funzioni e numeri di linea in base agli indirizzi raccolti e ai corrispondenti file di simboli che si trovano sulla mia macchina.

Domanda: C'è qualche lib, o tecnica o qualsiasi altra cosa per fare lo stesso in .NET?

Aggiornamento di stato: Molto interessante, che spesso fare una domanda è il modo migliore per iniziare la propria indagine. Per esempio, penso a questo problema da un po 'di tempo, ma inizio a cercare risposte solo alcuni giorni fa.

Opzione 1: MiniDump. Dopo molte ricerche ho trovato un modo per creare un mini dump dal codice e come ricreare lo stack dal mini dump gestito.

Questa soluzione però bisogno di ridistribuire due gruppi supplementari (~ 1 MB di dimensione), e i mini dump richiedono un po 'di spazio, e non è comodo per l'utente inviarli via email. Quindi per i miei scopi, al momento, è inaccettabile.

Opzione 2: grazie a weiqure per l'indizio. È possibile estrarre l'offset IL gestito per ogni frame dello stack. Ora il problema è come ottenere i numeri di riga da .pdb in base a questi offset. E quello che ho trovato:

Usando questo strumento, è possibile creare file xml per ogni build di rilascio e metterli in repository. Quando si verifica un'eccezione sul computer dell'utente, è possibile creare un messaggio di errore formattato con offset IL. Quindi l'utente invia questo messaggio (molto piccolo) per posta. E infine, è possibile creare un semplice strumento che ricrea lo stack risultante dal messaggio di errore formattato.

Mi chiedo solo perché nessun altro non implementa uno strumento come questo? Non credo che questo sia interessante solo per me.

+0

FYI: In Delphi questo è facile ora perché c'è madExcept che mette una traccia dello stack e altre informazioni utili in un report su eccezioni (non gestite). – schnaader

+1

Quale opzione hai scelto? Anch'io sto cercando una soluzione. – Giorgi

+1

Ho scelto la seconda opzione e scrivo un mucchio di classi per sostituire il dump delle eccezioni interno. Ho anche in programma di scrivere un articolo sulla mia soluzione con tutte le informazioni e le fonti. – arbiter

risposta

2

È possibile creare un minidump dell'applicazione ogni volta che si verifica un errore e utilizzarlo per l'analisi offline. Questo non richiede di distribuire pdbs sul computer client. Il collegamento This può essere un buon punto di partenza per l'apprendimento.

+0

Articolo interessante, ma richiede più tempo per leggere il pensiero. E in generale è principalmente per il debug (non lo stack di ricreazione), e richiede anche un sacco di azioni da parte dell'utente. – arbiter

+0

Non ho familiarità con C# .Net, ma nelle applicazioni C++ WIN32, i minidump sono molto efficaci per analizzare i problemi del sito del cliente. Immagino che qualcosa di simile debba esistere anche per C#. – Canopus

+1

I minidump sono molto utili per il codice C++ nativo. Ma non ho trovato un modo per ricreare una traccia dello stack .NET da un file minidump! – mmmmmmmm

5

È necessario utilizzare Environment.FailFast, chiamare FailFast nel Application.UnhandledException e verrà creato un file di dump per l'utente.

da MSDN:

Il metodo FailFast scrive una voce di registro nel registro eventi Applicazione Windows utilizzando il parametro messaggio, crea un discarica della vostra applicazione, e quindi termina il processo corrente.

utilizzare il metodo FailFast invece che il metodo Esci per interrompere l'applicazione se lo stato della vostra applicazione è danneggiato in modo irreparabile, e l'esecuzione di try-finally blocchi e finalizzatori sarà risorse del programma corrotti dell'applicazione. Il metodo Failfast termina il processo corrente ed esegue qualsiasi oggetto CriticalFinalizerObject, ma non esegue alcun blocco o finalizzatore attivo alla fine dello .

È possibile scrivere una semplice app che raccoglierà i file di registro e li invierà a voi.

Ora, l'apertura del file di dump è un po 'complicata, Visual Studio non può gestire il file di dump gestito (risolto in .NET 4.0) è possibile utilizzare WinDBG ma è necessario utilizzare SOS.

+3

Non adatto alle mie esigenze: 1. La maggior parte delle eccezioni è recuperabile, quindi l'app deve mostrare informazioni (eventualmente inviarla alla posta) e continuare. Questo metodo schiaccerà l'app su ogni eccezione non gestita. 2. Questo metodo richiede molte azioni da parte dell'utente per inviare a me le informazioni sulle eccezioni. Quasi nessuno lo farà. Puoi aspettarti dagli utenti che possono copiare le informazioni passate dalla finestra di dialogo degli errori e inviarle per posta, non di più. – arbiter

12

È possibile ottenere l'offset dell'ultima istruzione MSIL dal Eccezione utilizzando System.Diagnostics.StackTrace:

// Using System.Diagnostics 
static void Main(string[] args) 
{ 
    try { ThrowError(); } 
    catch (Exception e) 
    { 
     StackTrace st = new System.Diagnostics.StackTrace(e); 
     string stackTrace = ""; 
     foreach (StackFrame frame in st.GetFrames()) 
     { 
      stackTrace = "at " + frame.GetMethod().Module.Name + "." + 
       frame.GetMethod().ReflectedType.Name + "." 
       + frame.GetMethod().Name 
       + " (IL offset: 0x" + frame.GetILOffset().ToString("x") + ")\n" + stackTrace; 
     } 
     Console.Write(stackTrace); 
     Console.WriteLine("Message: " + e.Message); 
    } 
    Console.ReadLine(); 
} 

static void ThrowError() 
{ 
    DateTime myDateTime = new DateTime(); 
    myDateTime = new DateTime(2000, 5555555, 1); // won't work 
    Console.WriteLine(myDateTime.ToString()); 
} 

uscita:

a ConsoleApplicationN.exe.Program.Main (offset IL : 0x7)
a ConsoleApplicationN.exe.Program.ThrowError (IL offset: 0x1b)
a mscorlib.dll.DateTime..ctor (IL offset: 0x9)
a mscorlib.dll.Da teTime.DateToTicks (IL offset: 0x61)
Messaggio: i parametri di anno, mese e giorno descrivono un DateTime non rappresentabile.

È quindi possibile utilizzare Reflector o ILSpy per interpretare l'offset:

.method private hidebysig static void ThrowError() cil managed 
{ 
    .maxstack 4 
    .locals init (
     [0] valuetype [mscorlib]System.DateTime myDateTime) 
    L_0000: nop 
    L_0001: ldloca.s myDateTime 
    L_0003: initobj [mscorlib]System.DateTime 
    L_0009: ldloca.s myDateTime 
    L_000b: ldc.i4 0x7d0 
    L_0010: ldc.i4 0x54c563 
    L_0015: ldc.i4.1 
    L_0016: call instance void [mscorlib]System.DateTime::.ctor(int32, int32, int32) 
    L_001b: nop 
    L_001c: ldloca.s myDateTime 
    L_001e: constrained [mscorlib]System.DateTime 
    L_0024: callvirt instance string [mscorlib]System.Object::ToString() 
    L_0029: call void [mscorlib]System.Console::WriteLine(string) 
    L_002e: nop 
    L_002f: ret 
} 

Voi sapete che l'istruzione prima 0x1b ha generato l'eccezione. E 'facile trovare il codice C# per questo:

myDateTime = new DateTime(2000, 5555555, 1); 

Potreste mappare il codice IL al codice C# ora, ma penso che il guadagno sarebbe troppo poco e lo sforzo troppo grande (anche se ci potrebbe essere un riflettore collegare). Dovresti stare bene con l'offset IL.

+0

Mi piace la tua idea e la tua risposta è stata aumentata, ma questa è solo una bozza di idea. Forse esiste qualche metodo, o informazioni su come mappare questo offset IL al file .pdb corrispondente (perché ci sono molti assembly nel progetto, e ogni assembly ha il proprio .pdb). – arbiter

+0

Probabilmente sarebbe meglio se tu facessi un'altra domanda su come mappare il codice IL nei file .pdb o nel codice C#. Anche se, come ho detto, non sono sicuro che sia più facile che farlo manualmente. – weiqure

+0

Per la finestra di controllo: nuovo System.Diagnostics.StackTrace ($ exception) .GetFrames() [0] .ILOffset – zproxy

1

Sei assolutamente sulla buona strada per il bisogno di file PDB per ottenere con precisione informazioni di origine e di linea. Metterei in discussione qualsiasi problema percepito con i file PDB di spedizione come un problema valido, ma, supponendo che ci sia un motivo valido, è possibile farlo ma richiede un maggiore sforzo da parte dell'utente per creare l'ambiente di sviluppo del software appropriato.

Microsoft Symbol Server indicizzerà i simboli di debug e li memorizzerà per l'utilizzo in un secondo momento quando si verifica un dump di arresto anomalo, ad esempio, e sono necessari simboli disponibili. Puoi puntare Visual Studio o Windbg alla tua istanza del server dei simboli, proprio come Microsoft's, e tirerà giù i simboli necessari per il debug di quella versione della tua applicazione (supponendo che tu abbia indicizzato i simboli con il server dei simboli prima della spedizione).

Una volta che i simboli appropriati per una build, è necessario assicurarsi di disporre dei file di origine appropriati che appartengono a tale build.

Questo è dove Microsoft Source Server entra in gioco. Proprio come, dove gli indici Symbol Server simboli, server di origine sarà indice fonte per assicurarsi di avere la versione appropriata del codice sorgente appartenente ad una build del software.

versioni di sviluppo del Version Control, Symbol Server e origine server dovrebbero essere parte della vostra strategia di gestione della configurazione software.

Esistono strumenti di terze parti, alcuni commerciali, che forniscono un'API per generare snapshot dell'applicazione, ma come già si comprende, è necessario un meccanismo per ottenere tali snapshot caricati nell'ambiente in qualche modo.

John Robbins su PDB Files

John Robbins su Source Server

Partenza WinDbg documentation su come ottenere un server di simboli attivo e funzionante.

Problemi correlati