欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

使用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配置:
使用ProcMon 输出调试信息

使用ProcMon 输出调试信息

以上!

相关标签: 调试