Comment rediriger stdout vers la fenêtre de sortie de visual studio

est-il possible de rediriger stdout vers la fenêtre de sortie de Visual Studio? J'utilise dans mon programme OutputDebugString mais j'utilise certaines bibliothèques qui ont des messages de débogage de sortie avec des printf ou des cuts.

19
demandé sur Felics 2011-03-09 19:18:44

4 réponses

la simple redirection stdout ne fonctionnera pas, car il n'y a pas de poignée correspondant à OutputDebugString. Cependant, il devrait y avoir une façon:

cela pourrait être fait en redirigeant le stdout vers un tuyau, puis en créant un fil qui lirait le tuyau et imprimerait tout ce qui en serait lu en utilisant OutputDebugString.

Note: j'envisageais depuis longtemps de mettre en œuvre ceci, car je suis confronté exactement au même problème que vous (certaines bibliothèques utilisant printf ou printf). fprintf(stderr....), cependant je n'ai jamais vraiment fait cela, j'ai toujours fini par Modifier les bibliothèques à la place, donc je n'ai pas d'implémentation opérationnelle, mais je pense que cela devrait être faisable en principe.

4
répondu Suma 2011-03-09 20:24:45
https://web.archive.org/web/20140825203329/http://blog.tomaka17.com/2011/07/redirecting-cerr-and-clog-to-outputdebugstring/:

#include <ostream>
#include <Windows.h>

/// \brief This class is a derivate of basic_stringbuf which will output all the written data using the OutputDebugString function
template<typename TChar, typename TTraits = std::char_traits<TChar>>
class OutputDebugStringBuf : public std::basic_stringbuf<TChar,TTraits> {
public:
    explicit OutputDebugStringBuf() : _buffer(256) {
        setg(nullptr, nullptr, nullptr);
        setp(_buffer.data(), _buffer.data(), _buffer.data() + _buffer.size());
    }

    ~OutputDebugStringBuf() {
    }

    static_assert(std::is_same<TChar,char>::value || std::is_same<TChar,wchar_t>::value, "OutputDebugStringBuf only supports char and wchar_t types");

    int sync() try {
        MessageOutputer<TChar,TTraits>()(pbase(), pptr());
        setp(_buffer.data(), _buffer.data(), _buffer.data() + _buffer.size());
        return 0;
    } catch(...) {
        return -1;
    }

    int_type overflow(int_type c = TTraits::eof()) {
        auto syncRet = sync();
        if (c != TTraits::eof()) {
            _buffer[0] = c;
            setp(_buffer.data(), _buffer.data() + 1, _buffer.data() + _buffer.size());
        }
        return syncRet == -1 ? TTraits::eof() : 0;
    }


private:
    std::vector<TChar>      _buffer;

    template<typename TChar, typename TTraits>
    struct MessageOutputer;

    template<>
    struct MessageOutputer<char,std::char_traits<char>> {
        template<typename TIterator>
        void operator()(TIterator begin, TIterator end) const {
            std::string s(begin, end);
            OutputDebugStringA(s.c_str());
        }
    };

    template<>
    struct MessageOutputer<wchar_t,std::char_traits<wchar_t>> {
        template<typename TIterator>
        void operator()(TIterator begin, TIterator end) const {
            std::wstring s(begin, end);
            OutputDebugStringW(s.c_str());
        }
    };
};

Puis:

int main() {
    #ifndef NDEBUG
        #ifdef _WIN32
            static OutputDebugStringBuf<char> charDebugOutput;
            std::cerr.rdbuf(&charDebugOutput);
            std::clog.rdbuf(&charDebugOutput);

            static OutputDebugStringBuf<wchar_t> wcharDebugOutput;
            std::wcerr.rdbuf(&wcharDebugOutput);
            std::wclog.rdbuf(&wcharDebugOutput);
        #endif
    #endif

    ...

    std::cerr << "Error: something bad happened" << std::endl;      // will be displayed in the debugger

    ...
}

Vous pouvez utiliser avec

IsDebuggerPresent ()

de sorte qu'il continue à sortir vers la console lorsqu'il n'est pas exécuté à partir du débogueur Visual Studio.

10
répondu Ozirus 2016-11-16 14:14:43

