Win32アプリのデバッグ出力ウィンドウに出力するにはどうすればよいですか?


97

Visual Studio 2005に読み込んだwin32プロジェクトを持っています。VisualStudioの出力ウィンドウに印刷できるようにしたいのですが、私は一生かけてどのように作業するかできません。「printf」と「cout <<」を試しましたが、メッセージが頑固に印刷されません。

Visual Studioの出力ウィンドウに印刷する特別な方法はありますか?


11
Visual Studio出力ウィンドウはコンソールではないことに注意してください。どちらも「テキストが入ったウィンドウ」ですが、舞台裏では異なります。
MSalters 2009

回答:


136

使用できますOutputDebugStringOutputDebugStringは、ビルドオプションに応じて、OutputDebugStringA(char const*)またはにマップされるマクロですOutputDebugStringW(wchar_t const*)。後者の場合、ワイド文字列を関数に提供する必要があります。ワイド文字リテラルを作成するには、Lプレフィックスを使用できます。

OutputDebugStringW(L"My output string.");

通常、次のようにマクロと一緒にマクロバージョンを使用します_T

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

プロジェクトがUNICODE用にビルドするように構成されている場合は、次のように展開されます。

OutputDebugStringW(L"My output string.");

UNICODE向けにビルドしていない場合は、次のように展開されます。

OutputDebugStringA("My output string.");

2
パーフェクト!ありがとう。ただし、完全を期すために、これを実行する必要があることがわかりました。OutputDebugString(TEXT( "Hello console world")); ..おそらく何らかのユニコード関連のビルドオプションが原因です。
izb 2009

1
sysinternalsからdebugviewを使用すると便利です。これにより、ボックスでVisual Studioが実行されていない(またはインストールされている)場合でも、ODS出力を確認できます
pm100

4
@CDT:のタイプによって異なりmyStrます。それかchar*wchar_t*それともLPTSTR?それがあると仮定すると、char*あなたは、単に呼び出すOutputDebugStringA(myStr)か、使用OutputDebugStringWしてwchar_t*OutputDebugStringしてLPTSTR私の答えで説明したように。
Martin Liversage 2013年

1
@CDT:出力するメッセージである単一のパラメーターを持つ関数を呼び出すよりも簡単なことは何ですか?ANSI / UNICODEの複雑さですか?使用してOutputDebugString、使用する文字の幅に一致する適切なプリプロセッサシンボルを定義するか、8ビットと16ビットの両方の文字にコンパイルできる柔軟な "T"タイプを使用します。
マーティンLiversage 2013年

1
@MonaJalal:コメントからは画面が明確でないため、具体的なアドバイスをするのは少し難しいです。プロセスをデバッグする場合、デバッガーにはデバッグ出力を表示する方法があります。デバッガーとしてVisual Studioを使用している場合、出力は[ 出力]ウィンドウに表示されます。実際に出力を表示するには、ドロップダウンから[出力を表示 ] から[ デバッグ]を選択する必要があります。何らかの理由でデバッガの外部でプロセスを実行している場合は、DebugViewを使用して、すべてのプロセスからのデバッグ出力を確認できます。
Martin Liversage 2017年

29

プロジェクトがGUIプロジェクトの場合、コンソールは表示されません。プロジェクトをコンソールに変更するには、プロジェクトのプロパティパネルに移動して次のように設定する必要があります。

  • " リンカー->システム->サブシステム "の値 " コンソール(/ SUBSYSTEM:CONSOLE)
  • C / C ++-> Preprocessor-> Preprocessor Definitions」に「_CONSOLE」定義を追加します

このソリューションは、古典的な " int main()がある場合にのみ機能します」エントリポイント。

しかし、私のような場合(openGLプロジェクト)、プロパティを編集する必要はありません。

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

printfとcoutは通常どおり機能します。

ウィンドウを作成する前にAllocConsoleを呼び出すと、コンソールはウィンドウの背後に表示され、後で呼び出すと、前面に表示されます。

更新

freopenは非推奨であり、安全でない可能性があります。freopen_s代わりに使用:

FILE* fp;

AllocConsole();
freopen_s(&fp, "CONIN$", "r", stdin);
freopen_s(&fp, "CONOUT$", "w", stdout);
freopen_s(&fp, "CONOUT$", "w", stderr);

EDITBINではなくCONSOLEを使用している場合でも、サブシステムをに設定できます。WinMainint main()
Ben Voigt 2013年

