web-dev-qa-db-fra.com

Comment imprimer sur la fenêtre de sortie de débogage dans une application Win32?

J'ai un projet win32 que j'ai chargé dans Visual Studio 2005. J'aimerais pouvoir imprimer des éléments dans la fenêtre de sortie de Visual Studio, mais je ne peux pas, pour la vie, déterminer comment. J'ai essayé 'printf' et 'cout <<' mais mes messages restent obstinément non imprimés.

Existe-t-il un moyen spécial d’imprimer dans la fenêtre de sortie de Visual Studio?

85
izb

Vous pouvez utiliser OutputDebugString . OutputDebugString est une macro qui, en fonction de vos options de construction, est mappée sur OutputDebugStringA(char const*) ou OutputDebugStringW(wchar_t const*). Dans ce dernier cas, vous devrez fournir une chaîne de caractères large à la fonction. Pour créer un littéral de caractère large, vous pouvez utiliser le préfixe L:

OutputDebugStringW(L"My output string.");

Normalement, vous utiliserez la version macro avec le _T macro comme ceci:

OutputDebugString(_T("My output string."));

Si votre projet est configuré pour générer pour UNICODE, il sera développé comme suit:

OutputDebugStringW(L"My output string.");

Si vous ne construisez pas pour UNICODE, cela s'étendra à:

OutputDebugStringA("My output string.");
127
Martin Liversage

Si le projet est un projet graphique, aucune console n'apparaîtra. Pour changer le projet en console, vous devez aller dans le panneau des propriétés du projet et définir:

  • Dans "éditeur de liens-> Système-> Sous-système" la valeur "Console (/ SUBSYSTEM: CONSOLE)"
  • Dans "C/C++ -> Préprocesseur> Définitions du préprocesseur", ajoutez le "_ CONSOLE"

Cette solution ne fonctionne que si vous avez le point d’entrée classique "int main ()".

Mais si vous êtes comme dans mon cas (un projet openGL), vous n'avez pas besoin de modifier les propriétés, car cela fonctionne mieux:

AllocConsole();
freopen("CONIN$", "r",stdin);
freopen("CONOUT$", "w",stdout);
freopen("CONOUT$", "w",stderr);

printf et cout fonctionneront normalement.

Si vous appelez AllocConsole avant la création d'une fenêtre, la console apparaît derrière la fenêtre. Si vous l'appelez après, elle apparaîtra avant.

27
Zac

Pour imprimer sur la console real, vous devez la rendre visible à l’aide du drapeau de l’éditeur de liens /SUBSYSTEM:CONSOLE. La fenêtre de la console supplémentaire est agaçante, mais elle est très utile pour le débogage.

OutputDebugString s'imprime sur la sortie du débogueur lorsqu'il est exécuté à l'intérieur du débogueur.

12
Ringding

Si vous avez besoin de voir la sortie d'un programme existant qui utilisait abondamment printf sans changer le code (ou avec des modifications minimes), vous pouvez redéfinir printf comme suit et l'ajouter à l'en-tête commun (stdafx.h).

int print_log(const char* format, ...)
{
    static char s_printf_buf[1024];
    va_list args;
    va_start(args, format);
    _vsnprintf(s_printf_buf, sizeof(s_printf_buf), format, args);
    va_end(args);
    OutputDebugStringA(s_printf_buf);
    return 0;
}

#define printf(format, ...) \
        print_log(format, __VA_ARGS__)
4
vlad

