你是否正在寻找关于outputdebugstring的内容?让我把最俱价值的东西奉献给你:
DebugOutputString
功能:发送一个字串到调试器的显示。
函数原型:void WINAPI outputdebugstring( LPCTSTR lpOutputString );
头文件:<windows.h>
一.最简单的用法
#define MAX_DBG_MSG_LEN (1024)
char[MAX_DBG_MSG_LEN];
sprintf(msgbuf, "LastError=%ld/n", GetLastError());
outputdebugstring(msgbuf);
二.扩展的用法
按照printf的风格的对outputdebugstring进行封装
#define MAX_DBG_MSG_LEN (1024)
static void __dbg_printf (const char * format,...)
{
char buf[MAX_DBG_MSG_LEN];
va_list ap;
va_start(ap, format);
_vsnprintf(buf, sizeof(buf), format, ap);
va_end(ap);
outputdebugstring(buf);
}
使用:
__dbg_printf( "LastError=%ld/n", GetLastError());
三.进一步的扩展
对DEBUG和RELEASE下的区分.
ifdef _DEBUG
static void __dbg_printf (const char * format,...)
{
char buf[MAX_DBG_MSG_LEN];
va_list ap;
va_start(ap, format);
_vsnprintf(buf, sizeof(buf), format, ap);
va_end(ap);
outputdebugstring(buf);
}
#else
static void __dbg_printf (const char * format,...) {}
#endif
顺便说一下宏中对不定参数的使用
Linux下
#define dbg(format, arg...) __dbg_printf(format, ## arg)
Windows
#define dbg(format, ...) __dbg_printf(format, __VA_ARGS__)
当然有最直接的定义方式
#define dbg __dbg_printf
还有一个应该算比较独特的用法吧
#define PerFormat "[ThreadID @ %08d] "
#define dbgex(format, ...) __dbg_printf(PerFormat format,
GetCurrentProcessId(), __VA_ARGS__)
四.相关协议 (这段是转载)
在应用程序和调试器之间传递数据是通过一个 4KB 大小的共享内存块完成的,并有一个互斥量和两个事件对象用来保护对他的访问。下面就是相关的四个内核对象:
对象名称 对象类型
DBWinMutex Mutex
DBWIN_BUFFER Section (共享内存)
DBWIN_BUFFER_READY Event
DBWIN_DATA_READY Event
互斥量通常一直保留在系统中,其他三个对象仅当调试器要接收信息才出现,。事实上 - 如果一个调试器发现后三个对象已经存在,它会拒绝运行。 当 DBWIN_BUFFER 出现时,会被组织成以下结构。进程 ID 显示信息的来源,字符串数据填充这 4K 的剩余部分。按照约定,信息的末尾总是包括一个 NULL 字节。
struct dbwin_buffer
{
DWORD dwProcessId;
char data[4096-sizeof(DWORD)];
};
当 outputdebugstring() 被应用调用时,它执行以下步骤。注意在任意位置的错误都将放弃整个事情,调试请求被认为是什么也不做(不会发送字符串)。
1. 打开 DBWinMutex 并且等待,直到我们取得了独占访问。
2. 映射 DBWIN_BUFFER 段到内存中:如果没有发现,则没有调试器在运行,将忽略整个请求。
3. 打开 DBWIN_BUFFER_READY 和 DBWIN_DATA_READY 事件对象。就像共享内存段一样,缺少对象意味着没有可用的调试器。
4. 等待 DBWIN_BUFFER_READY 事件对象为有信号状态:表示内存缓冲区不再被占用。大部分时候,这一事件对象一被检查就处于有信号状态,但等待缓冲区就绪不会超过 10 秒(超时将放弃请求)。
5. 复制数据直到内存缓冲区中接近 4KB,再保存当前进程 ID。总是放置一个 NULL 字节到字符串结尾。
6. 通过设置 DBWIN_DATA_READY 事件对象告诉调试器缓冲区就绪。调试器从那儿取走它。
7. 释放互斥量。
8. 关闭事件对象和段对象,但保留互斥量的句柄以备后用。
在调试器端会简单一点。互斥量根本不需要,如果事件对象和/或共享内存对象已经存在,则假定其他调试器已经在运行。系统中任意时刻只能存在一个调试器。
1. 创建共享内存段以及两个事件对象。如果失败,退出。
2. 设置 DBWIN_BUFFER_READY 事件对象,由此应用程序得知缓冲区可用。
3. 等待 DBWIN_DATA_READY 事件对象变为有信号状态。
4. 从内存缓冲区中提取进程 ID 和 NULL 结尾的字符串。
5. 转到步骤 2。
这使我们认为这决不是一种低消耗的发送信息的方法,应用程序的运行速度会受到调试器的左右。
五.自己实现检测功能(主要框架);
//首先创建两个事件
hAckEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("DBWIN_BUFFER_READY"));
m_hReadyEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("DBWIN_DATA_READY"));
//创建共享内存.
hMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MAX_DBG_MSG_LEN, TEXT("DBWIN_BUFFER"));
//映射
pdbBuffer = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
while(true)
{
//通知共享内存可用
SetEvent(hAckEvent);
//等待写入消息的事件.
if (WaitForSingleObject(m_hReadyEvent, INFINITE) == WAIT_OBJECT_0)
{
//处理消息
//pdbBuffer里存放dbwin_buffer结构
}
}
以上就是关于outputdebugstring的全部内容,相信你一定会非常满意。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/shenmilingyu/article-6301-1.html
警告中国人拒绝美曰货
美帝此次行动