Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Nachdem das System die OpenPerformanceData-Funktion erfolgreich aufgerufen hat, ruft es die CollectPerformanceData-Funktion auf, um die Leistungsindikatorendaten zu sammeln. Wenn der Anbieter die abgefragten Objekte unterstützt, kontaktiert er den Dienst, den Treiber oder die Anwendung, mit der er verknüpft ist, und fragt ihn nach den Leistungsindikatorendaten.
Der pQuery Parameter wird einer der folgenden sein:
- Eine durch Leerzeichen getrennte Liste mit einer oder mehreren Dezimalzahlen: Sammeln Sie Leistungsdaten für alle unterstützten Objekttypen in der Liste.
-
Global: Sammeln Sie Leistungsdaten für alle unterstützten lokalen Objekttypen, mit Ausnahme derjenigen, die in derCostlyKategorie enthalten sind. -
Costly: Sammeln Sie Leistungsdaten für alle unterstützten lokalen Objekttypen, deren Daten in Bezug auf Prozessorzeit oder Speicherauslastung teuer zu erfassen sind. (Veraltet: In dieser Kategorie sollten normalerweise keine Objekttypen vorhanden sein.) -
Foreign: Erfassen von Leistungsdaten für alle unterstützten Remoteobjekttypen. (Veraltet: In dieser Kategorie sollten normalerweise keine Objekttypen vorhanden sein.) -
MetadataGlobal(neu): Sammeln Sie Metadaten für alle unterstützten lokalen Objekttypen, mit Ausnahme derjenigen, die in derCostlyKategorie enthalten sind. Dies ist identisch mitGlobalaußer dassNumInstancesentweder aufPERF_METADATA_MULTIPLE_INSTANCESoderPERF_METADATA_NO_INSTANCESgesetzt werden sollte, und das Ergebnis sollte keinePERF_INSTANCE_DEFINITIONBlöcke enthalten. -
MetadataCostly(neu): Sammeln Sie Metadaten für alle unterstützten lokalen Objekttypen, die in derCostlyKategorie enthalten sind. Dies ist identisch mitCostlymit der Ausnahme, dassNumInstancesentweder aufPERF_METADATA_MULTIPLE_INSTANCESoderPERF_METADATA_NO_INSTANCESgesetzt werden sollte, und das Ergebnis sollte keinePERF_INSTANCE_DEFINITION-Blöcke enthalten.
Die MetadataGlobal Und MetadataCostly Abfragetypen sind neu für Windows 10 20H1 und höher. Windows führt Metadatenabfragen nur aus, wenn Ihr Anbieter einen HKLM\CurrentControlSet\Services\<provider-name>\Performance\Collect Supports Metadata Registrierungswert hinzugefügt hat. Legen Sie den Wert auf 1 fest, um anzugeben, dass Ihr Anbieter sie unterstützt. Metadatenabfragen ermöglichen Windows das Sammeln von Informationen zu unterstützten Leistungsobjekten, ohne datensammlung durchzuführen. Erwägen Sie das Hinzufügen von Unterstützung für Metadatenabfragen zu Ihrem Anbieter, insbesondere, wenn die Datensammlung teuer ist.
Das folgende Beispiel zeigt eine Implementierung der CollectPerformanceData-Funktion . Die Headerdatei, die die Definition der in dieser Funktion verwendeten Leistungsindikatoren enthält, wird in der Implementierung von OpenPerformanceData gezeigt. Wenn Sie diese Funktion mithilfe von C++ implementieren, müssen Sie beim Deklarieren der Funktion unbedingt externes "C" verwenden.
// Callback that the performance service calls when the consumer wants to sample
// your counter data. Get the counter data and return it to the consumer.
extern "C" DWORD APIENTRY CollectPerfData(LPWSTR pQuery,
LPVOID* ppData,
LPDWORD pcbData,
LPDWORD pObjectsReturned)
{
BOOL fQuerySupported = FALSE;
DWORD TotalQuerySize = 0;
PBYTE pObjects = (PBYTE)*ppData; // Used to add counter objects to the buffer.
PEER_INSTANCE inst;
*pObjectsReturned = 0;
if (0 == g_OpenCount) // Open did not successfully initialize
{
*pcbData = 0;
*pObjectsReturned = 0;
return ERROR_SUCCESS;
}
// Confirm that we support the requested objects. The query string is passed
// to this function as it was passed to RegQueryValueEx. For this example,
// it should never be the case that we are being asked for objects that
// we do not support because we included the [objects] section in the .ini file.
fQuerySupported = IsQuerySupported(pQuery, &g_QueriedObjects);
if (fQuerySupported == FALSE)
{
*pcbData = 0;
*pObjectsReturned = 0;
return ERROR_SUCCESS;
}
// If multiple instance objects are queried, you need to discover how many
// instances exist so you can determine the buffer size that the
// query requires. This value can potentially change from query to query.
// The Peer object is a multiple instance object. For this example,
// set the number of instances to 2 if the Peer object was queried.
if (QUERIED_PEER_OBJECT == (g_QueriedObjects & QUERIED_PEER_OBJECT))
{
g_Peer.Object.NumInstances = 2;
g_Peer.Object.TotalByteLength = sizeof(PEER) +
sizeof(PEER_INSTANCE) * g_Peer.Object.NumInstances;
}
// Check pcbData to see if ppData is large enough to hold our counters.
// If the buffer is not large enough, return ERROR_MORE_DATA. This tells
// the calling application to increase the buffer size and query again.
TotalQuerySize = GetQuerySize(g_QueriedObjects);
if (TotalQuerySize > *pcbData)
{
*pcbData = 0;
*pObjectsReturned = 0;
return ERROR_MORE_DATA;
}
else
{
*pcbData = TotalQuerySize;
}
// If the query includes the Transfer object, collect the counter data
// for the Transfer object and copy it to the ppData buffer.
if (QUERIED_TRANSFER_OBJECT == (g_QueriedObjects & QUERIED_TRANSFER_OBJECT))
{
// Add calls to retrieve counter data from the server/driver/application.
// This example hard codes the counter data.
g_Transfer.BytesSentData = 5;
g_Transfer.AvailableBandwidthData = 20;
g_Transfer.TotalBandwidthData = 50;
// Since this is a single instance object, just copy the object
// to the buffer.
memcpy((PTRANSFER)pObjects, &g_Transfer, sizeof(TRANSFER));
pObjects += g_Transfer.Object.TotalByteLength;
(*pObjectsReturned)++;
}
// If the query includes the Peer object, collect the counter data
// for the Peer object and its instances and copy it to the ppData buffer.
if (QUERIED_PEER_OBJECT == (g_QueriedObjects & QUERIED_PEER_OBJECT))
{
// Copy the object and counter definition pieces to the buffer,
// the instance data follows.
memcpy((PPEER)pObjects, &g_Peer, sizeof(PEER));
pObjects += sizeof(PEER);
// Initialize the instance information.
ZeroMemory(&inst, sizeof(PEER_INSTANCE));
inst.Instance.ByteLength = sizeof(PERF_INSTANCE_DEFINITION) + sizeof(inst.InstanceName);
inst.Instance.UniqueID = PERF_NO_UNIQUE_ID;
inst.Instance.NameOffset = sizeof(PERF_INSTANCE_DEFINITION);
inst.CounterBlock.ByteLength = EndOfPeerData;
// Instance-specific data for the first instance. This information is
// hard coded for this example.
inst.Instance.NameLength = sizeof(INSTANCE_NAME_1);
StringCchCopy(inst.InstanceName, MAX_INSTANCE_NAME_LEN+1, INSTANCE_NAME_1);
inst.BytesServedData = 15;
// Copy the instance.
memcpy((PPEER_INSTANCE)pObjects, &inst, sizeof(PEER_INSTANCE));
pObjects += sizeof(PEER_INSTANCE);
// Instance-specific data for the second instance.
inst.Instance.NameLength = sizeof(INSTANCE_NAME_2);
StringCchCopy(inst.InstanceName, MAX_INSTANCE_NAME_LEN+1, INSTANCE_NAME_2);
inst.BytesServedData = 30;
// Copy the instance.
memcpy((PPEER_INSTANCE)pObjects, &inst, sizeof(PEER_INSTANCE));
pObjects += sizeof(PEER_INSTANCE);
(*pObjectsReturned)++;
}
*ppData = (LPVOID)pObjects;
return ERROR_SUCCESS;
}
// Scan the query string to see if we support the objects.
BOOL IsQuerySupported(LPWSTR pQuery, DWORD* pQueriedObjects)
{
BOOL fSupported = FALSE;
WCHAR IndexString[33+1];
LPWSTR pCopy = NULL;
DWORD dwQueryLen = 0;
*pQueriedObjects = 0;
// Copy the query string and make it lowercase.
dwQueryLen = wcslen(pQuery) + 1;
pCopy = new WCHAR[dwQueryLen];
wcscpy_s(pCopy, dwQueryLen, pQuery);
_wcslwr_s(pCopy, dwQueryLen);
if (wcsstr(pCopy, L"global"))
{
fSupported = TRUE;
*pQueriedObjects |= QUERIED_ALL_OBJECTS;
}
else
{
// See if the query contains the index value for
// the Transfer object.
_ultow_s(g_TransferIndex, IndexString, 33, 10);
if (wcsstr(pCopy, IndexString))
{
fSupported = TRUE;
*pQueriedObjects |= QUERIED_TRANSFER_OBJECT;
}
// See if the query contains the index value for
// the Peer object.
_ultow_s(g_PeerIndex, IndexString, 33, 10);
if (wcsstr(pCopy, IndexString))
{
fSupported = TRUE;
*pQueriedObjects |= QUERIED_PEER_OBJECT;
}
}
if (pCopy)
delete pCopy;
return fSupported;
}
// Determine the required buffer size for the query.
DWORD GetQuerySize(DWORD QueriedObjects)
{
DWORD QuerySize = 0;
if (QUERIED_TRANSFER_OBJECT == (QueriedObjects & QUERIED_TRANSFER_OBJECT))
QuerySize = g_Transfer.Object.TotalByteLength;
if (QUERIED_PEER_OBJECT == (g_QueriedObjects & QUERIED_PEER_OBJECT))
QuerySize += g_Peer.Object.TotalByteLength;
return QuerySize;
}