如何监听OutputDebugString

代码

#include <iostream>
#include <io.h>
#include <fcntl.h>
#include <process.h>
#include <Windows.h>
#include<thread>
#include <windows.h>
#include <atlbase.h>
#include <atlstr.h>


// -------------------------------------------------------------------------------
//  PROPERTIES OF OBJECTS
// -------------------------------------------------------------------------------
//	NAME			|	DBWIN_BUFFER_READY		DBWIN_DATA_READY	DBWIN_BUFFER
// -------------------------------------------------------------------------------
//	TYPE			|	Event					Event			FileMapping
//	ACCESS		|	All						Sync				All
//	INIT STATE	|	Signaled				Nonsignaled			Not open
//	PROPERTY		|	Auto-Reset			Auto-Reset			PAGE_READWRITE
//  Handle Name 	|	hEventBufferReady		hEventDataReady		DBWinBufferHandle
// -------------------------------------------------------------------------------
HANDLE DBWinBufferHandle;
HANDLE hEventBufferReady;
HANDLE hEventDataReady;

HANDLE m_hWinDebugMonitorThread;
BOOL m_bWinDebugMonStopped;
struct DBWIN_BUFFER_VIEW
{
	DWORD   dwProcessId;
	char    data[4096 - sizeof(DWORD)];
};
struct DBWIN_BUFFER_VIEW* pDBWIN_BufferView;
bool gMonitor = true;
std::thread gMonitorThread;
void MonitorFunction();

DWORD InitializeMonitor()
{
	DWORD errorCode = 0;
	BOOL bSuccessful = FALSE;
	SetLastError(0);

	// Shared memory
	// ---------------------------------------------------------	
	DBWinBufferHandle = ::OpenFileMapping(
		FILE_MAP_READ,
		FALSE,
		L"DBWIN_BUFFER"
	);

	if (DBWinBufferHandle == NULL) {
		DBWinBufferHandle = ::CreateFileMapping(
			INVALID_HANDLE_VALUE,
			NULL,
			PAGE_READWRITE,
			0,
			sizeof(DBWIN_BUFFER_VIEW),
			L"DBWIN_BUFFER"
		);

		if (DBWinBufferHandle == NULL) {
			errorCode = GetLastError();
			return errorCode;
		}
	}

	pDBWIN_BufferView = (DBWIN_BUFFER_VIEW*)::MapViewOfFile(
		DBWinBufferHandle,
		SECTION_MAP_READ,
		0,
		0,
		0
	);

	if (pDBWIN_BufferView == NULL) {
		errorCode = GetLastError();
		return errorCode;
	}

	// Event: buffer ready
	// ---------------------------------------------------------
	hEventBufferReady = ::OpenEvent(
		EVENT_ALL_ACCESS,
		FALSE,
		L"DBWIN_BUFFER_READY"
	);

	if (hEventBufferReady == NULL) {
		hEventBufferReady = ::CreateEvent(
			NULL,
			FALSE,	// auto-reset
			TRUE,	// initial state: signaled
			L"DBWIN_BUFFER_READY"
		);

		if (hEventBufferReady == NULL) {
			errorCode = GetLastError();
			return errorCode;
		}
	}

	// Event: data ready
	// ---------------------------------------------------------	
	hEventDataReady = ::OpenEvent(
		SYNCHRONIZE,
		FALSE,
		L"DBWIN_DATA_READY"
	);

	if (hEventDataReady == NULL) {
		hEventDataReady = ::CreateEvent(
			NULL,
			FALSE,	// auto-reset
			FALSE,	// initial state: nonsignaled
			L"DBWIN_DATA_READY"
		);

		if (hEventDataReady == NULL) {
			errorCode = GetLastError();
			return errorCode;
		}
	}

	// Monitoring thread
	// ---------------------------------------------------------
	gMonitor = true;
	gMonitorThread = std::move(std::thread(&MonitorFunction));
	return errorCode;
}

void UninitializeMonitor()
{
	gMonitor = false;
	gMonitorThread.join();

	if (DBWinBufferHandle != NULL) {
		::UnmapViewOfFile(pDBWIN_BufferView);
		CloseHandle(DBWinBufferHandle);
		DBWinBufferHandle = NULL;
	}

	if (hEventBufferReady != NULL) {
		CloseHandle(hEventBufferReady);
		hEventBufferReady = NULL;
	}

	if (hEventDataReady != NULL) {
		CloseHandle(hEventDataReady);
		hEventDataReady = NULL;
	}
	pDBWIN_BufferView = NULL;
}

void MonitorFunction()
{
	DWORD ret = 0;
	const DWORD	TIMEOUT_WIN_DEBUG = 100;	
	while (gMonitor)
	{
		// wait for data ready
		ret = ::WaitForSingleObject(hEventDataReady, TIMEOUT_WIN_DEBUG);
		if (ret == WAIT_OBJECT_0) {
			std::cout << pDBWIN_BufferView->data;
			// signal buffer ready
			SetEvent(hEventBufferReady);
		}
	}	
}


int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    AllocConsole();
    FILE* reopenOut = nullptr;    
    FILE* repoenErr = nullptr;
    freopen_s(&reopenOut, "CONOUT$", "w+t", stdout); 
    freopen_s(&repoenErr, "CONOUT$", "w+t", stderr); 
	InitializeMonitor();
	for (int i = 0; i < 10; ++i)
	{
		OutputDebugStringA("OutputDebugStringA\n");
		std::this_thread::sleep_for(std::chrono::seconds(1));
	}
	UninitializeMonitor();	

    return 0;
}

参考

Mechanism-of-OutputDebugString
Understanding Win32 “OutputDebugString”
DebugViewPP
线程监视 OutputDebugString 的调试输出
如何把std::cout标准输出重定向到vs2019的输出窗口中

My understanding

  • 我需要这个,因为我想在没有vs2019调试时看到调试字符串
  • OutputDebugString,它将等待DBWIN_BUFFER_READY Event,然后将buff写入DBWIN_BUFFER,然后设置 DBWIN_DATA_READY Event
  • 所以我们可以等待DBWIN_DATA_READY event,将DBWIN_BUFFER打印到控制台,设置 DBWIN_BUFFER_READY event
  • 使用VS2019调试时不会起作用
  • 我对此只有一点了解,我们可以从DebugViewPP项目中了解更多信息
发布了8 篇原创文章 · 获赞 4 · 访问量 1694
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览