Visual Studio-调试时将多行表达式插入监视窗口 [英] Visual Studio - inserting multi-line expressions into Watch Window while debugging

查看:99
本文介绍了Visual Studio-调试时将多行表达式插入监视窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Visual Studio中调试时,如何将多行表达式插入监视窗口,以使每一行都不会分解为单独的INVALID监视表达式。这真令人沮丧,因为我有很多需要跨越多行的表达式。请注意,固定到源代码窗口和立即窗口都不能用于跟踪源代码中许多位置的多个值。



例如

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

被破坏为:

  PyFunc1(Py.kw( var1,var1),

  Py.kw( var2,var2))


解决方案

Repro



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



我同意,将多行呼叫添加到使用行终止符而不是换行符的监视窗口:





< hr>

研究



我发现了类似的问题,但有一些解决方法可供选择:

 命名空间AddinMultiLineWatch 
{
public class Connect:IDTExtensibility2,IDTCommandTarget
{
//添加这些成员变量
//私有DebuggerEvents _debuggerEvents = null;
//私有_dispDebuggerEvents_OnEnterBreakModeEventHandler DebuggerEvents_OnEnterBreakMode;
private Window _watchWindow = null;
private CommandEvents _objCommandEvents;
private bool _isRecursive = false;
public Connect()
{
}

public void OnConnection(对象应用程序,ext_ConnectMode connectMode,对象addInInst,引用数组自定义)
{
_applicationObject =(DTE2)应用程序;
_addInInstance =(AddIn)addInInst;

//设置成员变量
// _ debuggerEvents = _applicationObject.Events.DebuggerEvents;
//_debuggerEvents.OnEnterBreakMode + =新的_dispDebuggerEvents_OnEnterBreakModeEventHandler(BreakHandler);
// var watchWindow = _applicationObject.Windows.Item(EnvDTE.Constants.vsWindowKindWatch);
_objCommandEvents = _applicationObject.Events.CommandEvents;
_objCommandEvents.BeforeExecute + =新的_dispCommandEvents_BeforeExecuteEventHandler(BeforeExecute);

if(connectMode == ext_ConnectMode.ext_cm_UISetup)
{
object [] contextGUIDS = new object [] {};
Commands2命令=(Commands2)_applicationObject.Commands;
string toolsMenuName =工具;

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

试试
{
Command command =命令。AddNamedCommand2(_addInInstance, AddinMultiLineWatch, AddinMultiLineWatch,为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)
{
}
}
}

//添加此方法以拦截DEBUG.ADDWATCH命令
public void BeforeExecute(字符串Guid,int ID,对象CustomIn,对象CustomOut,ref bool CancelDefault)
{
EnvDTE.Command objCommand = default( EnvDTE.Command);
try
{
objCommand = _applicationObject.Commands.Item(Guid,ID);
}
捕获(异常例外)
{
}

if(((objCommand!= null))
{
if(objCommand.Name == Debug.AddWatch)
{
//如果(_isRecursive)返回;
// _ isRecursive = true;
TextSelection selection =(TextSelection)_applicationObject.ActiveDocument.Selection;
// TODO将选择转到下一个分号/行终止符...
var selText = selection.Text;

if(string.IsNullOrEmpty(selText))返回;
//仅拦截多行添加监视命令
if(selText.Contains(Environment.NewLine))
{
//黑魔法:使其适合一行!大声笑
selText = selText.Replace(Environment.NewLine,string.Empty);
//此调用是紧急的,我将其留给读者作为练习来解决。.
_applicationObject.ExecuteCommand( Debug.AddWatch,selText);
}
}
}
}




  1. 创建一个新项目>其他项目类型>可扩展性> Visual Studio加载项>将其命名为AddinMultiLineWatch


  2. 向导


  3. 将上面的代码添加到Connect.cs类中-看到我的// UPPERCASE注释以及要添加的内容。


  4. 在行上设置一个断点 TextSelection selection =(TextSelection)_applicationObject.ActiveDocument.Selection;


  5. 按F5键,VS的新实例将启动>选择新建项目>控制台应用程序>将其命名为TestMultilineAddWatch


  6. In控制台应用程序的program.cs,在两行中指定一个代码调用,并在其上放置一个断点,如屏幕截图所示,例如:

      Add(1,//在此处断点并选择两行
    2);
    }

    static int Add(int i,int j)
    {
    return i + j;
    }


  7. F5在TestMultilineAddWatch解决方案中以及代码控件何时停止断点>选择/突出显示两行 Add(1,\r\n 2)>右键单击>添加监视


  8. 在VS IDE调试上下文菜单中单击添加监视,将使VS AddinMultiLineWatch解决方案拦截呼叫并激活,并在断点处暂停...。 将多行代码替换为一行的的黑魔法


Visual Studio EXEC命令本身调用该方法将使该方法具有递归性,如果您对其进行调试,则手动退出该递归操作,您将按照我的屏幕快照看到结果。



调试愉快!


While debugging in Visual Studio, how can I insert multi-line expressions into Watch Window, so that each line is not broken into a separate INVALID watch expression. This is really frustrating because I have many expressions spanning multiple lines that I need to watch. Note that both Pin to Source and Immediate Window do not work for tracking multiple values from many places in source code.

e.g.

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

gets broken to:

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

and

Py.kw("var2", var2))

解决方案

Repro

I dont think this is "By-Design", its just unavailable "out-of-the-box".

I agree, it'd be better behaviour for multi-line calls to be added to the Watch Window using line terminators instead of new lines:


Research

I found this similar question with a few "workarounds" to choose from: Multi-Line Watch Window in Visual Studio 2010?

I also found this comment in the MSDN Forums by a MSFT Engineer:

I’m afraid that it is not supported, we often edit them one by one. Maybe you could submit this feature request: http://visualstudio.uservoice.com/forums/121579-visual-studio


Roll your own Visual Studio Add-In

So I had a go at it myself, this is by no means production code but it shows you how to do it:

(click image to enlarge)

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. Create a New Project > Other Project Types > Extensibility > Visual Studio Add-In > name it AddinMultiLineWatch

  2. Go through the wizard

  3. Add the code above to the Connect.cs class - see my //UPPERCASE comments with what stuff to add.

  4. Put a break point on the line TextSelection selection = (TextSelection)_applicationObject.ActiveDocument.Selection;

  5. Press F5 and a new instance of VS will launch > choose New Project > Console App > name it TestMultilineAddWatch

  6. In the program.cs of the Console App, specify a code call over 2 lines and put a break point on it, as shown in the screenshot, eg:

    Add(1,            //Breakpoint here and select both lines
            2);
    }
    
    static int Add(int i, int j)
    {
        return i + j;
    }
    

  7. F5 in the TestMultilineAddWatch solution and when the code control halts on the break point > select/highlight the two lines Add(1, \r\n 2) > right click > Add Watch

  8. Clicking Add Watch in the VS IDE debugging context menu causes the VS AddinMultiLineWatch solution to intercept the call and activate, halting on the break point.... where you will see the black magic of replacing multi lined code in to a single line sent to the Watch Window.

The Visual Studio EXEC command calling itself makes this method recursive, if you debug it, exiting out of the recursion manually you will see the results as per my screenshot.

Happy debugging!

这篇关于Visual Studio-调试时将多行表达式插入监视窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