-
[WinAPI] 로그 출력하기 (Console, TRACE)C++/미분류 2024. 2. 16. 16:25
로그는 프로그램의 상태를 확인할 때 사용하는 가장 직관적인 방법 중 하나입니다.
WinAPI는 자체적인 로그를 출력하는 기능을 제공하지 않기 때문에, 로그를 출력할 방법이 필요합니다.
이번 글에서는 로그를 출력하는 여러 방법 중, Console창을 추가로 띄우는 방법과 MFC에서 사용하는 방법을 살펴보도록 하겠습니다.
이번 글은 Visual Studio 2022환경에서 작성되었습니다.
0. 시작하기 전에
더보기이번 글은 프로그램 실행 환경을 디버그와 릴리즈 두 가지를 번갈아 가며 확인할 예정입니다.
따라서, 디버그와 릴리즈 환경에서의 진입점 및 라이브러리 의존성을 동일하게 할 필요가 있습니다.
프로젝트 우클릭 후 Properties로 진입합니다.
진입한 Property Page의 Configuration을 다음 이미지와 같이 변경합니다.
Configuration을 All Configurations로 변경합니다.
이후 Debug와 Release에서 독립적으로 적용되어야 하는 속성이 있을 경우, 추가로 편집할 수 있습니다.
추가 의존성을 다음 이미지와 같이 편집합니다.
Linker -> Input -> Additional Dependencies 클릭 후 Edit, 생성되는 창에 다음과 같은 라이브러리를 추가합니다.
d2d1.lib
dwrite.lib
WindowsCodecs.lib이후 프로그램 진입점을 다음 이미지와 같이 편집합니다.
Linker -> System -> SubSystem을 Windows로 변경합니다.
1. Console
더보기콘솔은 개발 시 매우 친숙하게 접근할 수 있는 UI중 하나입니다.
프로그램 진입점을 윈도우로 바꾸면 콘솔 창이 나오지 않게 되므로, printf나 cout같은 출력 함수를 사용할 수 없게 됩니다.
다음 코드는 윈도우 프로그램에서 콘솔 창을 추가로 생성하는 코드입니다.
#pragma comment(linker, "/entry:WinMainCRTStartup /subsystem:console")
해당 코드는 프로그램의 엔트리를 WinMain으로 설정하되, 하위 시스템을 콘솔로 지정하는 코드입니다.
이 코드를 컴파일 후 실행할 경우, 윈도우 창과 콘솔 창이 동시에 생성됩니다.
다만, 콘솔 창은 배포시에는 출력되지 않아야 할 필요가 있습니다.
아래 코드를 추가하여, Debug환경에서만 해당 기능이 작동할 수 있도록 제한할 수 있습니다.
#ifdef _DEBUG #pragma comment(linker, "/entry:WinMainCRTStartup /subsystem:console") #endif
위 코드의 #ifdef, #endif사이의 블록은 디버그 환경에서만 실행됩니다.
만약 릴리즈 환경에서 선언되어야 할 코드가 있을 경우, 아래와 같이 작성할 수 있습니다.
#ifdef _DEBUG // Debug #else // Release #endif
결론적으로, 위 코드를 통해 윈도우 프로그램 환경에서 콘솔 창을 생성할 수 있습니다.
이 경우, printf와 cout등의 출력 함수들이 콘솔에 출력됩니다.
2. TRACE
더보기MFC에는 TRACE라는 로그 출력 매크로가 있습니다.
WinAPI에는 해당 기능이 없지만, 직접 구현해서 사용할 수 있습니다.
다음은 TRACE매크로의 선언 코드입니다.
#define TRACE TRACE_WIN32 void TRACE_WIN32(LPCTSTR lpszFormat, ...) { TCHAR lpszBuffer[0x160]; va_list fmtList; va_start(fmtList, lpszFormat); _vstprintf_s(lpszBuffer, lpszFormat, fmtList); va_end(fmtList); OutputDebugString(lpszBuffer); }
위 코드를 이용하면, 아래와 같이 TRACE매크로를 호출할 수 있습니다.
int tmp = 0; TRACE(L"tmp = %d\n", tmp);
사용법은 printf와 매우 유사합니다.
TRACE의 결과물은 Visual Studio의 Debugging 실행 환경의 output에서 확인할 수 있습니다.
해당 기능 또한 디버그 환경에서 필요하고, 릴리즈 환경에서는 불필요합니다.
콘솔 창을 직접적으로 띄우는 이전 문단과는 다르게, 위와 같은 로그는 직접 보려고 하지 않으면 볼 수 없지만, 출력 오버헤드 및 프로그램의 민감한 정보가 노출될 수 있다는 점에서, 릴리즈 환경에서는 출력하지 않을 필요가 있습니다.
다음 코드는 TRACE매크로를 Debug환경에서만 유효하도록 바꾸는 코드입니다.
#if defined(_DEBUG) && defined(WIN32) && !defined(_AFX) && !defined(_AFXDLL) #define TRACE TRACE_WIN32 void TRACE_WIN32(LPCTSTR lpszFormat, ...) { TCHAR lpszBuffer[0x160]; va_list fmtList; va_start(fmtList, lpszFormat); _vstprintf_s(lpszBuffer, lpszFormat, fmtList); va_end(fmtList); OutputDebugString(lpszBuffer); } #else #define TRACE #endif
TRACE코드의 정의는 이전 예제와 동일합니다.
하지만, TRACE의 선언에 몇 가지 조건이 추가되었습니다.
추가된 조건은 DEBUG모드와, Win32환경일 경우 등 입니다.
조건이 맞을 경우 TRACE가 출력 함수로써 정의되고, 맞지 않을 경우 아무런 역할도 수행하지 않습니다.
WinAPI개발에서 로그 출력에 사용할 수 있는 방법 몇 가지를 알아보았습니다.
전체 소스 코드는 아래 Github에서 확인하실 수 있습니다.
이번 글이 도움이 되셨기를 바랍니다.
감사합니다.
'C++ > 미분류' 카테고리의 다른 글
[WinAPI] 키보드 입력 (WM_KEYDOWN, WM_KEYUP, GetAsyncKeyState) (0) 2024.02.23 [DirectX] QPC로 FPS(프레임 레이트) 구현하기 (0) 2024.02.20 [Direct2D] 도형 그려보기 (0) 2024.02.08 [Win32] Windows application 만들기 (1) 2024.01.25 [C++] 랜덤 이벤트 (확률) 구현하기 (0) 2022.10.06