Win32 앱에서 디버그 출력 창에 인쇄하려면 어떻게해야합니까?


98

Visual Studio 2005에로드 한 win32 프로젝트가 있습니다. Visual Studio 출력 창에 항목을 인쇄하고 싶지만 평생 방법을 알아낼 수 없습니다. 나는 'printf'와 'cout <<'을 시도했지만 내 메시지는 완고하게 인쇄되지 않습니다.

Visual Studio 출력 창에 인쇄하는 특별한 방법이 있습니까?


11
Visual Studio 출력 창은 콘솔이 아닙니다. 둘 다 "텍스트가있는 창"이지만이면에서는 다릅니다.
MSalters

VS 출력 창이 기본적으로 각 메시지 앞에 소스 cpp의 전체 경로를 표시하는 경우 __ FILE __에 대한 해결 방법 을 고려하십시오 .
Laurie Stearn

답변:


137

사용할 수 있습니다 OutputDebugString. OutputDebugString빌드 옵션에 따라 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-08-26

1
sysinternals에서 debugview를 사용하는 것이 유용하다는 것을 알 수 있습니다. 이렇게하면 Visual Studio가 실행 중이 아니거나 설치되어 있지 않아도 ODS 출력을 볼 수 있습니다
pm100

4
@CDT : 유형에 따라 다릅니다 myStr. 그것은인가 char*, wchar_t*또는 LPTSTR? 그것이 가정하면 char*당신은 단순히 전화 OutputDebugStringA(myStr)또는 사용 OutputDebugStringWwchar_t*OutputDebugString함께 LPTSTR내 대답에 설명 된대로.
Martin Liversage 2013 년

1
@CDT : 출력하려는 ​​메시지 인 단일 매개 변수가있는 함수를 호출하는 것보다 더 간단한 것은 무엇입니까? ANSI / UNICODE 복잡성입니까? 사용 OutputDebugString하는 문자의 너비와 일치하도록 적절한 전 처리기 기호를 사용 하고 정의하거나 8 비트 및 16 비트 문자로 컴파일 할 수있는 유연한 "T"유형을 사용하십시오.
Martin Liversage

1
@MonaJalal : 어떤 화면 인지 코멘트에서 명확하지 않으므로 구체적인 조언을 제공하기가 조금 어렵습니다. 프로세스를 디버깅하는 경우 디버거는 디버그 출력을 표시 할 수 있습니다. Visual Studio를 디버거로 사용하는 경우 출력이 출력 창에 표시됩니다. 실제로 당신이 선택해야 출력 보려면 디버그 으로부터 의 표시 출력 드롭 다운을. 어떤 이유로 디버거 외부에서 프로세스를 실행하는 경우 DebugView 를 사용 하여 모든 프로세스의 디버그 출력을 볼 수 있습니다 .
Martin Liversage

29

프로젝트가 GUI 프로젝트 인 경우 콘솔이 표시되지 않습니다. 프로젝트를 콘솔로 변경하려면 프로젝트 속성 패널로 이동하여 다음을 설정해야합니다.

  • " linker-> System-> SubSystem "에서 값 " Console (/ SUBSYSTEM : CONSOLE) "값
  • " C / C ++-> 전 처리기-> 전 처리기 정의 "에서 " _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사용 WinMain하는 경우에도 하위 시스템을로 설정할 수 있습니다 int main().
벤 보이트

1
@Zac. 감사! AllocConsole ()로 시작하는 4 줄은 훌륭하게 작동했습니다. 플러스 1입니다. 이전에 / SUBSYSTEM : CONSOLE 및 / 또는 _CONSOLE 매크로를 사용하기 전에 Win32 프로젝트에서 이전에 콘솔을 표시했지만 다른 것은 작동하지 않았습니다. 오늘 저녁에 매크로가 작동하지 않는 이유를 모르겠습니다. 공용 언어 런타임 지원 (/ clr) 을 사용하는 것과 관련이 있습니까?
riderBill

12

real콘솔에 인쇄하려면 링커 플래그를 사용하여 표시해야합니다 /SUBSYSTEM:CONSOLE. 추가 콘솔 창은 성가 시지만 디버깅 목적으로 매우 유용합니다.

OutputDebugString 디버거 내에서 실행될 때 디버거 출력에 인쇄합니다.


6
AllocConsole ()을 사용하여 자신의 콘솔을 할당 할 수도 있습니다
Billy ONeal

5

_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는 디버그 보고서 파일, 디버그 모니터 (Visual Studio 디버거) 또는 디버그 메시지 창의 세 가지 다른 대상으로 디버그 보고서를 보낼 수 있습니다.

_CrtDbgReport 및 _CrtDbgReportW는 printf 또는 wprintf 함수에 정의 된 동일한 규칙을 사용하여 argument [n] 인수를 형식 문자열로 대체하여 디버그 보고서에 대한 사용자 메시지를 만듭니다. 그런 다음 이러한 함수는 디버그 보고서를 생성하고 reportType에 대해 정의 된 현재 보고서 모드 및 파일을 기반으로 대상을 결정합니다. 보고서가 디버그 메시지 창으로 전송되면 파일 이름, lineNumber 및 moduleName이 창에 표시되는 정보에 포함됩니다.


_RPTF0형식 문자열 뒤에 변수가 전달되지 않을 것으로 예상되는 곳에서 사용할 수있는 답변에 추가하거나 주목할 가치가 있습니다. 반면에 _RPTFN매크로 는 형식 문자열 뒤에 최소한 하나의 인수 가 필요 합니다.
amn

5

소수 변수를 인쇄하려면 다음을 수행하십시오.

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

%uunsigned의 경우, %ffloat의 경우 참조에 따라 .
Laurie Stearn

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
정적 버퍼 때문에주의해야합니다.이 함수는 재진입이 불가능하며 다른 스레드에서 사용할 수 없습니다.
Nikazo 2011

2

Win32 프로젝트는 콘솔 프로젝트가 아닌 GUI 프로젝트 일 수 있습니다. 이로 인해 실행 가능한 헤더에 차이가 발생합니다. 결과적으로 GUI 프로젝트는 자체 창을 열어야합니다. 하지만 콘솔 창일 수 있습니다. 호출 AllocConsole()하여 작성하고 Win32 콘솔 함수를 사용하여 작성하십시오.


2

나는 이것을 직접 할 방법을 찾고 있었고 간단한 해결책을 찾았습니다.

Visual Studio에서 "WinMain"기능을 제공하는 기본 Win32 프로젝트 (Windows 응용 프로그램)를 시작했다고 가정합니다. 기본적으로 Visual Studio는 진입 점을 "SUBSYSTEM : WINDOWS"로 설정합니다. 먼저 다음으로 이동하여이를 변경해야합니다.

프로젝트-> 속성-> 링커-> 시스템-> 하위 시스템

드롭 다운 목록에서 "콘솔 (/ SUBSYSTEM : CONSOLE)"을 선택합니다.

이제 "WinMain"기능 대신 "main"기능이 필요하므로 프로그램이 실행되지 않습니다.

이제 일반적으로 C ++에서하는 것처럼 "main"함수를 추가 할 수 있습니다. 그런 다음 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.