Oui. Je suppose que vous travaillez sur une application Win32 GUI.

votre implémentation C définit 3 poignées pour stdin, stdout et stderr. Win32 définit des poignées équivalentes, qui définissent où l'entrée/sortie physique réelle apparaîtra. c fonctions telles que "printf", utilisez ces poignées Win32 pour effectuer des entrées / sorties. Fondamentalement, ce que vous devez faire est de créer une console pour la sortie, puis rediriger où les points Win32 stdout. et ensuite gettign la poignée à la c stdout et associer cela avec le Win32 stdout.

Ce lien contient plus d'informations sur comment faire ceci:

Vous aurez besoin d'ajouter deux nouveaux fichiers à votre demande (le lien contient les listes ).

3
répondu BeeBand 2011-03-09 17:35:13

J'utilise Visual Studio 2012 et je voulais aussi rediriger stdout et stderr lors du débogage d'un Script, d'un programme C++ ou D'une DLL MSTest sans avoir à changer le code source lui-même. Mon approche que j'ai finalement trouvé était de capturer la sortie en utilisant une sorte de programme intermédiaire.

Créer Un Windows En C# Console Application

prenez le code C# suivant et créez / compilez une Console Windows C# .NET Application:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;

namespace OutputDebugStringConsole
{
    class OutputDebugStringConsole
    {
        private static void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
        {
            if (null != outLine.Data)
            {
                Trace.WriteLine(outLine.Data);
                Trace.Flush();
                Console.WriteLine(outLine.Data);
            }
        }

        static void Main(string[] args)
        {
            if (args.Length == 0)
            {
                return;
            }

            try
            {
                Process p = new Process();

                p.StartInfo.FileName = args[0];
                p.StartInfo.Arguments = String.Join(" ", args, 1, args.Length - 1);
                Trace.WriteLine("Calling " + p.StartInfo.FileName + " " + p.StartInfo.Arguments);
                p.StartInfo.WorkingDirectory = Directory.GetCurrentDirectory();
                p.StartInfo.CreateNoWindow = true;
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.RedirectStandardOutput = true;
                p.StartInfo.RedirectStandardError = true;
                p.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
                p.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler);
                p.Start();
                p.BeginOutputReadLine();
                p.BeginErrorReadLine();
                p.WaitForExit();
                // Call WaitForExit() AFTER I know the process has already exited by a successful return from WaitForExit(timeout).
                // This causes the code that reads all remaining pending async data to be executed.
                // see https://groups.google.com/d/msg/microsoft.public.dotnet.framework.sdk/jEen9Hin9hY/FQtEhjdKLmoJ
                Thread.Sleep(100);
                p.WaitForExit();
                p.Close();
            }
            catch (Exception e)
            {
                Trace.WriteLine(e.ToString());
                Console.WriteLine("{0} Exception caught.", e);
            }
        }
    }
}

J'ai utilisé Trace.WriteLine () au lieu de Debug.WriteLine () parce que cela fonctionne aussi dans la version release du code ci-dessus.

utiliser L'Application dans le Debugging VS Project

NOTE: si vous avez choisi .NET 4/4.5 et vous capturez la sortie de code non géré, vous devez sélectionner Mixte comme votre débogueur/débogueur taper dans les paramètres de votre projet. Dans le cas contraire (avec Auto), vous pouvez obtenir un base D'amande non pressée.dll exception.

Maintenant vous pouvez utiliser l'application en mettant le nouveau

OutputDebugStringConsole.exe

dans les propriétés de débogage/commande et

" $(TargetPath)" [ARGS ...]

ou, par exemple, s'il est MSTest DLL

"$(DevEnvDir)CommonExtensions\Microsoft\TestWindow\vstest.console.EXE" / Plate-forme:x86 $(TargetPath)

dans votre Débogage/Arguments de l'application que vous souhaitez déboguer. Les guillemets dans les arguments de commande sont nécessaires pour gérer les espaces dans le chemin de votre application.

s'il vous Plaît prendre cela comme un exemple de ce que l'application peut être utilisée pour. Je suis conscient que L'Explorateur de test VS 2012 offre une très belle façon d'exécuter MSTest DLLs et d'obtenir la sortie d'une manière structurée.

0
répondu Florian 2017-05-23 12:33:32