使用ProcMon 输出调试信息

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_18218335/article/details/79558713

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配置:
这里写图片描述

这里写图片描述

以上!

猜你喜欢

转载自blog.csdn.net/qq_18218335/article/details/79558713
今日推荐