Toegang tot prestatiegegevens in C++
De WMI high-performance API is een reeks interfaces die gegevens ophalen uit prestatiemeteritemsklassen. Voor deze interfaces moet een vernieuwingsfunctie object worden gebruikt om de steekproefsnelheid te verhogen. Zie Accessing Performance Data in Script en WMI-taken: Prestatiemonitoringvoor meer informatie over het gebruik van het updateobject in een script.
In dit onderwerp worden de volgende secties besproken:
- prestatiegegevens vernieuwen
- Enumerators toevoegen aan de WMI Refresher-
- Voorbeeld
- Verwante onderwerpen
Prestatiegegevens vernieuwen
Een vernieuwingsobject verhoogt de prestaties van de gegevensprovider en de client door gegevens op te halen zonder procesgrenzen te overschrijden. Als de client en de server zich op dezelfde computer bevinden, laadt een vernieuwer de hoogwaardige provider intern naar de client en kopieert gegevens rechtstreeks van providerobjecten naar clientobjecten. Als de client en de server zich op verschillende computers bevinden, verhoogt de vernieuwing de prestaties door objecten op de externe computer in de cache op te slaan en minimale gegevenssets naar de client te verzenden.
Een opfrisser ook:
Hiermee wordt een client automatisch opnieuw verbonden met een externe WMI-service wanneer er een netwerkfout optreedt of wordt de externe computer opnieuw opgestart.
Standaard probeert een vernieuwingsfunctie uw toepassing opnieuw te verbinden met de relevante provider met hoge prestaties wanneer een externe verbinding tussen de twee computers mislukt. Als u wilt voorkomen dat er opnieuw verbinding wordt gemaakt, geeft u de vlag WBEM_FLAG_REFRESH_NO_AUTO_RECONNECT door in de methode-aanroep vernieuwen. Scriptclients moeten de eigenschap SWbemRefresher.AutoReconnect instellen op FALSE-.
Laadt meerdere objecten en opsommingen die worden geleverd door dezelfde of verschillende providers.
Hiermee kunt u meerdere objecten, opsommingen of beide toevoegen aan een ververser.
Inventariseert objecten.
Net als andere providers kan een provider met hoge prestaties objecten inventariseren.
Nadat u klaar bent met het schrijven van uw krachtige client, kunt u de reactietijd verbeteren. Omdat de IWbemObjectAccess interface is geoptimaliseerd voor snelheid, is de interface niet intrinsiek threadsafe. Daarom hebt u tijdens een vernieuwingsbewerking geen toegang tot het vernieuwbare object of de opsomming. Als u objecten tussen threads wilt beveiligen tijdens methodeoproepen van IWbemObjectAccess, gebruikt u de methode IWbemObjectAccess::Lock en Unlock methoden. Voor betere prestaties synchroniseert u uw threads, zodat u afzonderlijke threads niet hoeft te vergrendelen. Het verminderen van threads en het synchroniseren van groepen objecten voor vernieuwingsbewerkingen biedt de beste algehele prestaties.
Enumerators toevoegen aan WMI Refresher
Zowel het aantal exemplaren als de gegevens in elke instantie wordt vernieuwd door een opsomming toe te voegen aan de vernieuwingsfunctie, zodat elke aanroep naar IWbemRefresher::Refresh resulteert in een volledige opsomming.
Voor het volgende C++-codevoorbeeld zijn de volgende verwijzingen en #include instructies vereist om correct te compileren.
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
In de volgende procedure wordt getoond hoe u een enumerator toevoegt aan een ververser.
Een enumerator toevoegen aan een refresher
Roep de methode IWbemConfigureRefresher::AddEnum- aan met behulp van het pad naar het vernieuwbare object en de interface IWbemServices.
De vernieuwer retourneert een pointer naar een IWbemHiPerfEnum interface. U kunt de IWbemHiPerfEnum-interface gebruiken om toegang te krijgen tot de objecten in de opsomming.
IWbemHiPerfEnum* pEnum = NULL; long lID; IWbemConfigureRefresher* pConfig; IWbemServices* pNameSpace; // Add an enumerator to the refresher. if (FAILED (hr = pConfig->AddEnum( pNameSpace, L"Win32_PerfRawData_PerfProc_Process", 0, NULL, &pEnum, &lID))) { goto CLEANUP; } pConfig->Release(); pConfig = NULL;
Maak een lus waarmee de volgende acties worden uitgevoerd:
Hiermee vernieuwt u het object met behulp van een aanroep naar IWbemRefresher::Refresh.
Biedt een matrix van IWbemObjectAccess interfaceaanwijzers naar de methode IWbemHiPerfEnum::GetObjects.
Hiermee krijgt u toegang tot de eigenschappen van de enumerator met behulp van de IWbemObjectAccess methoden die aan de GetObjectszijn doorgegeven.
Een eigenschapsgreep kan worden doorgegeven aan elke IWbemObjectAccess exemplaar om de vernieuwde waarde op te halen. De client moet Release aanroepen om de IWbemObjectAccess pointers geretourneerd door GetObjectsvrij te geven.
Voorbeeld
In het volgende C++-codevoorbeeld wordt een klasse met hoge prestaties opgesomd, waarbij de client een eigenschapsgreep ophaalt uit het eerste object en de ingang opnieuw gebruikt voor de rest van de vernieuwingsbewerking. Elke aanroep naar de methode Refresh werkt het aantal exemplaren en de instantiegegevens bij.
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
int __cdecl wmain(int argc, wchar_t* argv[])
{
// To add error checking,
// check returned HRESULT below where collected.
HRESULT hr = S_OK;
IWbemRefresher *pRefresher = NULL;
IWbemConfigureRefresher *pConfig = NULL;
IWbemHiPerfEnum *pEnum = NULL;
IWbemServices *pNameSpace = NULL;
IWbemLocator *pWbemLocator = NULL;
IWbemObjectAccess **apEnumAccess = NULL;
BSTR bstrNameSpace = NULL;
long lID = 0;
long lVirtualBytesHandle = 0;
long lIDProcessHandle = 0;
DWORD dwVirtualBytes = 0;
DWORD dwProcessId = 0;
DWORD dwNumObjects = 0;
DWORD dwNumReturned = 0;
DWORD dwIDProcess = 0;
DWORD i=0;
int x=0;
if (FAILED (hr = CoInitializeEx(NULL,COINIT_MULTITHREADED)))
{
goto CLEANUP;
}
if (FAILED (hr = CoInitializeSecurity(
NULL,
-1,
NULL,
NULL,
RPC_C_AUTHN_LEVEL_NONE,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL, EOAC_NONE, 0)))
{
goto CLEANUP;
}
if (FAILED (hr = CoCreateInstance(
CLSID_WbemLocator,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator,
(void**) &pWbemLocator)))
{
goto CLEANUP;
}
// Connect to the desired namespace.
bstrNameSpace = SysAllocString(L"\\\\.\\root\\cimv2");
if (NULL == bstrNameSpace)
{
hr = E_OUTOFMEMORY;
goto CLEANUP;
}
if (FAILED (hr = pWbemLocator->ConnectServer(
bstrNameSpace,
NULL, // User name
NULL, // Password
NULL, // Locale
0L, // Security flags
NULL, // Authority
NULL, // Wbem context
&pNameSpace)))
{
goto CLEANUP;
}
pWbemLocator->Release();
pWbemLocator=NULL;
SysFreeString(bstrNameSpace);
bstrNameSpace = NULL;
if (FAILED (hr = CoCreateInstance(
CLSID_WbemRefresher,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWbemRefresher,
(void**) &pRefresher)))
{
goto CLEANUP;
}
if (FAILED (hr = pRefresher->QueryInterface(
IID_IWbemConfigureRefresher,
(void **)&pConfig)))
{
goto CLEANUP;
}
// Add an enumerator to the refresher.
if (FAILED (hr = pConfig->AddEnum(
pNameSpace,
L"Win32_PerfRawData_PerfProc_Process",
0,
NULL,
&pEnum,
&lID)))
{
goto CLEANUP;
}
pConfig->Release();
pConfig = NULL;
// Get a property handle for the VirtualBytes property.
// Refresh the object ten times and retrieve the value.
for(x = 0; x < 10; x++)
{
dwNumReturned = 0;
dwIDProcess = 0;
dwNumObjects = 0;
if (FAILED (hr =pRefresher->Refresh(0L)))
{
goto CLEANUP;
}
hr = pEnum->GetObjects(0L,
dwNumObjects,
apEnumAccess,
&dwNumReturned);
// If the buffer was not big enough,
// allocate a bigger buffer and retry.
if (hr == WBEM_E_BUFFER_TOO_SMALL
&& dwNumReturned > dwNumObjects)
{
apEnumAccess = new IWbemObjectAccess*[dwNumReturned];
if (NULL == apEnumAccess)
{
hr = E_OUTOFMEMORY;
goto CLEANUP;
}
SecureZeroMemory(apEnumAccess,
dwNumReturned*sizeof(IWbemObjectAccess*));
dwNumObjects = dwNumReturned;
if (FAILED (hr = pEnum->GetObjects(0L,
dwNumObjects,
apEnumAccess,
&dwNumReturned)))
{
goto CLEANUP;
}
}
else
{
if (hr == WBEM_S_NO_ERROR)
{
hr = WBEM_E_NOT_FOUND;
goto CLEANUP;
}
}
// First time through, get the handles.
if (0 == x)
{
CIMTYPE VirtualBytesType;
CIMTYPE ProcessHandleType;
if (FAILED (hr = apEnumAccess[0]->GetPropertyHandle(
L"VirtualBytes",
&VirtualBytesType,
&lVirtualBytesHandle)))
{
goto CLEANUP;
}
if (FAILED (hr = apEnumAccess[0]->GetPropertyHandle(
L"IDProcess",
&ProcessHandleType,
&lIDProcessHandle)))
{
goto CLEANUP;
}
}
for (i = 0; i < dwNumReturned; i++)
{
if (FAILED (hr = apEnumAccess[i]->ReadDWORD(
lVirtualBytesHandle,
&dwVirtualBytes)))
{
goto CLEANUP;
}
if (FAILED (hr = apEnumAccess[i]->ReadDWORD(
lIDProcessHandle,
&dwIDProcess)))
{
goto CLEANUP;
}
wprintf(L"Process ID %lu is using %lu bytes\n",
dwIDProcess, dwVirtualBytes);
// Done with the object
apEnumAccess[i]->Release();
apEnumAccess[i] = NULL;
}
if (NULL != apEnumAccess)
{
delete [] apEnumAccess;
apEnumAccess = NULL;
}
// Sleep for a second.
Sleep(1000);
}
// exit loop here
CLEANUP:
if (NULL != bstrNameSpace)
{
SysFreeString(bstrNameSpace);
}
if (NULL != apEnumAccess)
{
for (i = 0; i < dwNumReturned; i++)
{
if (apEnumAccess[i] != NULL)
{
apEnumAccess[i]->Release();
apEnumAccess[i] = NULL;
}
}
delete [] apEnumAccess;
}
if (NULL != pWbemLocator)
{
pWbemLocator->Release();
}
if (NULL != pNameSpace)
{
pNameSpace->Release();
}
if (NULL != pEnum)
{
pEnum->Release();
}
if (NULL != pConfig)
{
pConfig->Release();
}
if (NULL != pRefresher)
{
pRefresher->Release();
}
CoUninitialize();
if (FAILED (hr))
{
wprintf (L"Error status=%08x\n",hr);
}
return 1;
}
Verwante onderwerpen