Visual Studio - 在调试时将多行表达式插入Watch Window

时间:2016-07-12 19:35:47

标签: c# .net visual-studio debugging visual-studio-2015

在Visual Studio中进行调试时,如何在监视窗口中插入多行表达式,以便每行不会分成单独的INVALID监视表达式。这真是令人沮丧,因为我有很多表达式需要观察多行。请注意,Pin to Source和Immediate Window都不能用于跟踪源代码中许多位置的多个值。

e.g。

PyFunc1(Py.kw("var1", var1),
        Py.kw("var2", var2))

被打破:

PyFunc1(Py.kw("var1", var1),

Py.kw("var2", var2))

2 个答案:

答案 0 :(得分:6)

摄制

我不认为这是“By-Design”,它只是不可用的“开箱即用”。

我同意,使用行终止符而不是新行将多行调用添加到监视窗口是更好的行为:

enter image description here

研究

我发现这个类似的问题有一些“解决方法”可供选择: Multi-Line Watch Window in Visual Studio 2010?

我也在MSDN Forums by a MSFT Engineer中找到了这条评论:

  

我担心它不受支持,我们经常逐个编辑它们。也许您可以提交此功能请求:http://visualstudio.uservoice.com/forums/121579-visual-studio

滚动您自己的Visual Studio加载项

所以我自己动手了,这绝不是生产代码,但它会告诉你如何做到这一点:

(点击图片放大)

enter image description here

namespace AddinMultiLineWatch
{
public class Connect : IDTExtensibility2, IDTCommandTarget
{
    //ADD THESE MEMBER VARIABLES
    //private DebuggerEvents _debuggerEvents = null;
    //private _dispDebuggerEvents_OnEnterBreakModeEventHandler DebuggerEvents_OnEnterBreakMode;
    private Window _watchWindow = null;
    private CommandEvents _objCommandEvents;
    private bool _isRecursive = false;
    public Connect()
    {
    }

    public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
    {
        _applicationObject = (DTE2)application;
        _addInInstance = (AddIn)addInInst;

        //SET THE MEMBER VARIABLES
        //_debuggerEvents = _applicationObject.Events.DebuggerEvents;
        //_debuggerEvents.OnEnterBreakMode += new _dispDebuggerEvents_OnEnterBreakModeEventHandler(BreakHandler);
        //var watchWindow = _applicationObject.Windows.Item(EnvDTE.Constants.vsWindowKindWatch);
        _objCommandEvents = _applicationObject.Events.CommandEvents;
        _objCommandEvents.BeforeExecute += new _dispCommandEvents_BeforeExecuteEventHandler(BeforeExecute);

        if(connectMode == ext_ConnectMode.ext_cm_UISetup)
        {
            object []contextGUIDS = new object[] { };
            Commands2 commands = (Commands2)_applicationObject.Commands;
            string toolsMenuName = "Tools";

            Microsoft.VisualStudio.CommandBars.CommandBar menuBarCommandBar = ((Microsoft.VisualStudio.CommandBars.CommandBars)_applicationObject.CommandBars)["MenuBar"];
ar:
            CommandBarControl toolsControl = menuBarCommandBar.Controls[toolsMenuName];
            CommandBarPopup toolsPopup = (CommandBarPopup)toolsControl;

            try
            {
                Command command = commands.AddNamedCommand2(_addInInstance, "AddinMultiLineWatch", "AddinMultiLineWatch", "Executes the command for AddinMultiLineWatch", true, 59, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported+(int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton);

                if((command != null) && (toolsPopup != null))
                {
                    command.AddControl(toolsPopup.CommandBar, 1);
                }
            }
            catch(System.ArgumentException)
            {
            }
        }
    }

    //ADD THIS METHOD TO INTERCEPT THE DEBUG.ADDWATCH COMMAND
    public void BeforeExecute(string Guid, int ID, object CustomIn, object CustomOut, ref bool CancelDefault)
    {
        EnvDTE.Command objCommand = default(EnvDTE.Command);
        try
        {
            objCommand = _applicationObject.Commands.Item(Guid, ID);
        }
        catch (Exception ex)
        {
        }

        if ((objCommand != null))
        {
            if (objCommand.Name == "Debug.AddWatch")
            {
                //if (_isRecursive) return;
                //_isRecursive = true;
                TextSelection selection = (TextSelection)_applicationObject.ActiveDocument.Selection;
                //TODO make selection goto next semi-colon/Line Terminator...
                var selText = selection.Text;  

                if (string.IsNullOrEmpty(selText)) return;   
                //Only intercept multi-line Add Watch commands                    
                if (selText.Contains(Environment.NewLine))
                {
                  //THE BLACK MAGIC: make it fit in one line! lol
                  selText = selText.Replace(Environment.NewLine, string.Empty);              
                  //THIS CALL IS RECURSIVE, I'LL LEAVE IT TO THE READER AS AN EXERCISE TO SOLVE..
                _applicationObject.ExecuteCommand("Debug.AddWatch", selText);
               }
            }
        }
    }
  1. 创建新项目>其他项目类型>可扩展性> Visual Studio加载项>将其命名为AddinMultiLineWatch

  2. 完成向导

  3. 将上面的代码添加到Connect.cs类 - 请参阅我的//大写评论以及要添加的内容。

  4. TextSelection selection = (TextSelection)_applicationObject.ActiveDocument.Selection;

  5. 行上设置一个断点
  6. 按F5,VS的新实例将启动>选择新项目>控制台应用>将其命名为TestMultilineAddWatch

  7. 在Console App的program.cs中,指定2行代码调用并在其上放置断点,如屏幕截图所示,例如:

    Add(1,            //Breakpoint here and select both lines
            2);
    }
    
    static int Add(int i, int j)
    {
        return i + j;
    }
    
  8. TestMultilineAddWatch解决方案中的F5,当代码控制在断点处停止时>选择/突出显示两行Add(1, \r\n 2)>右键单击>添加观察

  9. 在VS IDE调试上下文菜单中单击添加监视会导致VS AddinMultiLineWatch解决方案拦截呼叫并激活,暂停中断点...您将看到 的黑魔法将多行代码替换为发送到监视窗口的单行

  10. Visual Studio EXEC命令调用本身使这个方法递归,如果你调试它,手动退出递归,你会看到我的截图结果。

    快乐的调试!

答案 1 :(得分:3)

您可以使用autohotkey和自定义键绑定(例如Alt + Shift + V)

来完成此操作

!+ v表示Alt + Shift + v

下面的宏: 如果在devenv.exe中,按Alt + Shift + V,编辑剪贴板内容,删除/ r / n并替换为空,然后按Ctrl + V粘贴

我在视觉工作室的文本文档中对此进行了剪切和粘贴测试。

#IfWinActive ahk_exe devenv.exe
!+v::
FixString = %clipboard%
StringReplace, FixString, FixString,`r`n,,A
Clipboard := FixString
Send, ^v