【问题标题】:Visual Studio - inserting multi-line expressions into Watch Window while debuggingVisual Studio - 在调试时将多行表达式插入监视窗口
【发布时间】:2016-07-12 19:35:46
【问题描述】:

在 Visual Studio 中调试时,如何在 Watch Window 中插入多行表达式,以使每一行都不会分解为单独的 INVALID 观察表达式。这真的很令人沮丧,因为我需要查看许多跨越多行的表达式。请注意,Pin to Source 和 Immediate Window 都不适用于跟踪源代码中多个位置的多个值。

例如

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

被破坏到:

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

Py.kw("var2", var2))

【问题讨论】:

  • 在将表达式粘贴到监视窗口之前,是否有不能删除换行符的原因?
  • 尝试粘贴到即时窗口中。它往往更适合较长的表达式。
  • 看看 OzCode 的 Magic Glance 功能 - 即使没有 Watch 或 Immediate 窗口,它也可以显示表达式的结果
  • 奇怪的是,快速观看命令工作正常。
  • @denfromufa 我很乐意这样做,但不幸的是,尽管快速观察正确显示了列表中的表达式和值,但表达式组合仅显示第一行,更重要的是,两者都没有添加监视按钮或列表项上下文菜单有效 - 它们在监视窗口中产生相同的多错误行。一致性:(

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


【解决方案1】:

复制

我不认为这是“按设计”,它只是“开箱即用”不可用。

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


研究

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

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

恐怕不支持,我们经常一一编辑。也许你可以提交这个功能请求:http://visualstudio.uservoice.com/forums/121579-visual-studio


推出您自己的 Visual Studio 插件

所以我自己尝试了一下,这绝不是生产代码,但它向您展示了如何做到这一点:

(点击图片放大)

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 类 - 请参阅我的 //UPPERCASE cmets 以及要添加的内容。

  4. TextSelection selection = (TextSelection)_applicationObject.ActiveDocument.Selection;这一行打断点

  5. 按 F5,将启动一个新的 VS 实例 > 选择 New Project > Console App > 将其命名为 TestMultilineAddWatch

  6. 在Console App的program.cs中,指定2行以上的代码调用,并在其上打断点,如截图所示,eg:

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

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

调用自身的 Visual Studio EXEC 命令使此方法递归,如果您对其进行调试,手动退出递归,您将看到按照我的屏幕截图的结果。

调试愉快!

【讨论】:

    【解决方案2】:

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

    !+v 表示 Alt+Shift+v

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

    我在 Visual Studio 的文本文档中进行了剪切和粘贴测试。

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

    【讨论】:

      猜你喜欢
      • 2018-10-04
      • 1970-01-01
      • 1970-01-01
      • 2016-05-21
      • 1970-01-01
      • 1970-01-01
      • 2012-10-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多