Envisagez d’utiliser les macros d’exécution VC++ pour le reporting _ RPT [~ # ~] n [~ # ~] () et _RPTF [~ # ~] n [~ # ~] ()

Vous pouvez utiliser les macros _RPTn et _RPTFn, définies dans CRTDBG.H, pour remplacer l’utilisation des instructions printf pour le débogage. Ces macros disparaissent automatiquement dans votre version de publication lorsque _DEBUG n'est pas défini. Il n'est donc pas nécessaire de les inclure dans #ifdefs.

Exemple...

if (someVar > MAX_SOMEVAR) {
    _RPTF2(_CRT_WARN, "In NameOfThisFunc( )," 
         " someVar= %d, otherVar= %d\n", someVar, otherVar );
}

Ou vous pouvez utiliser les fonctions d'exécution VC++ _ CrtDbgReport, _CrtDbgReportW directement.

_CrtDbgReport et _CrtDbgReportW peuvent envoyer le rapport de débogage à trois destinations différentes: un fichier de rapport de débogage, un moniteur de débogage (le débogueur Visual Studio) ou une fenêtre de message de débogage.

_CrtDbgReport et _CrtDbgReportW créent le message utilisateur pour le rapport de débogage en substituant les arguments de l'argument [n] dans la chaîne de format, en utilisant les mêmes règles que celles définies par les fonctions printf ou wprintf. Ces fonctions génèrent ensuite le rapport de débogage et déterminent la ou les destinations, en fonction des modes de rapport actuels et du fichier défini pour reportType. Lorsque le rapport est envoyé à une fenêtre de message de débogage, le nom de fichier, le numéro de ligne et le nom de module sont inclus dans les informations affichées dans la fenêtre.

4
Autodidact

Si vous souhaitez imprimer des variables décimales:

wchar_t text_buffer[20] = { 0 }; //temporary buffer
swprintf(text_buffer, _countof(text_buffer), L"%d", your.variable); // convert
OutputDebugString(text_buffer); // print
4
svensito

Votre projet Win32 est probablement un projet graphique, pas un projet de console. Cela provoque une différence dans l'en-tête de l'exécutable. En conséquence, votre projet d'interface graphique sera responsable de l'ouverture de sa propre fenêtre. Cela peut être une fenêtre de console, cependant. Appelez AllocConsole() pour le créer et utilisez les fonctions de la console Win32 pour y écrire.

2
MSalters

Je cherchais un moyen de le faire moi-même et j'ai trouvé une solution simple.

Je suppose que vous avez démarré un projet Win32 par défaut (application Windows) dans Visual Studio, qui fournit une fonction "WinMain". Par défaut, Visual Studio définit le point d'entrée sur "SOUS-SYSTEME: WINDOWS". Vous devez d'abord changer cela en allant à:

Projet -> Propriétés -> Éditeur de liens -> Système -> Sous-système

Et sélectionnez "Console (/ SUBSYSTEM: CONSOLE)" dans la liste déroulante.

Maintenant, le programme ne fonctionnera pas, puisqu’une fonction "principale" est nécessaire à la place de la fonction "WinMain".

Alors maintenant, vous pouvez ajouter une fonction "principale" comme vous le feriez normalement en C++. Ensuite, pour lancer le programme graphique, vous pouvez appeler la fonction "WinMain" à partir de la fonction "principale".

La partie de départ de votre programme devrait maintenant ressembler à ceci:

#include <iostream>

using namespace std;

// Main function for the console
int main(){

    // Calling the wWinMain function to start the GUI program
    // Parameters:
    // GetModuleHandle(NULL) - To get a handle to the current instance
    // NULL - Previous instance is not needed
    // NULL - Command line parameters are not needed
    // 1 - To show the window normally
    wWinMain(GetModuleHandle(NULL), NULL,NULL, 1); 

    system("pause");
    return 0;
}

// Function for entry into GUI program
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    // This will display "Hello World" in the console as soon as the GUI begins.
    cout << "Hello World" << endl;
.
.
.

Résultat de ma mise en oeuvre

Vous pouvez maintenant utiliser des fonctions pour générer des sorties vers la console dans n’importe quelle partie de votre programme d’interface graphique à des fins de débogage ou à d’autres fins.

2
pops

Vous pouvez également utiliser la méthode WriteConsole pour imprimer sur la console.

AllocConsole();
LPSTR lpBuff = "Hello Win32 API";
DWORD dwSize = 0;
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), lpBuff, lstrlen(lpBuff), &dwSize, NULL);
1
HaSeeB MiR