Události související se záložkami
Záložka identifikuje událost v kanálu nebo souboru protokolu. Záložku můžete použít při dotazování na události nebo přihlášení k odběru událostí, abyste mohli začít číst události z této události. Obvykle vytvoříte záložku poslední události v sadě výsledků (za předpokladu, že jste v sadě výsledků vyčíslili všechny události).
Následující postup popisuje, jak vytvořit záložku z události.
Vytvoření záložky z události
- Voláním funkce EvtCreateBookmark vytvořte záložku. Předat jako argument NULL.
- Voláním funkce EvtUpdateBookmark aktualizujte záložku událostí. Předejte popisovač události jako argument.
- Voláním funkce EvtRender vytvořte řetězec XML, který představuje záložku. Předejte EvtRenderBookmark jako příznak vykreslování.
- Uložte řetězec XML pro pozdější použití (například řetězec XML můžete zachovat v souboru nebo registru).
Následující postup popisuje, jak vytvořit záložku pomocí řetězce záložky XML, který byl zachován v předchozím postupu.
Vytvoření záložky pomocí řetězce záložky XML
- Získejte řetězec XML, který představuje záložku, kterou jste dříve zachovali.
- Voláním funkce EvtCreateBookmark vytvořte záložku. Předejte XML řetězec jako argument.
Následující postup popisuje použití záložky v dotazu.
Použití záložky v dotazu
- Zavoláním funkce EvtQuery získáte události, které odpovídají vašemu dotazu.
- Volejte funkci EvtSeek, která hledá událost v záložkách. Předejte popisovač záložkě a příznak EvtSeekRelativeToBookmark.
- Voláním funkce EvtNext ve smyčce vytvořte výčet událostí, které začínají po události záložky (v závislosti na posunu zadaném v EvtSeek).
Příklad najdete v tématu Použití záložky v dotazu.
Následující postup popisuje, jak používat záložku v předplatném.
Použití záložky v předplatném
- Voláním funkce EvtSubscribe se přihlaste k odběru událostí, které odpovídají vašemu dotazu. Předejte popisovač záložkě a příznak EvtSubscribeStartAfterBookmark.
- Pokud jste implementovali funkci EVT_SUBSCRIBE_CALLBACK, vaše zpětná volání obdrží události, které začínají poté, co začala událost označená záložkou.
- Pokud jste neimplementovali zpětné volání, zavolejte funkci EvtNext ve smyčce a vytvořte výčet událostí, které začínají po události záložky.
Příklad najdete v tématu Použití záložky v předplatném.
Použití záložky v dotazu
Následující příklad ukazuje, jak použít záložku v dotazu. Příklad rozvíjí příklad v Dotazování na události.
// Enumerate all the events in the result set beginning with the bookmarked event.
DWORD PrintResults(EVT_HANDLE hResults)
{
DWORD status = ERROR_SUCCESS;
EVT_HANDLE hEvents[ARRAY_SIZE];
DWORD dwReturned = 0;
LPWSTR pwsBookmarkXml = NULL;
EVT_HANDLE hBookmark = NULL;
// Get the persisted bookmark XML string.
pwsBookmarkXml = GetBookmarkedString();
// If the bookmark string was persisted, create a bookmark and
// seek to the bookmarked event in the result set.
if (pwsBookmarkXml)
{
hBookmark = EvtCreateBookmark(pwsBookmarkXml);
if (NULL == hBookmark)
{
wprintf(L"EvtCreateBookmark failed with %lu\n", GetLastError());
goto cleanup;
}
if (!EvtSeek(hResults, 1, hBookmark, 0, EvtSeekRelativeToBookmark))
{
wprintf(L"EvtSeek failed with %lu\n", GetLastError());
goto cleanup;
}
}
// Enumerate the events in the result set after the bookmarked event.
while (true)
{
if (!EvtNext(hResults, ARRAY_SIZE, hEvents, INFINITE, 0, &dwReturned))
{
if (ERROR_NO_MORE_ITEMS != (status = GetLastError()))
{
wprintf(L"EvtNext failed with %lu\n", status);
}
goto cleanup;
}
for (DWORD i = 0; i < dwReturned; i++)
{
if (status = PrintEvent(hEvents[i]))
{
EvtClose(hEvents[i]);
hEvents[i] = NULL;
}
else
{
goto cleanup;
}
}
}
cleanup:
if (ERROR_NO_MORE_ITEMS == status)
{
// Get the last event in the result set, use it to create a
// bookmark, render the bookmark as an XML string, and persist the string.
if (ERROR_SUCCESS != (status = SaveBookmark(hResults)))
wprintf(L"\nFailed to save bookmark\n");
}
else
{
for (DWORD i = 0; i < dwReturned; i++)
{
if (NULL != hEvents[i])
EvtClose(hEvents[i]);
}
}
if (pwsBookmarkXml)
free(pwsBookmarkXml);
return status;
}
// Get the bookmark XML string from wherever you persisted it.
LPWSTR GetBookmarkedString(void)
{
LPWSTR pwsBookmarkXML = NULL;
// TODO: Add the code to get the bookmark XML string from storage.
return pwsBookmarkXML;
}
// Persist the bookmark XML string. This example assumes that we've read through
// the result set and are persisting the last event as the bookmark.
DWORD SaveBookmark(EVT_HANDLE hResults)
{
DWORD status = ERROR_SUCCESS;
DWORD dwBufferSize = 0;
DWORD dwBufferUsed = 0;
DWORD dwPropertyCount = 0;
DWORD dwReturned = 0;
LPWSTR pBookmarkXml = NULL;
EVT_HANDLE hBookmark = NULL;
EVT_HANDLE hEvent = NULL;
// Seek to the last event in the result set and get the event.
if (!EvtSeek(hResults, 0, NULL, 0, EvtSeekRelativeToLast))
{
wprintf(L"EvtSeek failed with %lu\n", status = GetLastError());
goto cleanup;
}
if (!EvtNext(hResults, 1, &hEvent, INFINITE, 0, &dwReturned))
{
wprintf(L"EvtNext failed with %lu\n", status = GetLastError());
goto cleanup;
}
// Create a bookmark and update it with the last event in the result set.
hBookmark = EvtCreateBookmark(NULL);
if (NULL == hBookmark)
{
wprintf(L"EvtCreateBookmark failed with %lu\n", GetLastError());
goto cleanup;
}
if (!EvtUpdateBookmark(hBookmark, hEvent))
{
wprintf(L"EvtUpdateBookmark failed with %lu\n", GetLastError());
goto cleanup;
}
// Render the bookmark as an XML string that you can then persist.
if (!EvtRender(NULL, hBookmark, EvtRenderBookmark, dwBufferSize, pBookmarkXml, &dwBufferUsed, &dwPropertyCount))
{
if (ERROR_INSUFFICIENT_BUFFER == (status = GetLastError()))
{
dwBufferSize = dwBufferUsed;
pBookmarkXml = (LPWSTR)malloc(dwBufferSize);
if (pBookmarkXml)
{
EvtRender(NULL, hBookmark, EvtRenderBookmark, dwBufferSize, pBookmarkXml, &dwBufferUsed, &dwPropertyCount);
}
else
{
wprintf(L"malloc failed\n");
status = ERROR_OUTOFMEMORY;
goto cleanup;
}
}
if (ERROR_SUCCESS != (status = GetLastError()))
{
wprintf(L"EvtRender failed with %d\n", GetLastError());
goto cleanup;
}
}
// TODO: Add code to persist bookmark XML string.
cleanup:
if (pBookmarkXml)
free(pBookmarkXml);
if (hBookmark)
EvtClose(hBookmark);
if (hEvent)
EvtClose(hEvent);
return status;
}
Použití záložky v předplatném
Následující příklad ukazuje, jak použít záložku v nabízeném předplatném.
#include <windows.h>
#include <conio.h>
#include <stdio.h>
#include <winevt.h>
#pragma comment(lib, "wevtapi.lib")
DWORD WINAPI SubscriptionCallback(EVT_SUBSCRIBE_NOTIFY_ACTION action, PVOID pContext, EVT_HANDLE hEvent);
DWORD PrintEvent(EVT_HANDLE hEvent);
EVT_HANDLE GetBookmark();
DWORD SaveBookmark(EVT_HANDLE hBookmark);
void main(void)
{
DWORD status = ERROR_SUCCESS;
EVT_HANDLE hSubscription = NULL;
EVT_HANDLE hBookmark = NULL;
LPWSTR pwsPath = L"<channel name goes here>";
LPWSTR pwsQuery = L"<xpath query goes here>";
// Get the saved bookmark.
hBookmark = GetBookmark();
// Subscribe to existing and furture events beginning with the bookmarked event.
// If the bookmark has not been persisted, pass an empty bookmark and the subscription
// will begin with the second event that matches the query criteria.
hSubscription = EvtSubscribe(NULL, NULL, pwsPath, pwsQuery, hBookmark, (PVOID)hBookmark,
(EVT_SUBSCRIBE_CALLBACK)SubscriptionCallback, EvtSubscribeStartAfterBookmark);
if (NULL == hSubscription)
{
wprintf(L"EvtSubscribe failed with %lu.\n", GetLastError());
goto cleanup;
}
wprintf(L"Hit any key to quit\n\n");
while (!_kbhit())
Sleep(10);
status = SaveBookmark(hBookmark);
cleanup:
if (hSubscription)
EvtClose(hSubscription);
if (hBookmark)
EvtClose(hBookmark);
}
// The callback that receives the events that match the query criteria. Use the
// context parameter to pass the handle to the bookmark, so you can update the bookmark
// with each event that you receive.
DWORD WINAPI SubscriptionCallback(EVT_SUBSCRIBE_NOTIFY_ACTION action, PVOID pContext, EVT_HANDLE hEvent)
{
DWORD status = ERROR_SUCCESS;
EVT_HANDLE hBookmark = (EVT_HANDLE)pContext;
switch(action)
{
// You should only get the EvtSubscribeActionError action if your subscription flags
// includes EvtSubscribeStrict and the channel contains missing event records.
case EvtSubscribeActionError:
if (ERROR_EVT_QUERY_RESULT_STALE == (DWORD)hEvent)
{
wprintf(L"The subscription callback was notified that event records are missing.\n");
// Handle if this is an issue for your application.
}
else
{
wprintf(L"The subscription callback received the following Win32 error: %lu\n", (DWORD)hEvent);
}
break;
case EvtSubscribeActionDeliver:
if (ERROR_SUCCESS != (status = PrintEvent(hEvent)))
{
goto cleanup;
}
if (!EvtUpdateBookmark(hBookmark, hEvent))
{
wprintf(L"EvtUpdateBookmark failed with %lu\n", status = GetLastError());
goto cleanup;
}
break;
default:
wprintf(L"SubscriptionCallback: Unknown action.\n");
}
cleanup:
if (ERROR_SUCCESS != status)
{
// End subscription - Use some kind of IPC mechanism to signal
// your application to close the subscription handle.
}
return status; // The service ignores the returned status.
}
EVT_HANDLE GetBookmark(void)
{
DWORD status = ERROR_SUCCESS;
EVT_HANDLE hBookmark = NULL;
LPWSTR pBookmarkXml = NULL;
// Set pBookmarkXml to the XML string that you persisted in SaveBookmark.
hBookmark = EvtCreateBookmark(pBookmarkXml);
if (NULL == hBookmark)
{
wprintf(L"EvtCreateBookmark failed with %lu\n", GetLastError());
goto cleanup;
}
cleanup:
if (pBookmarkXml)
free(pBookmarkXml);
return hBookmark;
}
DWORD SaveBookmark(EVT_HANDLE hBookmark)
{
DWORD status = ERROR_SUCCESS;
DWORD dwBufferSize = 0;
DWORD dwBufferUsed = 0;
DWORD dwPropertyCount = 0;
LPWSTR pBookmarkXml = NULL;
if (!EvtRender(NULL, hBookmark, EvtRenderBookmark, dwBufferSize, pBookmarkXml, &dwBufferUsed, &dwPropertyCount))
{
if (ERROR_INSUFFICIENT_BUFFER == (status = GetLastError()))
{
dwBufferSize = dwBufferUsed;
pBookmarkXml = (LPWSTR)malloc(dwBufferSize);
if (pBookmarkXml)
{
EvtRender(NULL, hBookmark, EvtRenderBookmark, dwBufferSize, pBookmarkXml, &dwBufferUsed, &dwPropertyCount);
}
else
{
wprintf(L"malloc failed\n");
status = ERROR_OUTOFMEMORY;
goto cleanup;
}
}
if (ERROR_SUCCESS != (status = GetLastError()))
{
wprintf(L"EvtRender failed with %d\n", status);
goto cleanup;
}
}
// Persist bookmark to a file or the registry.
cleanup:
if (pBookmarkXml)
free(pBookmarkXml);
return status;
}
// Render the event as an XML string and print it.
DWORD PrintEvent(EVT_HANDLE hEvent)
{
DWORD status = ERROR_SUCCESS;
DWORD dwBufferSize = 0;
DWORD dwBufferUsed = 0;
DWORD dwPropertyCount = 0;
LPWSTR pRenderedContent = NULL;
if (!EvtRender(NULL, hEvent, EvtRenderEventXml, dwBufferSize, pRenderedContent, &dwBufferUsed, &dwPropertyCount))
{
if (ERROR_INSUFFICIENT_BUFFER == (status = GetLastError()))
{
dwBufferSize = dwBufferUsed;
pRenderedContent = (LPWSTR)malloc(dwBufferSize);
if (pRenderedContent)
{
EvtRender(NULL, hEvent, EvtRenderEventXml, dwBufferSize, pRenderedContent, &dwBufferUsed, &dwPropertyCount);
}
else
{
wprintf(L"malloc failed\n");
status = ERROR_OUTOFMEMORY;
goto cleanup;
}
}
if (ERROR_SUCCESS != (status = GetLastError()))
{
wprintf(L"EvtRender failed with %d\n", status);
goto cleanup;
}
}
wprintf(L"%s\n\n", pRenderedContent);
cleanup:
if (pRenderedContent)
free(pRenderedContent);
return status;
}