首页 > 解决方案 > 使用 EvtFormatMessage 获取默认字符串

问题描述

我正在尝试使用 EvtFormatMessage 获取 DLL 中的基本字符串,但无论我做什么它都不起作用。Windows 帮助页面听起来像是您可以使用 values 和 valuecount 参数来更改默认行为,但是当我更改它们时,什么都不会打印。

我所做的另一项尝试是查看发布者元数据并将其与正确的 eventId 和版本匹配,但 EvtOpenEventMetadatEnum 没有可供它迭代所有事件发布者的项目。它适用于时间变化事件,但不适用于其他事件。

这是我必须返回消息字符串的代码。hMetadata 是发布者元数据,hEvent 是事件元数据

LPWSTR GetMessageString(EVT_HANDLE hMetadata, EVT_HANDLE hEvent, EVT_FORMAT_MESSAGE_FLAGS FormatId, DWORD MsgID)
{
LPWSTR pBuffer = NULL;
DWORD dwBufferSize = 0;
DWORD dwBufferUsed = 0;
DWORD status = ERROR_SUCCESS;

if (!fpEvtFormatMessage(hMetadata, hEvent, MsgID, 0, NULL, FormatId, dwBufferSize, pBuffer, &dwBufferUsed))
{
    status = GetLastError();
    if (ERROR_INSUFFICIENT_BUFFER == status)
    {
        // An event can contain one or more keywords. The function returns keywords
        // as a list of keyword strings. To process the list, you need to know the
        // size of the buffer, so you know when you have read the last string, or you
        // can terminate the list of strings with a second null terminator character 
        // as this example does.
        if ((EvtFormatMessageKeyword == FormatId))
            pBuffer[dwBufferSize - 1] = L'\0';
        else
            dwBufferSize = dwBufferUsed;

        pBuffer = (LPWSTR)malloc(dwBufferSize * sizeof(WCHAR));

        if (pBuffer)
        {
            fpEvtFormatMessage(hMetadata, hEvent, MsgID, 0, NULL, FormatId, dwBufferSize, pBuffer, &dwBufferUsed);

            // Add the second null terminator character.
            if ((EvtFormatMessageKeyword == FormatId))
                pBuffer[dwBufferUsed - 1] = L'\0';
        }
        else
        {
            TRACE5(_T("malloc failed\n"));
        }
    }
    else if (ERROR_EVT_MESSAGE_NOT_FOUND == status || ERROR_EVT_MESSAGE_ID_NOT_FOUND == status)
        ;
    else
    {
        TRACE5(_T("EvtFormatMessage failed with %u\n"), status);
    }
}

这是应该与我拥有的事件与 dll 中的模板事件相匹配的代码

hEvents = fpEvtOpenEventMetadataEnum(g_hMetadata, 0);
if (NULL == hEvents)
{
    TRACE5(_T("EvtOpenEventMetadataEnum failed with %lu\n"), GetLastError());
    goto cleanup;
}

// Enumerate the events and print each event's metadata.
while (run)
{
    hEvent = fpEvtNextEventMetadata(hEvents, 0);
    if (NULL == hEvent)
    {
        if (ERROR_NO_MORE_ITEMS != (status = GetLastError()))
        {
            TRACE5(_T("EvtNextEventMetadata failed with %lu\n"), status);
        }

        break;
    }
    msgId = getEventID(g_hMetadata, hEvent, &tempVersion);
    if (dwMsgID == msgId && tempVersion == version) {
        PEVT_VARIANT pProperty = NULL;  // Contains a metadata value
        PEVT_VARIANT pTemp = NULL;
        DWORD dwBufferSize = 0;
        DWORD dwBufferUsed = 0;
        DWORD status2 = ERROR_SUCCESS;

        if (!fpEvtGetEventMetadataProperty(hEvent, EventMetadataEventMessageID, 0, dwBufferSize, pProperty, &dwBufferUsed))
        {
            status2 = GetLastError();
            if (ERROR_INSUFFICIENT_BUFFER == status2)
            {
                dwBufferSize = dwBufferUsed;
                pTemp = (PEVT_VARIANT)realloc(pProperty, dwBufferSize);
                if (pTemp)
                {
                    pProperty = pTemp;
                    pTemp = NULL;
                    fpEvtGetEventMetadataProperty(hEvent, EventMetadataEventMessageID, 0, dwBufferSize, pProperty, &dwBufferUsed);
                }
                else
                {
                    TRACE5(_T("realloc failed\n"));
                    status2 = ERROR_OUTOFMEMORY;
                    goto cleanup;
                }
            }
            if (ERROR_SUCCESS != (status2 = GetLastError()))
            {
                TRACE5(_T("EvtGetEventMetadataProperty failed with %d\n"), GetLastError());
                goto cleanup;
            }
        }
        if (-1 == pProperty->UInt32Val)
        {
            *pStrNonExpLibMsg = "Message string: \n";
        }
        else
        {
            *pStrNonExpLibMsg = GetMessageString(g_hMetadata, NULL, EvtFormatMessageId, pProperty->UInt32Val);
            if (pMessage)
            {
                free(pMessage);
            }
        }
        run = false;
        break;
    }

    fpEvtClose(hEvent);
    hEvent = NULL;
}


cleanup:

if (hEvents)
    fpEvtClose(hEvents);

if (hEvent)
    fpEvtClose(hEvent);

return status;

}

DWORD getEventID(EVT_HANDLE g_hMetadata, EVT_HANDLE hEvent, DWORD *evtVersion)
{
PEVT_VARIANT pProperty = NULL;  // Contains a metadata value
PEVT_VARIANT pTemp = NULL;
DWORD dwBufferSize = 0;
DWORD dwBufferUsed = 0;
DWORD status = ERROR_SUCCESS;
DWORD retValue = NULL;

// Get the specified metadata property. If the pProperty buffer is not big enough, reallocate the buffer.
for (int i = 0; i < 2; i++) 
{
    if (!fpEvtGetEventMetadataProperty(hEvent, (EVT_EVENT_METADATA_PROPERTY_ID)i, 0, dwBufferSize, pProperty, &dwBufferUsed))
    {
        status = GetLastError();
        if (ERROR_INSUFFICIENT_BUFFER == status)
        {
            dwBufferSize = dwBufferUsed;
            pTemp = (PEVT_VARIANT)realloc(pProperty, dwBufferSize);
            if (pTemp)
            {
                pProperty = pTemp;
                pTemp = NULL;
                fpEvtGetEventMetadataProperty(hEvent, (EVT_EVENT_METADATA_PROPERTY_ID)i, 0, dwBufferSize, pProperty, &dwBufferUsed);
            }
            else
            {
                TRACE5(_T("realloc failed\n"));
                status = ERROR_OUTOFMEMORY;
                goto cleanup;
            }
        }
        if (ERROR_SUCCESS != (status = GetLastError()))
        {
            TRACE5(_T("EvtGetEventMetadataProperty failed with %d\n"), GetLastError());
            goto cleanup;
        }
    }
    if (i == 0) 
    {
        retValue = pProperty->UInt32Val;
    }
    else 
    {
        *evtVersion = pProperty->UInt32Val;
    }
    RtlZeroMemory(pProperty, dwBufferUsed);
}

标签: c++windowsevent-viewer

解决方案


推荐阅读