2009-06-24 14 views
13

En primer lugar, el problema: Tengo varios proyectos gratuitos, y como cualquier software que contienen errores. Algunos compañeros usuarios cuando se encuentran errores me envían un informe de errores con seguimientos de pila. Para simplificar la búsqueda de un lugar de falla, quiero ver los números de línea en esta pila. Si la aplicación se envió sin archivos .pdb, se pierde toda la información de la línea, por lo que actualmente todos mis proyectos implementados con archivos .pdb, y por lo tanto los trazados de la pila generados tienen estos números. ¡Pero! Pero no quiero ver estos archivos en distribución y quiero eliminar todos los archivos .pdb. Ellos confundir a los usuarios, consumen espacio en el instalador, etc.¿Recrea el seguimiento de la pila con los números de línea del informe de errores del usuario en .net?

solución de Delphi: hace mucho tiempo, cuando yo era un programador delphi, he utilizado la siguiente técnica: en mi caminar excepción de aplicación en la pila y recoger direcciones. Luego, cuando recibo el informe de errores, utilicé una herramienta que reconstruye un seguimiento de pila válido con nombres de funciones y números de línea basados ​​en las direcciones recopiladas y los archivos de símbolos correspondientes ubicados en MI máquina.

Pregunta: ¿Existe alguna lib, técnica o lo que sea para hacer lo mismo en .NET?

Actualización de estado: Muy interesante, que a menudo hacer una pregunta es la mejor manera de comenzar su propia investigación. Por ejemplo, pienso en este problema por algún tiempo, pero empiezo a buscar respuestas solo hace varios días.

Opción 1: MiniDumps. Después de mucho buscar en Google, he encontrado una forma de crear mini volcado desde el código y cómo recrear la pila desde el mini volcado administrado.

Esta solución, sin embargo necesidad de redistribuir dos conjuntos adicionales (~ 1 MB de tamaño), y mini dumps toma algo de espacio, y es incómodo para el usuario enviarlos por correo electrónico. Entonces para mis propósitos, en este momento, es inaceptable.

Opción 2: Gracias a weiqure por pista. Es posible extraer el desplazamiento IL gestionado para cada marco de pila. Ahora el problema es cómo obtener los números de línea de .pdb en función de estos desplazamientos. Y lo que he encontrado:

El uso de este herramienta, es posible crear archivos xml para cada compilación de lanzamiento y ponerlos en repository. Cuando se produce una excepción en la máquina del usuario, es posible crear un mensaje de error formateado con compensaciones IL. Entonces el usuario envía este mensaje (muy pequeño) por correo. Y finalmente, es posible crear una herramienta simple que recree la pila resultante del mensaje de error formateado.

Me pregunto por qué nadie más no implementa una herramienta como esta? No creo que esto sea interesante solo para mí.

+0

FYI: En Delphi esto es fácil ahora porque está loco. Excepto que pone un rastro de pila y otras informaciones útiles en un informe sobre excepciones (no controladas). – schnaader

+1

¿Qué opción eligió? Estoy buscando una solución yo también. – Giorgi

+1

Elegí la segunda opción y escribí un montón de clases para reemplazar el volcado de excepción interno. También estoy planeando escribir un artículo sobre mi solución con toda la información y las fuentes. – arbiter

Respuesta

2

Puede crear un minivolcado de aplicación siempre que haya un error y usarlo para el análisis fuera de línea. Esto no requiere que implemente pdbs en la máquina cliente. El enlace This puede servir como un buen punto de partida para el aprendizaje.

+0

Artículo interesante, pero requiere más tiempo para pensar leyendo. Y, en general, es principalmente para la depuración (no recreación de pila), y también requiere muchas acciones del usuario. – arbiter

+0

No estoy familiarizado con C# .Net, pero en las aplicaciones WIN32 C++, los minivolcados son muy efectivos para analizar los problemas del sitio del cliente. Supongo que algo similar también debe existir para C#. – Canopus

+1

Los minivolcados son muy útiles para el código nativo de C++. ¡Pero no he encontrado una forma de recrear un seguimiento de pila .NET desde un archivo de minivolcado! – mmmmmmmm

5

Debe usar Environment.FailFast, llame a FailFast en el Application.UnhandledException y se creará un archivo de volcado para usted.

Desde el MSDN:

El método FailFast escribe una entrada de registro en el registro de sucesos de aplicación de Windows utilizando el parámetro de mensaje, crea un vertedero de su aplicación, y luego termina el proceso actual.

