1. 程式人生 > >使用ProcMon 輸出除錯資訊

使用ProcMon 輸出除錯資訊

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配置:
這裡寫圖片描述

這裡寫圖片描述

以上!