Peristiwa Marka Buku
Bookmark mengidentifikasi peristiwa dalam saluran atau file log. Anda bisa menggunakan marka buku saat mengkueri atau berlangganan peristiwa untuk mulai membaca peristiwa dari peristiwa yang diberi marka buku tersebut. Biasanya Anda membuat bookmark peristiwa terakhir dalam tataan hasil (dengan asumsi Bahwa Anda telah menghitung semua peristiwa dalam tataan hasil).
Prosedur berikut ini menjelaskan cara membuat bookmark dari peristiwa.
Untuk membuat bookmark dari acara
- Panggil fungsi EvtCreateBookmark untuk membuat bookmark. Teruskan NULL untuk argumen .
- Panggil fungsi EvtUpdateBookmark untuk memperbarui marka buku dengan peristiwa. Teruskan handel ke peristiwa sebagai argumen.
- Panggil fungsi EvtRender untuk membuat string XML yang mewakili bookmark. Teruskan EvtRenderBookmark sebagai bendera penyajian.
- Pertahankan string XML untuk digunakan nanti (misalnya, Anda dapat mempertahankan string XML dalam file atau registri).
Prosedur berikut ini menjelaskan cara membuat bookmark menggunakan string marka buku XML yang dipertahankan dalam prosedur sebelumnya.
Untuk membuat bookmark menggunakan string marka buku XML
- Dapatkan string XML yang mewakili bookmark yang sebelumnya Anda pertahankan.
- Panggil fungsi EvtCreateBookmark untuk membuat bookmark. Teruskan string XML untuk argumen .
Prosedur berikut ini menjelaskan cara menggunakan bookmark dalam kueri.
Untuk menggunakan bookmark dalam kueri
- Panggil fungsi EvtQuery untuk mendapatkan peristiwa yang cocok dengan kueri Anda.
- Panggil fungsi EvtSeek untuk mencari peristiwa yang diberi marka buku. Teruskan handel ke marka buku dan bendera EvtSeekRelativeToBookmark.
- Panggil fungsi EvtNext dalam perulangan untuk menghitung peristiwa yang dimulai setelah peristiwa marka buku (tergantung pada offset yang Anda tentukan di EvtSeek).
Misalnya, lihat Menggunakan bookmark dalam kueri.
Prosedur berikut ini menjelaskan cara menggunakan bookmark dalam langganan.
Untuk menggunakan bookmark dalam langganan
- Panggil fungsi EvtSubscribe untuk berlangganan peristiwa yang cocok dengan kueri Anda. Teruskan handel ke bookmark dan bendera EvtSubscribeStartAfterBookmark.
- Jika Anda menerapkan fungsi EVT_SUBSCRIBE_CALLBACK , panggilan balik Anda akan menerima peristiwa yang dimulai setelah peristiwa bookmark.
- Jika Anda tidak menerapkan panggilan balik, panggil fungsi EvtNext dalam perulangan untuk menghitung peristiwa yang dimulai setelah peristiwa bookmark.
Misalnya, lihat Menggunakan bookmark dalam langganan.
Menggunakan bookmark dalam kueri
Contoh berikut menunjukkan cara menggunakan bookmark dalam kueri. Contohnya meluas pada contoh dalam Mengkueri untuk Peristiwa.
// 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;
}
Menggunakan bookmark dalam langganan
Contoh berikut menunjukkan cara menggunakan bookmark dalam langganan push.
#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;
}