Adding an Event Source to a Collector Initiated Subscription
To receive a forwarded event from an event subscription, you can create a collector-initiated subscription on the local computer. For more information about how to create a collector initiated subscription, see the C++ code example shown in Creating an Event Collector Subscription.
After a collector-initiated subscription has been created, you can add event sources to the subscription. You must add at least one event source to a subscription to collect events.
Note
You can use this code example to add an event source to a subscription or you can type the following command at the command prompt:
wecutil ss SubscriptionName **/esa:**EventSourceAddress /aes /ese
EventSourceAddress can be either localhost for the local computer or a fully qualified domain name for a remote computer.
For more information about how to add event sources to a source initiated subscription, see Setting up a Source Initiated Subscription.
This example follows a series of steps to add an event source to a collector initiated subscription.
To add an event source to a collector initiated subscription
- Open the existing subscription by providing the subscription name and access rights as parameters to the EcOpenSubscription function. For more information about access rights, see Windows Event Collector Constants.
- Get the event sources array of the subscription by calling the EcGetSubscriptionProperty function. For more information about subscription properties that can be retrieved, see the EC_SUBSCRIPTION_PROPERTY_ID enumeration.
- Add a new event source to the event sources array of the subscription by calling the EcInsertObjectArrayElement function.
- Set the event source properties by calling the EcSetObjectArrayProperty function. The EcSubscriptionEventSourceAddress property is either set to an address for the local computer (Localhost) or to a fully qualified domain name for a remote computer. For more information about event source properties that can be set, see the EC_SUBSCRIPTION_PROPERTY_ID enumeration.
- Save the subscription by calling the EcSaveSubscription function.
- Close the subscription by calling the EcClose function.
The following C++ code example shows how to add an event source to a collector initiated subscription:
#include <windows.h>
#include <iostream>
using namespace std;
#include <EvColl.h>
#include <vector>
#include <string>
#include <strsafe.h>
#pragma comment(lib, "wecapi.lib")
DWORD GetProperty(EC_HANDLE hSubscription,
EC_SUBSCRIPTION_PROPERTY_ID propID,
DWORD flags,
std::vector<BYTE>& buffer,
PEC_VARIANT& vProperty);
void __cdecl wmain()
{
EC_HANDLE hSubscription;
std::wstring eventSource = L"localhost";
BOOL status = true;
std::wstring eventSourceUserName;
std::wstring eventSourcePassword;
LPCWSTR lpSubname = L"TestSubscription-CollectorInitiated";
DWORD dwEventSourceCount;
DWORD dwRetVal = ERROR_SUCCESS;
PEC_VARIANT vEventSource = NULL;
std::vector<BYTE> buffer;
LPVOID lpwszBuffer;
EC_VARIANT vProperty;
// Create a handle to access the event sources array.
EC_OBJECT_ARRAY_PROPERTY_HANDLE hArray = NULL;
// Step 1: Open an existing subscription.
hSubscription = EcOpenSubscription( lpSubname,
EC_READ_ACCESS | EC_WRITE_ACCESS,
EC_OPEN_EXISTING);
if (!hSubscription)
{
dwRetVal = GetLastError();
goto Cleanup;
}
// Step 2: Get the event sources array to add a new event
// source to the subscription.
dwRetVal = GetProperty(hSubscription,
EcSubscriptionEventSources,
0,
buffer,
vEventSource);
if (ERROR_SUCCESS != dwRetVal)
{
goto Cleanup;
}
// Ensure that a handle to the event sources array has been obtained.
if (vEventSource->Type != EcVarTypeNull &&
vEventSource->Type != EcVarObjectArrayPropertyHandle)
{
dwRetVal = ERROR_INVALID_DATA;
goto Cleanup;
}
hArray = (vEventSource->Type == EcVarTypeNull)? NULL:
vEventSource->PropertyHandleVal;
if(!hArray)
{
dwRetVal = ERROR_INVALID_DATA;
goto Cleanup;
}
if (!EcGetObjectArraySize(hArray, &dwEventSourceCount))
{
dwRetVal = GetLastError();
goto Cleanup;
}
// Step 3: Add a new event source to the event source array.
if (!EcInsertObjectArrayElement(hArray,
dwEventSourceCount))
{
dwRetVal = GetLastError();
goto Cleanup;
}
// Step 4: Set the properties of the event source
// Set the EventSourceAddress property that specifies the address
// of the event forwarding computer, this property can be localhost
// or a fully-qualified domain name.
vProperty.Type = EcVarTypeString;
vProperty.StringVal = eventSource.c_str();
if (!EcSetObjectArrayProperty( hArray,
EcSubscriptionEventSourceAddress,
dwEventSourceCount,
0,
&vProperty))
{
dwRetVal = GetLastError();
goto Cleanup;
}
// Get the credentials.
wcout << "Enter credentials used to connect to the event source " <<
eventSource << ". " << endl <<
"Enter user name: " << endl;
wcin >> eventSourceUserName;
cout << "Enter password: " << endl;
wchar_t c;
while( (c = _getwch()) && c != '\n' && c != '\r' && eventSourcePassword.length() < 512)
{eventSourcePassword.append(1, c);}
// Set the EventSourceUserName property that specifies the user
// that can retrieve events from the event source.
if (eventSourceUserName.length() > 0)
{
vProperty.Type = EcVarTypeString;
vProperty.StringVal = eventSourceUserName.c_str();
if (!EcSetObjectArrayProperty(hArray,
EcSubscriptionEventSourceUserName,
dwEventSourceCount,
0,
&vProperty))
{
dwRetVal = GetLastError();
goto Cleanup;
}
// Set the EventSourcePassword property that defines the password
// for the previously-defined user.
vProperty.StringVal = (eventSourcePassword.length() > 0) ?
eventSourcePassword.c_str() : L"";
if (!EcSetObjectArrayProperty(hArray,
EcSubscriptionEventSourcePassword,
dwEventSourceCount,
0,
&vProperty))
{
dwRetVal = GetLastError();
goto Cleanup;
}
}
// When you have finished using the credentials,
// erase them.
eventSourceUserName.erase();
eventSourcePassword.erase();
// Set the EventSourceEnabled property that enables the event source
// to forward events.
vProperty.Type = EcVarTypeBoolean;
vProperty.BooleanVal = status;
if (!EcSetObjectArrayProperty(hArray,
EcSubscriptionEventSourceEnabled,
dwEventSourceCount,
0,
&vProperty))
{
dwRetVal = GetLastError();
goto Cleanup;
}
// Step 5: Save the subscription to enable the event source.
if (!EcSaveSubscription(hSubscription, NULL))
{
dwRetVal = GetLastError();
goto Cleanup;
}
// Step 6: Close the subscription.
Cleanup:
if (hArray)
EcClose(hArray);
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\n Error Code from FormatMessage: %u\n", dwRetVal, GetLastError());
return;
}
wprintf(L"\nFailed to Perform Operation. Error Code: %u\n 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;
}
Related topics