使用ProcMon 输出调试信息
程序员文章站
2022-05-27 09:21:49
...
https://github.com/Wintellect/ProcMonDebugOutput
提供者
/*//////////////////////////////////////////////////////////////////////////////
// Process Monitor Debug Output Header File
//
// History:
// - April 1, 2010 - Version 1.0 - John Robbins/Wintellect
// - Initial release
// - March 1, 2014 - Version 1.1 - John Robbins/Wintellect
// - Fixed an issue in DLL main where the handle could get close too
// soon.
// - Moved the project to VS 2013.
//
//////////////////////////////////////////////////////////////////////////////*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/*//////////////////////////////////////////////////////////////////////////////
// The defines that set up how the functions or classes are exported or
// imported.
//////////////////////////////////////////////////////////////////////////////*/
#ifndef PROCMONDEBUGOUTPUT_DLLINTERFACE
#ifdef PROCMONDEBUGOUTPUT_EXPORTS
#define PROCMONDEBUGOUTPUT_DLLINTERFACE __declspec ( dllexport )
#else
#define PROCMONDEBUGOUTPUT_DLLINTERFACE __declspec ( dllimport )
#endif
#endif
/*//////////////////////////////////////////////////////////////////////////////
// ProcMonDebugOutput
// Sends a string to Process Monitor for display.
//
// Parameters:
// pszOutputString
// The null-terminated wide character string to be displayed.
//
// Return Values:
// TRUE - The string was sent to Process Monitor.
// FALSE - There was a problem sending the string to Process Monitor. To get
// extended error information, call GetLastError to determine the
// exact failure.
//
// Last Error Codes:
// ERROR_INVALID_PARAMETER - The pszOutputString parameter is NULL.
// ERROR_WRITE_FAULT - The Process Monitor driver is loaded but the
// Process Monitor user mode portion is not running.
// ERROR_BAD_DRIVER - The Process Monitor driver is not loaded.
//////////////////////////////////////////////////////////////////////////////*/
PROCMONDEBUGOUTPUT_DLLINTERFACE
_Success_(return == TRUE)
BOOL __stdcall ProcMonDebugOutput(_In_z_ LPCWSTR pszOutputString);
#ifdef __cplusplus
}
#endif
#include "stdafx.h"
#include "ProcMonDebugOutput.h"
#define FILE_DEVICE_PROCMON_LOG 0x00009535
#define IOCTL_EXTERNAL_LOG_DEBUGOUT (ULONG) CTL_CODE(FILE_DEVICE_PROCMON_LOG ,\
0x81 ,\
METHOD_BUFFERED ,\
FILE_WRITE_ACCESS )
// The global file handle to the Process Monitor device.
static HANDLE g_hDevice = INVALID_HANDLE_VALUE;
// Anonymous namespace for private helpers
namespace {
HANDLE OpenProcessMonitorLogger()
{
if (INVALID_HANDLE_VALUE == g_hDevice)
{
// I'm attempting the open every time because the user could start
// Process Monitor after their process.
g_hDevice = ::CreateFile(L"\\\\.\\Global\\ProcmonDebugLogger",
GENERIC_WRITE,
FILE_SHARE_WRITE,
nullptr,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
nullptr);
}
return g_hDevice;
}
void CloseProcessMonitorLogger()
{
if (INVALID_HANDLE_VALUE != g_hDevice)
{
::CloseHandle(g_hDevice);
g_hDevice = INVALID_HANDLE_VALUE;
}
}
// Used to pass strings to legacy C APIs expecting a raw void* pointer.
inline void* StringToPVoid(PCWSTR psz)
{
return reinterpret_cast<void *>(const_cast<wchar_t*>(psz));
}
} // anonymous namespace
PROCMONDEBUGOUTPUT_DLLINTERFACE _Success_(return == TRUE)
BOOL __stdcall ProcMonDebugOutput(_In_z_ LPCWSTR pszOutputString)
{
BOOL bRet = FALSE;
if (nullptr == pszOutputString)
{
::SetLastError(ERROR_INVALID_PARAMETER);
bRet = FALSE;
}
else
{
HANDLE hProcMon = OpenProcessMonitorLogger();
if (INVALID_HANDLE_VALUE != hProcMon)
{
DWORD iLen = static_cast<DWORD>(wcslen(pszOutputString) * sizeof (WCHAR));
DWORD iOutLen = 0;
bRet = ::DeviceIoControl(hProcMon,
IOCTL_EXTERNAL_LOG_DEBUGOUT,
StringToPVoid(pszOutputString),
iLen,
nullptr,
0,
&iOutLen,
nullptr);
if (FALSE == bRet)
{
DWORD dwLastError = ::GetLastError();
if (ERROR_INVALID_PARAMETER == dwLastError)
{
// The driver is loaded but the user mode Process Monitor
// program is not running so turn the last error into a
// write failure.
::SetLastError(ERROR_WRITE_FAULT);
}
}
}
else
{
// Process Monitor isn't loaded.
::SetLastError(ERROR_BAD_DRIVER);
bRet = FALSE;
}
}
return bRet;
}
BOOL APIENTRY DllMain(HMODULE /*hModule*/,
DWORD ul_reason_for_call,
LPVOID /*lpReserved*/)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
// Close the handle to the driver.
CloseProcessMonitorLogger();
break;
}
return TRUE;
}
使用方法:
int _tmain(void)
{
WCHAR szText[100];
for (int i = 0; i < 20; i++)
{
_stprintf_s(szText,
_countof(szText),
L"ProcMon Debug Out Test # %d",
i);
BOOL bRet = ProcMonDebugOutput(szText);
if (TRUE == bRet)
{
_tprintf(L"Wrote %d\n", i);
}
else
{
_tprintf(L"error 0x%x\n", GetLastError());
}
::Sleep(500);
}
return (0);
}
ProcMon配置:
以上!
推荐阅读
-
C#使用timer定时在屏幕上输出信息的方法
-
mssql sqlserver 使用sql脚本输出交替不同的背景色的html信息的方法分享
-
Jfinal中使用日志框架输出完整sql语句信息
-
如何使用FastReport.Net在SAP NetWeaver中生成报表-第2部分:输出信息(打印文档)
-
c++ thrift 库调试信息输出
-
使用readelf/objdump查看dwaf调试信息
-
使用ProcMon 输出调试信息
-
Golang写了一个帮助调试的代理程序,PHP实现了一个类用于输出调试信息
-
使用 Clockwork 扩展在 Chrome 浏览器中显示 Laravel 应用调试信息
-
Golang写了一个帮助调试的代理程序,PHP实现了一个类用于输出调试信息