1
@Zac。ありがとう!AllocConsole()で始まる4行はうまくいきました。プラス1。/ SUBSYSTEM:CONSOLEや_CONSOLEマクロを使用する前に、Win32プロジェクトでコンソールを表示する前に、他に何も機能していませんでした。マクロが今晩機能しなかった理由がわかりません。それは使用を行うには何も持っている可能性があり、共通言語ランタイムサポート(/ CLR)を
riderBill、2015年

12

印刷するにはreal、コンソールには、リンカフラグを使用することによって、それが目に見えるようにする必要があり/SUBSYSTEM:CONSOLE。余分なコンソールウィンドウは煩わしいですが、デバッグの目的には非常に役立ちます。

OutputDebugString デバッガー内で実行するときに、デバッガーの出力に出力します。


6
AllocConsole()を使用して独自のコンソールを割り当てることもできます
Billy ONeal

4

_RPT N()および_RPTF N()のレポートにVC ++ランタイムマクロを使用することを検討してください

CRTDBG.Hで定義されている_RPTnおよび_RPTFnマクロを使用して、デバッグ用のprintfステートメントの使用を置き換えることができます。これらのマクロは、_DEBUGが定義されていない場合、リリースビルドで自動的に非表示になるため、#ifdefsで囲む必要はありません。

例...

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

または、VC ++ランタイム関数_CrtDbgReport、_CrtDbgReportWを直接使用することもできます。

_CrtDbgReportおよび_CrtDbgReportWは、デバッグレポートを3つの異なる宛先(デバッグレポートファイル、デバッグモニター(Visual Studioデバッガー)、またはデバッグメッセージウィンドウ)に送信できます。

_CrtDbgReportおよび_CrtDbgReportWは、printf関数またはwprintf関数で定義されたのと同じルールを使用して、argument [n]引数をフォーマット文字列に置き換えることにより、デバッグレポートのユーザーメッセージを作成します。これらの関数は、デバッグレポートを生成し、現在のレポートモードとreportTypeに定義されたファイルに基づいて、1つまたは複数の宛先を決定します。レポートがデバッグメッセージウィンドウに送信されると、ファイル名、lineNumber、およびmoduleNameがウィンドウに表示される情報に含まれます。


回答に追加するか_RPTF0、フォーマット文字列の後に変数が渡されないことが予想される場合に使用できることに注意してください。_RPTFNマクロは、一方で、必要とするフォーマット文字列以下の少なくとも一つの引数を。
2018

4

10進変数を出力する場合:

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

4

コードを変更せずに(または最小限の変更で)printfを広範囲に使用した既存のプログラムの出力を確認する必要がある場合は、printfを次のように再定義して、共通ヘッダー(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__)

1
静的バッファーのため、注意が必要です。この関数は再入可能ではなく、別のスレッドからは使用できません。
ニカゾ2017年

2

Win32プロジェクトは、おそらくコンソールプロジェクトではなくGUIプロジェクトです。これにより、実行可能ヘッダーに違いが生じます。その結果、GUIプロジェクトは独自のウィンドウを開く必要があります。ただし、コンソールウィンドウの場合もあります。呼び出しAllocConsole()て作成し、Win32コンソール関数を使用して書き込みます。


2

私はこれを自分で行う方法を探していて、簡単な解決策を見つけました。

「WinMain」機能を提供するデフォルトのWin32プロジェクト(Windowsアプリケーション)をVisual Studioで起動したと想定しています。デフォルトでは、Visual Studioはエントリポイントを "SUBSYSTEM:WINDOWS"に設定します。最初にこれを変更する必要があります:

プロジェクト->プロパティ->リンカ->システム->サブシステム

そして、ドロップダウンリストから「コンソール(/ SUBSYSTEM:CONSOLE)」を選択します。

これで、「WinMain」関数の代わりに「main」関数が必要になるため、プログラムは実行されません。

したがって、C ++で通常行うように、「メイン」関数を追加できます。この後、GUIプログラムを開始するには、「main」関数内から「WinMain」関数を呼び出すことができます。

プログラムの最初の部分は次のようになります。

#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;
.
.
.

私の実装の結果

関数を使用して、デバッグまたはその他の目的でGUIプログラムの任意の部分でコンソールに出力できます。


2

WriteConsoleメソッドを使用して、コンソールに印刷することもできます。

AllocConsole();
LPSTR lpBuff = "Hello Win32 API";
DWORD dwSize = 0;
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), lpBuff, lstrlen(lpBuff), &dwSize, NULL);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.