Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Subskrypcje inicjowane przez źródło umożliwiają zdefiniowanie subskrypcji na komputerze modułu zbierającego zdarzenia bez definiowania komputerów źródłowych zdarzeń, a następnie można skonfigurować wiele zdalnych komputerów źródłowych zdarzeń (przy użyciu ustawienia zasad grupy) w celu przekazywania zdarzeń do komputera modułu zbierającego zdarzenia. Aby komputer lokalny mógł subskrybować zdarzenia, a komputer zdalny może przekazywać zdarzenia, należy skonfigurować oba komputery na potrzeby zbierania zdarzeń i przekazywania zdarzeń. Aby uzyskać więcej informacji na temat konfigurowania komputerów, zobacz Konfigurowanie subskrypcji inicjowanej przez źródło.
Poniższy przykład kodu jest zgodny z serią kroków tworzenia subskrypcji inicjowanej przez źródło, w której źródła zdarzeń znajdują się w tej samej domenie co komputer modułu zbierającego zdarzenia.
Aby programowo utworzyć subskrypcję zainicjowaną przez źródło
- Otwórz subskrypcję, podając nazwę subskrypcji i prawa dostępu jako parametry funkcji EcOpenSubscription. Aby uzyskać więcej informacji na temat praw dostępu, zobacz Stałe modułu zbierającego zdarzenia systemu Windows.
- Ustaw właściwości subskrypcji, wywołując funkcję EcSetSubscriptionProperty. Aby uzyskać więcej informacji na temat właściwości subskrypcji, które można ustawić, zobacz wyliczenie EC_SUBSCRIPTION_PROPERTY_ID.
- Zapisz subskrypcję, wywołując funkcję EcSaveSubscription.
- Zamknij subskrypcję, wywołując funkcję EcClose.
W poniższym przykładzie języka C++ pokazano, jak utworzyć subskrypcję zainicjowaną przez źródło:
#include <windows.h>
#include <iostream>
using namespace std;
#include <string>
#include <xstring>
#include <conio.h>
#include <EvColl.h>
#include <vector>
#include <wincred.h>
#pragma comment(lib, "credui.lib")
#pragma comment(lib, "wecapi.lib")
// Track properties of the Subscription.
typedef struct _SUBSCRIPTION_SOURCE_INITIATED
{
std::wstring Name;
EC_SUBSCRIPTION_TYPE SubscriptionType;
std::wstring Description;
BOOL SubscriptionStatus;
std::wstring URI;
EC_SUBSCRIPTION_CONFIGURATION_MODE ConfigMode;
EC_SUBSCRIPTION_DELIVERY_MODE DeliveryMode;
DWORD MaxItems;
DWORD MaxLatencyTime;
DWORD HeartbeatInerval;
time_t Expires;
std::wstring Query;
BOOL ReadExistingEvents;
std::wstring TransportName;
EC_SUBSCRIPTION_CONTENT_FORMAT ContentFormat;
std::wstring DestinationLog;
std::wstring AllowedSourceNonDomainComputers;
std::wstring AllowedSourceDomainComputers;
} SUBSCRIPTION_SOURCE_INITIATED;
// Subscription Information
DWORD GetProperty(EC_HANDLE hSubscription,
EC_SUBSCRIPTION_PROPERTY_ID propID,
DWORD flags,
std::vector<BYTE>& buffer,
PEC_VARIANT& vProperty);
void __cdecl wmain()
{
LPVOID lpwszBuffer;
DWORD dwRetVal = ERROR_SUCCESS;
EC_HANDLE hSubscription;
EC_VARIANT vPropertyValue;
std::vector<BYTE> buffer;
PEC_VARIANT vProperty = NULL;
SUBSCRIPTION_SOURCE_INITIATED sub;
sub.Name = L"TestSubscription-SourceInitiated";
sub.SubscriptionType = EcSubscriptionTypeSourceInitiated;
sub.Description = L"A subscription that collects events that are published in\n" \
L"the Microsoft-Windows-TaskScheduler/Operational log and forwards them \n" \
L"to the ForwardedEvents log.";
sub.URI = L"http://schemas.microsoft.com/wbem/wsman/1/windows/EventLog";
sub.Query = L"<QueryList>" \
L"<Query Path=\"Microsoft-Windows-TaskScheduler/Operational\">" \
L"<Select>*</Select>" \
L"</Query>" \
L"</QueryList>";
sub.DestinationLog = L"ForwardedEvents";
sub.ConfigMode = EcConfigurationModeCustom;
sub.MaxItems = 5;
sub.MaxLatencyTime = 1000;
sub.HeartbeatInerval = 60000;
sub.DeliveryMode = EcDeliveryModePush;
sub.ContentFormat = EcContentFormatRenderedText;
sub.ReadExistingEvents = true;
sub.SubscriptionStatus = true;
sub.TransportName = L"http";
// This SDDL grants members of the Domain Computers domain group as well
// as members of the Network Service group (for the local forwarder),
// the ability to raise events for this subscription.
sub.AllowedSourceDomainComputers = L"O:NSG:NSD:(A;;GA;;;DC)(A;;GA;;;NS)";
// Step 1: Open the Event Collector subscription.
hSubscription = EcOpenSubscription(sub.Name.c_str(),
EC_READ_ACCESS | EC_WRITE_ACCESS,
EC_CREATE_NEW);
if ( !hSubscription)
{
dwRetVal = GetLastError();
goto Cleanup;
}
// Step 2: Define the subscription properties.
// Set the subscription type property (collector initiated).
vPropertyValue.Type = EcVarTypeUInt32;
vPropertyValue.UInt32Val = sub.SubscriptionType;
if (!EcSetSubscriptionProperty(hSubscription,
EcSubscriptionType,
NULL,
&vPropertyValue))
{
dwRetVal = GetLastError();
goto Cleanup;
}
// Set the Description property that contains a description
// of the subscription.
vPropertyValue.Type = EcVarTypeString;
vPropertyValue.StringVal = sub.Description.c_str();
if (!EcSetSubscriptionProperty(hSubscription,
EcSubscriptionDescription,
NULL,
&vPropertyValue))
{
dwRetVal = GetLastError();
goto Cleanup;
}
// Set the URI property that specifies the URI of all the event sources.
vPropertyValue.Type = EcVarTypeString;
vPropertyValue.StringVal = sub.URI.c_str();
if (!EcSetSubscriptionProperty(hSubscription,
EcSubscriptionURI,
NULL,
&vPropertyValue))
{
dwRetVal = GetLastError();
goto Cleanup;
}
// Set the Query property that defines the query used by the event
// source to select events that are forwarded to the event collector.
vPropertyValue.Type = EcVarTypeString;
vPropertyValue.StringVal = sub.Query.c_str();
if (!EcSetSubscriptionProperty(hSubscription,
EcSubscriptionQuery,
NULL,
&vPropertyValue))
{
dwRetVal = GetLastError();
goto Cleanup;
}
// Set the Log File property that specifies where the forwarded events
// will be stored.
vPropertyValue.Type = EcVarTypeString;
vPropertyValue.StringVal = sub.DestinationLog.c_str();
if (!EcSetSubscriptionProperty(hSubscription,
EcSubscriptionLogFile,
NULL,
&vPropertyValue))
{
dwRetVal = GetLastError();
goto Cleanup;
}
// Set the ConfigurationMode property that specifies the mode in which events
// are delivered.
vPropertyValue.Type = EcVarTypeUInt32;
vPropertyValue.UInt32Val = sub.ConfigMode;
if (!EcSetSubscriptionProperty(hSubscription,
EcSubscriptionConfigurationMode,
NULL,
&vPropertyValue))
{
dwRetVal = GetLastError();
goto Cleanup;
}
// If the Configuration Mode is Custom, set the DeliveryMode, DeliveryMaxItems,
// HeartbeatInterval, and DeliveryMaxLatencyTime properties.
if ( sub.ConfigMode == EcConfigurationModeCustom)
{
// Set the DeliveryMode property that defines how events are delivered.
// Events can be delivered through either a push or pull model.
vPropertyValue.Type = EcVarTypeUInt32;
vPropertyValue.UInt32Val = sub.DeliveryMode;
if (!EcSetSubscriptionProperty(hSubscription,
EcSubscriptionDeliveryMode,
NULL,
&vPropertyValue))
{
dwRetVal = GetLastError();
goto Cleanup;
}
// Set the DeliveryMaxItems property that specifies the maximum number of
// events that can be batched when forwarded from the event sources.
vPropertyValue.Type = EcVarTypeUInt32;
vPropertyValue.UInt32Val = sub.MaxItems;
if (!EcSetSubscriptionProperty(hSubscription,
EcSubscriptionDeliveryMaxItems,
NULL,
&vPropertyValue))
{
dwRetVal = GetLastError();
goto Cleanup;
}
// Set the HeartbeatInterval property that defines the time interval, in
// seconds, that is observed between the heartbeat messages.
vPropertyValue.Type = EcVarTypeUInt32;
vPropertyValue.UInt32Val = sub.HeartbeatInerval;
if (!EcSetSubscriptionProperty(hSubscription,
EcSubscriptionHeartbeatInterval,
NULL,
&vPropertyValue))
{
dwRetVal = GetLastError();
goto Cleanup;
}
// Set the DeliveryMaxLatencyTime property that specifies how long, in
// seconds, the event source should wait before forwarding events.
vPropertyValue.Type = EcVarTypeUInt32;
vPropertyValue.UInt32Val = sub.MaxLatencyTime;
if (!EcSetSubscriptionProperty(hSubscription,
EcSubscriptionDeliveryMaxLatencyTime,
NULL,
&vPropertyValue))
{
dwRetVal = GetLastError();
goto Cleanup;
}
}
// Set the ContentFormat property that specifies the format for the event content.
vPropertyValue.Type = EcVarTypeUInt32;
vPropertyValue.UInt32Val = sub.ContentFormat;
if (!EcSetSubscriptionProperty(hSubscription,
EcSubscriptionContentFormat,
0,
&vPropertyValue))
{
dwRetVal = GetLastError();
goto Cleanup;
}
// Set the ReadExistingEvents property that is used to enable or disable whether
// existing events are forwarded.
vPropertyValue.Type = EcVarTypeBoolean;
vPropertyValue.BooleanVal = sub.ReadExistingEvents;
if (!EcSetSubscriptionProperty(hSubscription,
EcSubscriptionReadExistingEvents,
0,
&vPropertyValue))
{
dwRetVal = GetLastError();
goto Cleanup;
}
// Set the Enabled property that is used to enable or disable the subscription
// or to obtain the current status of a subscription.
vPropertyValue.Type = EcVarTypeBoolean;
vPropertyValue.BooleanVal = sub.SubscriptionStatus;
if (!EcSetSubscriptionProperty(hSubscription,
EcSubscriptionEnabled,
0,
&vPropertyValue))
{
dwRetVal = GetLastError();
goto Cleanup;
}
// Set the TransportName property that determines the type of
// transport used by the subscription.
vPropertyValue.Type = EcVarTypeString;
vPropertyValue.StringVal = sub.TransportName.c_str();
if (!EcSetSubscriptionProperty(hSubscription,
EcSubscriptionTransportName,
0,
&vPropertyValue))
{
dwRetVal = GetLastError();
goto Cleanup;
}
// Required:
// Set the AllowedSourceDomainComputers property to the specified SDDL.
vPropertyValue.Type = EcVarTypeString;
vPropertyValue.StringVal = sub.AllowedSourceDomainComputers.c_str();
if (!EcSetSubscriptionProperty(hSubscription,
EcSubscriptionAllowedSourceDomainComputers,
0,
&vPropertyValue))
{
dwRetVal = GetLastError();
goto Cleanup;
}
//----------------------------------------------
// Step 3: Save the subscription.
// Save the subscription with the associated properties
// This will create the subscription and store it in the
// subscription repository
if( !EcSaveSubscription(hSubscription, NULL) )
{
dwRetVal = GetLastError();
goto Cleanup;
}
// Step 4: Close the subscription.
Cleanup:
if(hSubscription)
EcClose(hSubscription);
if (dwRetVal != ERROR_SUCCESS)
{
FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dwRetVal,
0,
(LPWSTR) &lpwszBuffer,
0,
NULL);
if (!lpwszBuffer)
{
wprintf(L"Failed to FormatMessage. Operation Error Code: %u." \
L"Error Code from FormatMessage: %u\n", dwRetVal, GetLastError());
return;
}
wprintf(L"\nFailed to Perform Operation.\nError Code: %u\n" \
L" Error Message: %s\n", dwRetVal, lpwszBuffer);
LocalFree(lpwszBuffer);
}
}
DWORD GetProperty(EC_HANDLE hSubscription,
EC_SUBSCRIPTION_PROPERTY_ID propID,
DWORD flags,
std::vector<BYTE>& buffer,
PEC_VARIANT& vProperty)
{
DWORD dwBufferSize, dwRetVal = ERROR_SUCCESS;
buffer.resize(sizeof(EC_VARIANT));
if (!hSubscription)
return ERROR_INVALID_PARAMETER;
// Get the value for the specified property.
if (!EcGetSubscriptionProperty(hSubscription,
propID,
flags,
(DWORD) buffer.size(),
(PEC_VARIANT)&buffer[0],
&dwBufferSize) )
{
dwRetVal = GetLastError();
if (ERROR_INSUFFICIENT_BUFFER == dwRetVal)
{
dwRetVal = ERROR_SUCCESS;
buffer.resize(dwBufferSize);
if (!EcGetSubscriptionProperty(hSubscription,
propID,
flags,
(DWORD) buffer.size(),
(PEC_VARIANT)&buffer[0],
&dwBufferSize))
{
dwRetVal = GetLastError();
}
}
}
if (dwRetVal == ERROR_SUCCESS)
{
vProperty = (PEC_VARIANT) &buffer[0];
}
else
{
vProperty = NULL;
}
return dwRetVal;
}
Sprawdź, czy subskrypcja działa prawidłowo
Na komputerze modułu zbierającego zdarzenia wykonaj następującą procedurę:
Uruchom następujące polecenie w wierszu polecenia z uprawnieniami administratora, aby uzyskać status działania subskrypcji:
wecutil gr<subscriptionID>
Sprawdź, czy źródło zdarzeń zostało połączone. Może być konieczne poczekanie na przekroczenie interwału odświeżania określonego w zasadach po utworzeniu subskrypcji, aby źródło zdarzeń było połączone.
Uruchom następujące polecenie, aby uzyskać informacje o subskrypcji:
wecutil gs<subscriptionID>
Pobierz wartość DeliveryMaxItems z informacji o subskrypcji.
Na komputerze źródłowym zdarzeń wywołaj zdarzenia zgodne z zapytaniem z subskrypcji zdarzeń. Liczba zdarzeń w parametrze "DeliveryMaxItems" musi zostać zwiększona, aby zdarzenia mogły zostać przekazane.
Na komputerze modułu zbierającego zdarzenia sprawdź, czy zdarzenia zostały przekazane do dziennika ForwardedEvents lub do dziennika określonego w subskrypcji.
Tematy pokrewne