Здравствуйте, elw00d, Вы писали:
E>А кто-нибудь писал плагины для Visual Studio ?
E>Интересует вопрос — можно ли в дебаге при остановке на исключении (которое отмечено галочкой в CLR Exceptions) плагином реализовать функциональность, позволяющую внести изменения в список этих исключений ? Сценарий такой — я хочу продебажить приложение и поостанавливаться на местах, где выбрасываются исключения. Отмечаю галочкой всю группу CLR Exceptions, и запускаю. Естественно, перед тем как я доберусь до необходимого мне места, студия будет постоянно останавливаться на first chance exceptions, которые я хотел бы быстро добавлять в игнор лист, без открытия модального диалогового окна Exceptions и ручного проставления галочки. Хочется кнопку "Ignore this exception type". Ну и если получится такое сделать, то можно развить идею в сторону загрузки наборов настроек и адвансед условий на игнор исключения.
Набросал скриптик для студии, позволяющий это делать. Минус — почему-то студия бажит, и инфа по обновленным настройкам не подцепляется сразу, ввиду чего повторные исключения в том же запуске не будут проигнорированы. Простой workaround : если подряд несколько раз исключения повторяются, жмем Ctrl + A + E и нажимаем Ок. И дебагер подхватывает измененные настройки.
Public Module Module1
Sub BreakWhenThrown(Optional ByVal strException As String = "")
Dim dbg As Debugger3 = DTE.Debugger
Dim eg As ExceptionSettings = _
dbg.ExceptionGroups.Item("Common Language Runtime Exceptions")
eg.SetBreakWhenThrown(True, eg.Item(strException))
End Sub
Sub IgnoreWhenThrown()
Dim commandWin As EnvDTE.CommandWindow
commandWin = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindCommandWindow).Object
commandWin.OutputString(Environment.NewLine)
commandWin.OutputString("Trying to get the information about current exception.." + Environment.NewLine)
Dim dbg As Debugger3 = DTE.Debugger
Dim currentExpression As Expression = dbg.GetExpression("$exception", False)
Try
Dim currentExceptionTypeString As String = currentExpression.DataMembers.Item(1).Type
commandWin.OutputString("Detected current exception type is : " + currentExceptionTypeString + Environment.NewLine)
Dim flag As Boolean = True
Dim eg As ExceptionSettings = dbg.ExceptionGroups.Item("Common Language Runtime Exceptions")
Try
eg.SetBreakWhenThrown(False, eg.Item(currentExceptionTypeString))
Catch exc As Exception
commandWin.OutputString("Cannot find this exception, trying to create.." + currentExceptionTypeString + Environment.NewLine)
eg.NewException(currentExceptionTypeString, New Random().Next)
eg.SetBreakWhenThrown(False, eg.Item(currentExceptionTypeString))
eg.SetBreakWhenUserUnhandled(True, eg.Item(currentExceptionTypeString))
flag = False
End Try
commandWin.OutputString(Environment.NewLine)
commandWin.OutputString("Exception '" + currentExceptionTypeString + "' added to ignore list.")
commandWin.OutputString(Environment.NewLine)
Catch exc As Exception
commandWin.OutputString("Exception occured")
End Try
End Sub
End Module
Вызывается из Command Window командой
> Macros.MyMacros.Module1.IgnoreWhenThrown
(при последующих вызовах можно просто жать кнопку вверх).
Да, это бага студии, проявляется и в 2008, и в 2010. Для того, чтобы настройки подцеплялись — дописал программный вызов диалогового окна "Exceptions" и нажатие сразу там кнопки Ok.
Идиотизм конечно, но что делать. Зато работает, хоть и медленно из-за тормозной студии.
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports EnvDTE90a
Imports EnvDTE100
Imports System.Diagnostics
Imports Microsoft.VisualBasic
Imports Microsoft.VisualBasic.ControlChars
' execute Macros.MyMacros.VSDebuggerExceptions.IgnoreCurrentExceptionWhenThrown from VS Command Window
Public Module VSDebuggerExceptions
Sub BreakWhenThrown(Optional ByVal strException As String = "")
Dim dbg As Debugger3 = DTE.Debugger
Dim eg As ExceptionSettings = _
dbg.ExceptionGroups.Item("Common Language Runtime Exceptions")
eg.SetBreakWhenThrown(True, eg.Item(strException))
End Sub
' copied from Utilities module (samples)
Function GetOutputWindowPane(ByVal Name As String, Optional ByVal show As Boolean = True) As OutputWindowPane
Dim window As Window
Dim outputWindow As OutputWindow
Dim outputWindowPane As OutputWindowPane
window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput)
If show Then window.Visible = True
outputWindow = window.Object
Try
outputWindowPane = outputWindow.OutputWindowPanes.Item(Name)
Catch e As System.Exception
outputWindowPane = outputWindow.OutputWindowPanes.Add(Name)
End Try
outputWindowPane.Activate()
Return outputWindowPane
End Function
Private WithEvents t As Timers.Timer
' Adds the current exception to ignore list
Sub IgnoreCurrentExceptionWhenThrown()
Dim commandWin As EnvDTE.CommandWindow
commandWin = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindCommandWindow).Object
Select Case DTE.Debugger.CurrentMode
Case dbgDebugMode.dbgDesignMode
commandWin.OutputString("This macro is not enabled in Design Mode. Run it in Break Mode." + vbCrLf)
Return
Case dbgDebugMode.dbgRunMode
commandWin.OutputString("This macro is not enabled in Run Mode. Run it in Break Mode." + vbCrLf)
Return
End Select
commandWin.OutputString(Environment.NewLine)
commandWin.OutputString("Trying to get the information about current exception.." + Environment.NewLine)
Dim dbg As Debugger3 = DTE.Debugger
Dim currentExpression As Expression = dbg.GetExpression("$exception", False)
Try
'dump of currentExpression.DataMembers
'Dim count As Integer = currentExpression.DataMembers.Count
'For i As Integer = 1 To count
' commandWin.OutputString("$exception.DataMembers[" + i.ToString + "].Type = " + currentExpression.DataMembers.Item(i).Type)
' commandWin.OutputString(Environment.NewLine)
'Next
'commandWin.OutputString("Taking first data member to identify current exception.." + Environment.NewLine)
Dim currentExceptionTypeString As String = currentExpression.DataMembers.Item(1).Type
commandWin.OutputString("Detected current exception type is : " + currentExceptionTypeString + Environment.NewLine)
Dim flag As Boolean = True
Dim eg As ExceptionSettings = dbg.ExceptionGroups.Item("Common Language Runtime Exceptions")
Try
eg.SetBreakWhenThrown(False, eg.Item(currentExceptionTypeString))
Catch exc As Exception
commandWin.OutputString("Cannot find this exception, trying to create.." + currentExceptionTypeString + Environment.NewLine)
'
eg.NewException(currentExceptionTypeString, New Random().Next)
eg.SetBreakWhenThrown(False, eg.Item(currentExceptionTypeString))
eg.SetBreakWhenUserUnhandled(True, eg.Item(currentExceptionTypeString))
flag = False
End Try
commandWin.OutputString(Environment.NewLine)
commandWin.OutputString("Exception '" + currentExceptionTypeString + "' added to ignore list.")
commandWin.OutputString(Environment.NewLine)
t = New Timers.Timer()
' small interval to send keys after DTE will start to exec command
t.Interval = 0.1
t.Start()
DTE.ExecuteCommand("Debug.Exceptions")
Catch exc As Exception
commandWin.OutputString("Error occured")
End Try
End Sub
Private Sub t_Elapsed(ByVal ee As Object, ByVal dd As Timers.ElapsedEventArgs) Handles t.Elapsed
t.Stop()
' only press Ok to apply changed exceptions settings to debugger
System.Windows.Forms.SendKeys.SendWait("%t")
System.Windows.Forms.SendKeys.SendWait("{ENTER}")
End Sub
End Module