locked
Update OutputWindow UI RRS feed

  • Question

  • My extension reads the Output Window content using the next code.

    TextSelection selection = outputWindow.TextDocument.Selection;
    selection.StartOfDocument(false);
    selection.EndOfDocument(true);
    string output = selection.Text;

    Is there anyway to make sure that output window content is fully updated? I've tried System.Windows.Forms.Application.DoEvents() before reading the content - no help.

    Wednesday, September 19, 2012 9:50 PM

Answers

  • What do you mean by the "old" content? Are you sure the content isn't being added by the debugger after your code runs? 

    The output window essentially works like this:

    IVsOutputWindowPane has an OutputString method.  People call that method to add strings to the output window. The output window has an internal buffer of strings that have been added that it flushes either when the buffer fills up or when a timer fires. When it 'flushes the buffer' it gets the editor associated with the pane and simply adds the strings to its underlying buffer. This is what causes them to appear on the screen.

    Interacting with the editor via DTE (which is what you were doing above) is only going to expose things that have been added to the editor's buffer, which is only things that have been pushed out of the output window's internal buffer. Calling FlushToTaskList definetely pushes any items in the internal buffer to the underlying editor buffer.

    That said it is possible the DTE object is capturing a version of the editor buffer which was snapshotted prior to the flush.  What is the ordering in your code of fetching the DTE TextDocument object (or SelectionObject) and the call to FlushToTaskList?

    Ryan

    • Marked as answer by EliMLi Thursday, September 20, 2012 3:30 PM
    Thursday, September 20, 2012 12:40 AM

All replies

  • >I've tried System.Windows.Forms.Application.DoEvents() before reading the content - no help.

    DoEvents is basically never the answer, unless the question is 'how do I introduce unexpected re-entrancy and massively increase the likelihood of crashing or encountering other bugs?'

    The output window buffers strings in an internal buffer to avoid huge amounts of re-painting when strings are coming fast and heavy (say during builds or debugging). You can force flush the buffer in an unintuitive way (i.e. it wasn't designed as a way to flush the buffer, but it has that effect) by calling IVsOutputWindowPane::FlushToTaskList.

    That said, why are you reading the text out of the output window? It seems like a very brittle approach to just about any problem I could imagine. I suspect there is a better way to get the info you are looking for.

    Ryan

    Wednesday, September 19, 2012 10:45 PM
  • I'm developing a debugger extension that reads output window content immediately after entering the break mode. I noticed that quite often the extension captures "old" window content. 

    Is there any other way to read the output window content?

    Wednesday, September 19, 2012 11:14 PM
  • Well there is no way that wouldn't be affected by the buffering, my point is that it isn't clear what your extension does with the data. If it is parsing the text to try and make some decision or discover something you are very susceptible to your extension breaking because someone changes the output text ever so slightly. Text output is not an API so there is no 'backwards compat' argument about it never changing format, and it can/does change from release to release.

    What excatly are you doing with the output window contents?  And by 'output window' I suspect you actually mean specifically the Debug output window pane (since there are more than a single pane in the output window, each with their own contents).

    Ryan

    Wednesday, September 19, 2012 11:43 PM
  • Correct, I'm trying to capture Debug pane. My extension when entering break state checks the output producing by debuggee application and doers something according to the output.
    Wednesday, September 19, 2012 11:51 PM
  • It seems FlushToTaskList doesn't really help. I'm using the next code and still getting the "old" content of the output window.

    IVsOutputWindow outputWindow = Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(SVsOutputWindow)) as IVsOutputWindow;
    IVsOutputWindowPane windowPane = null;
    outputWindow.GetPane(Microsoft.VisualStudio.VSConstants.GUID_OutWindowDebugPane, out windowPane);
    windowPane.FlushToTaskList();

    Thursday, September 20, 2012 12:09 AM
  • What do you mean by the "old" content? Are you sure the content isn't being added by the debugger after your code runs? 

    The output window essentially works like this:

    IVsOutputWindowPane has an OutputString method.  People call that method to add strings to the output window. The output window has an internal buffer of strings that have been added that it flushes either when the buffer fills up or when a timer fires. When it 'flushes the buffer' it gets the editor associated with the pane and simply adds the strings to its underlying buffer. This is what causes them to appear on the screen.

    Interacting with the editor via DTE (which is what you were doing above) is only going to expose things that have been added to the editor's buffer, which is only things that have been pushed out of the output window's internal buffer. Calling FlushToTaskList definetely pushes any items in the internal buffer to the underlying editor buffer.

    That said it is possible the DTE object is capturing a version of the editor buffer which was snapshotted prior to the flush.  What is the ordering in your code of fetching the DTE TextDocument object (or SelectionObject) and the call to FlushToTaskList?

    Ryan

    • Marked as answer by EliMLi Thursday, September 20, 2012 3:30 PM
    Thursday, September 20, 2012 12:40 AM