2008-12-11 8 views
57

Estoy buscando un modo en .NET (2.0, C# en particular) para que el código fuente desencadene una interrupción de depuración como si se hubiera establecido un punto de interrupción en ese punto, sin tener que recordar establecer un punto de interrupción específico allí en el depurador y sin interferir con el tiempo de ejecución de la producción.¿Puede el código fuente de .NET codificar un punto de interrupción de depuración?

Nuestro código necesita tragarse excepciones en la producción para no interrumpir una aplicación cliente que se vincule con nosotros, pero estoy tratando de configurarlo para que esos errores aparezcan para ser analizados si resulta ser corriendo en un depurador, y de lo contrario será ignorado de forma segura.

Mi intento de utilizar Debug.Assert(false) ha sido menos que ideal, y supongo que Debug.Fail() se comportaría de la misma manera. En teoría, no debería tener ningún efecto en la producción, y se detiene con éxito cuando se depura, pero por diseño (hasta donde puedo decir) no hay forma de continuar la ejecución si se quiere ignorar ese error, como se podría hacer con un punto de ruptura real , y como lo haría en producción donde tragamos el error. También aparentemente rompe la evaluación de estado variable porque el depurador realmente se detiene en el código del sistema nativo y no en el nuestro, por lo que la ayuda para la depuración es limitada. (Tal vez me falta alguna forma de volver a las cosas para ver las variables y así sucesivamente dónde sucedió. ???)

Esperaba algo como Debug.Break(), pero no parece existir (a menos que tal vez en una versión posterior de .NET?), y ningún otro método Debug parece aplicable, tampoco.

Actualización: Si bien la respuesta de ctacke es la mejor opción para lo que yo estaba buscando, he puesto también descubrió un truco con Debug.Assert() - cuando se ejecuta en el depurador - Pausa el depurador, vaya a el código para la depuración. Afirma la llamada pendiente (resaltada en verde porque está abajo en el código de la estructura) y presiona Salir (shift-F11), luego presiona Ignorar en el cuadro de diálogo de afirmación. Esto dejará el depurador en pausa al retorno de la declaración (y podrá continuar la ejecución como si no hubiera ocurrido, porque se ignoró). Puede haber otras formas de hacer más o menos lo mismo (¿es mejor intentarlo de nuevo con Reintentar?), Pero de esta manera fue intuitivo.

Respuesta

109

Probablemente está después de algo como esto:

if(System.Diagnostics.Debugger.IsAttached) 
    System.Diagnostics.Debugger.Break(); 

Por supuesto eso todavía se compilará en una versión de lanzamiento. Si quieres que se comporte más como el objeto de depuración en el que el código simplemente no existe en una versión de lanzamiento, entonces se podría hacer algo como esto:

[Conditional("DEBUG")] 
void DebugBreak() 
{ 
    if(System.Diagnostics.Debugger.IsAttached) 
    System.Diagnostics.Debugger.Break(); 
} 

A continuación, agregue una llamada a ella en su código.

+2

también puede usar #if DEBUG ... #endif en su lugar –

+10

Claro, pero es mucho más feo que un condicional porque tiene que ajustar cada llamada al método con la directiva precompiladora también. – ctacke

+0

Para aclarar, desde MSDN: 'Cuando se llama a un método marcado como condicional, la presencia o ausencia del símbolo de preprocesamiento especificado determina si la llamada se incluye u omite. Si el símbolo está definido, la llamada está incluida; de lo contrario, la llamada se omite, así como 'Un método condicional debe ser un método en una declaración de clase o estructura y debe tener un tipo de retorno de vacío. – Kiruse

11

System.Diagnostics.Debugger.Break?

+0

(Originalmente respondí en Dic '08 como otra respuesta antes de saber que podía comentar las respuestas a mi propia pregunta): Ahhh, gracias, shahkalpesh. System.Diagnostics.Debugger.Break() es un buen comienzo. Eso es lo que me faltaba, en Debugger en lugar de Debug. Parece que eso interrumpirá y pedirá que adjunte un depurador, lo cual es posible que desee evitar. Pero parece que ... if (Debugger.IsAttached) Debugger.Break(); ... hace lo que estoy buscando, como sugirió ctacke. Debugger.Launch() podría funcionar para sitaciones ligeramente diferentes, en las que desea un depurador si no había ninguno. –

8

me encontré con una situación donde una vez que esto no funcionaba

System.Diagnostics.Debugger.Break(); 

pero esto hizo

System.Diagnostics.Debugger.Launch(); 
+0

Si el depurador no está conectado, primero debe adjuntarlo a Debugger.Launch() y luego puede usar Debugger.Break(). Esto es necesario si desea depurar una solución donde un proceso inicia otro proceso y desea depurar ambos. –

4

¿Qué tal si simplemente configura Visual Studio para que aparezca con el depurador incluso si se lo traga?

hacer esto:

  • Ir a Debug-> Excepciones ...
  • Encuentra la excepción derecha, o añadirlo si es su propia
  • Marque la casilla "Arrojado" para la excepción

Esto detendrá Visual Studio en la ubicación que se lanza excepción, no sólo si no se maneja

Puede ver más información here.

+0

Ese es un truco que vale la pena mencionar. Es particularmente útil para identificar dónde se produce el problema por primera vez (y aún así obtener el estado miembro, no solo el seguimiento de la pila de excepción). Pero en este caso me gustaría que la fuente nos avise de las excepciones que no esperamos específicamente y no se pueden configurar. –

3

Un buen truco que encontré es poner Debugger.Break() en el ctor de su Excepción.

+0

Buen truco. No es bueno para las excepciones del sistema, por supuesto, pero podemos intentarlo con nuestros propios tipos de excepciones, condicionales a uno o dos miembros estáticos para que podamos activarlo y desactivarlo, junto con verificar Debugger.IsAttached; una configuración podría Romper()/Lanzar() incluso sin IsAttached, otra solo si lo es. –

1

En Visual Studio 2010, golpeando reintento en un diálogo Debug.Assert le lleva a la aserción de depuración fallado, al igual que si tuviera un punto de interrupción.

+0

Hmmm, gracias. Tendré que intentarlo la próxima vez que presione una afirmación mientras estoy en el depurador. Nunca he tenido claro qué se suponía que significaba "Retry". Tal vez eso es un remanente de un uso anterior de ese diálogo. –

+1

Es un diálogo mal redactado, seguro. –

4

Si usted quiere tener una sola línea de código en lugar de 4, envuelva

#if DEBUG 
     if (Debugger.IsAttached) 
      Debugger.Break(); 
#endif 

en

public static class DebugHelper 
{ 
    [DebuggerHidden] 
    [Conditional("DEBUG")] 
    public static void Stop() 
    { 
     if (Debugger.IsAttached) 
      Debugger.Break(); 
    } 
} 

y utilizar

DebugHelper.Stop(); 

DebuggerHiddenAttribute se añade para evitar el depurador de detenerse en el código interno del método Stop y fr O entrando en el método con F11.

+0

+1 para la sugerencia y explicación '[DebuggerHidden]'; eso haría que el método condicionalmente compilado sea aún más útil. ¿Sabes cuánto tiempo ese atributo ha sido compatible? ¿Es algo nuevo, o incluso se remonta a .NET 2.0 y VS 2010 más o menos? –

+0

Supongo que ha sido desde la versión 1.1 https://msdn.microsoft.com/en-us/library/3a4d38ze(v=vs.v.71).aspx – Sergey

+0

O incluso desde 1.0 - anterior a Debugger.Break() se introdujo . https://msdn.microsoft.com/library/system.diagnostics.debugger.break(v=vs.110).aspx Vale la pena señalar que el comportamiento del método Break() se ha cambiado desde la versión 4.0 para los casos en que el depurador no está adjunto. – Sergey

Cuestiones relacionadas