Capturing cout in Visual Studio 2005 output window?
Asked Answered
F

7

17

I created a C++ console app and just want to capture the cout/cerr statements in the Output Window within the Visual Studio 2005 IDE. I'm sure this is just a setting that I'm missing. Can anyone point me in the right direction?

Flashcube answered 16/9, 2008 at 14:59 Comment(0)
C
14

I've finally implemented this, so I want to share it with you:

#include <vector>
#include <iostream>
#include <windows.h>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/tee.hpp>

using namespace std;
namespace io = boost::iostreams;

struct DebugSink
{
    typedef char char_type;
    typedef io::sink_tag category;

    std::vector<char> _vec;

    std::streamsize write(const char *s, std::streamsize n)
    {
        _vec.assign(s, s+n);
        _vec.push_back(0); // we must null-terminate for WINAPI
        OutputDebugStringA(&_vec[0]);
        return n;
    }
};

int main()
{
    typedef io::tee_device<DebugSink, std::streambuf> TeeDevice;
    TeeDevice device(DebugSink(), *cout.rdbuf());
    io::stream_buffer<TeeDevice> buf(device);
    cout.rdbuf(&buf);

    cout << "hello world!\n";
    cout.flush(); // you may need to flush in some circumstances
}

BONUS TIP: If you write:

X:\full\file\name.txt(10) : message

to the output window and then double-click on it, then Visual Studio will jump to the given file, line 10, and display the 'message' in status bar. It's very useful.

Cerf answered 22/5, 2011 at 8:22 Comment(1)
This has been working really well for me, but with VS2013 and Boost 1.57 it crashes with an assertion failure in the Boost code as soon as the stream gets flushed, either by printing a lot or by sending std::endl to the stream, so it's no longer usable :-( Not sure if it's a bug in Boost or what.Declinature
B
8

You can capture the output of cout like this, for example:

std::streambuf* old_rdbuf = std::cout.rdbuf();
std::stringbuf new_rdbuf;
// replace default output buffer with string buffer
std::cout.rdbuf(&new_rdbuf);

// write to new buffer, make sure to flush at the end
std::cout << "hello, world" << std::endl;

std::string s(new_rdbuf.str());
// restore the default buffer before destroying the new one
std::cout.rdbuf(old_rdbuf);

// show that the data actually went somewhere
std::cout << s.size() << ": " << s;

Magicking it into the Visual Studio 2005 output window is left as an exercise to a Visual Studio 2005 plugin developer. But you could probably redirect it elsewhere, like a file or a custom window, perhaps by writing a custom streambuf class (see also boost.iostream).

Burgh answered 16/9, 2008 at 16:59 Comment(1)
No plugin needed, just use OutputDebugString as mentioned by Mike Dimmick.Proportioned
L
6

You can't do this.

If you want to output to the debugger's output window, call OutputDebugString.

I found this implementation of a 'teestream' which allows one output to go to multiple streams. You could implement a stream that sends data to OutputDebugString.

Lipkin answered 16/9, 2008 at 15:7 Comment(0)
M
2

A combination of ben's answer and Mike Dimmick's: you would be implementing a stream_buf_ that ends up calling OutputDebugString. Maybe someone has done this already? Take a look at the two proposed Boost logging libraries.

Metamorphism answered 17/9, 2008 at 0:39 Comment(0)
R
1

Is this a case of the output screen just flashing and then dissapearing? if so you can keep it open by using cin as your last statement before return.

Rosenberg answered 16/9, 2008 at 15:7 Comment(1)
No you cannot because evaluating cin on its own has no effect.Burgh
A
0

Also, depending on your intentions, and what libraries you are using, you may want to use the TRACE macro (MFC) or ATLTRACE (ATL).

Alicealicea answered 17/9, 2008 at 7:24 Comment(0)
S
0

Write to a std::ostringsteam and then TRACE that.

std::ostringstream oss;

oss << "w:=" << w << " u=" << u << " vt=" << vt << endl;

TRACE(oss.str().data());
Stan answered 20/8, 2019 at 12:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.