utilizar el método de FailFast en lugar del método Salir para finalizar su aplicación si el estado de su solicitud está dañado sin posibilidad de reparación, y ejecutar try-finally bloques y finalizadores voluntad recursos de programas corruptos de su aplicación. El método FailFast finaliza el proceso actual y ejecuta cualquier objeto CriticalFinalizerObject, pero no ejecuta ningún try-finally bloques o finalizadores activos.

Puede escribir una aplicación sencilla que recopilará los archivos de registro y se los enviará.

Ahora, abrir el archivo de volcado es un poco complicado, Visual Studio no puede manejar el archivo de volcado administrado (corregido en .NET 4.0) puede usar WinDBG pero necesita usar SOS.

+3

No adecuado para mis necesidades: 1. La mayoría de las excepciones son recuperables, por lo que la aplicación debe mostrar información (opcionalmente enviarla por correo) y continuar. Este método aplastará la aplicación en cualquier excepción no controlada. 2. Este método requiere mucha acción del usuario para enviarme información de excepción. Casi nadie hará eso. Los usuarios pueden esperar que puedan copiar la información pasada del cuadro de diálogo de error y enviarla por correo, nada más. – arbiter

12

se puede obtener el desplazamiento de la última instrucción MSIL de la excepción usando 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()); 
} 

Salida:

en ConsoleApplicationN.exe.Program.Main (IL compensado : 0x7)
en ConsoleApplicationN.exe.Program.ThrowError (IL offset: 0x1b)
en mscorlib.dll.DateTime..ctor (IL offset: 0x9)
en mscorlib.dll.Da teTime.DateToTicks (IL offset: 0x61)
Mensaje: los parámetros Year, Month y Day describen un DateTime no representable.

A continuación, puede utilizar Reflector o ILSpy para interpretar el desplazamiento:

.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 
} 

Usted sabe que la instrucción antes de 0x1b lanzó la excepción. Es fácil encontrar el código C# para que:

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

Usted puede asignar el código IL a su código C# ahora, pero creo que la ganancia sería demasiado poco y el esfuerzo demasiado grande (aunque puede haber un reflector enchufar). Deberías estar bien con el desplazamiento IL.

+0

Me gusta su idea, y votó a favor su respuesta, pero esta es solo una idea preliminar. Tal vez exista algún método, o información sobre cómo asignar este desplazamiento de IL al archivo .pdb correspondiente (porque hay muchos ensamblados en el proyecto, y cada ensamblaje tiene su propio .pdb). – arbiter

+0

Probablemente sería mejor si simplemente hiciera otra pregunta sobre cómo asignar el código IL a los archivos .pdb o al código C#. Aunque, como dije, no estoy seguro de si esto será más fácil que solo hacerlo manualmente. – weiqure

+0

Para ver la ventana: new System.Diagnostics.StackTrace ($ exception) .GetFrames() [0] .ILOffset – zproxy

1

Está absolutamente en el camino correcto de necesitar archivos PDB para obtener con precisión la información de fuente y línea. Me gustaría cuestionar cualquier problema percibido con el envío de archivos PDB como una preocupación válida, pero, suponiendo que exista una razón válida, puede hacerlo, pero requiere un mayor esfuerzo de parte suya para crear el entorno de creación de software adecuado.

Microsoft Symbol Server indexará los símbolos de depuración y los almacenará para utilizarlos en una fecha posterior cuando tenga un volcado de emergencia, por ejemplo, y necesite símbolos disponibles. Puede apuntar a Visual Studio o Windbg en su propia instancia de servidor de símbolos, al igual que Microsoft's, y desplegará los símbolos necesarios para depurar esa versión de su aplicación (suponiendo que haya indexado los símbolos con el servidor de símbolos antes del envío).

Una vez que tenga los símbolos apropiados para una compilación, debe asegurarse de tener los archivos fuente apropiados que pertenecen a esa compilación.

Aquí es donde Microsoft Servidor de origen entra. Al igual que en los índices de servidor de símbolos símbolos, servidor de origen indexará fuente para asegurarse de que tiene la versión adecuada del código fuente que pertenece a una compilación de software.

últimas versiones de de control de versiones, servidor de símbolos de y Servidor de origen deben ser parte de su estrategia de gestión de configuración de software.

Existen herramientas de terceros, algunas comerciales, que le proporcionarán una API para generar instantáneas de aplicaciones, pero como usted ya entiende, necesita un mecanismo para obtener esas instantáneas cargadas en su entorno de alguna manera.

John Robbins en PDB Files

John Robbins en Source Server

Salida WinDbg documentation en conseguir un servidor de símbolos en funcionamiento.

Cuestiones relacionadas