Acessando classes de desempenho pré-instaladas do WMI
O repositório WMI contém classes de desempenho pré-instaladas para todos os objetos da biblioteca de desempenho. Por exemplo, instâncias da classe de desempenho de dados brutos Win32_PerfRawData_PerfProc_Process representam processos. Este objeto de desempenho é visível no Monitor do Sistema como o objeto Process.
A propriedade PageFaultsPerSec de Win32_PerfRawData_PerfProc_Process representa o contador de desempenho de falhas de página por segundo para o processo. As classes Win32_PerfFormattedData contêm os dados calculados que são exibidos no Monitor do Sistema (Perfmon.exe). O valor da propriedade PageFaultsPerSec de Win32_PerfFormattedData_PerfProc_Process é o mesmo que quando aparece no Monitor do Sistema.
Use a API COM para WMI ou a API de script para WMI para aceder a dados de desempenho por meio das Classes de Contadores de Desempenho . Em ambos os casos, é necessário um objeto de atualização para obter cada amostra de dados. Para obter mais informações e exemplos de código de script para usar atualizações e acessar classes de desempenho, consulte Tarefas WMI: Monitoramento de desempenho. Para obter mais informações, consulte Acessando dados de desempenho no Script.
Acessando dados de desempenho a partir de C++
O exemplo de código C++ a seguir usa o provedor Performance Counter para acessar classes de alto desempenho predefinidas. Ele cria um objeto de atualização e adiciona um objeto à atualização. O objeto é uma instância Win32_PerfRawData_PerfProc_Process que monitora o desempenho de um processo específico. O código lê apenas uma propriedade contador no objeto de processo, a propriedade VirtualBytes. O código requer as seguintes referências e instruções #include para compilar corretamente.
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
O procedimento a seguir mostra como acessar dados de um provedor de alto desempenho em C++.
Para acessar dados de um provedor de alto desempenho em C++
Estabeleça uma conexão com o namespace WMI e defina a segurança WMI usando uma chamada para IWbemLocator::ConnectServer e CoSetProxyBlanket.
Esta etapa é uma etapa padrão para criar qualquer aplicativo cliente WMI. Para obter mais informações, consulte Criando um aplicativo WMI usando C++.
Crie um objeto de atualização usando CoCreateInstance com CLSID_WbemRefresher. Solicite um interface de IWbemConfigureRefresher por meio do métodoQueryInterface. Solicite uma interface IWbemRefresher através do método QueryInterface.
A interface IWbemRefresher é a interface principal para o objeto WMI Refresher.
O exemplo de código C++ a seguir mostra como recuperar IWbemConfigureRefresher.
IWbemRefresher* pRefresher = NULL; HRESULT hr = CoCreateInstance( CLSID_WbemRefresher, NULL, CLSCTX_INPROC_SERVER, IID_IWbemRefresher, (void**) &pRefresher); IWbemConfigureRefresher* pConfig = NULL; pRefresher->QueryInterface( IID_IWbemConfigureRefresher, (void**) &pConfig );
Adicione um objeto ao refrescador por meio de uma chamada para o métodoIWbemConfigureRefresher::AddObjectByPath.
Quando você adiciona um objeto à atualização, o WMI atualiza o objeto sempre que você chama o método IWbemRefresher::Refresh. O objeto adicionado designa o provedor em seus qualificadores de classe.
O exemplo de código C++ a seguir mostra como chamar AddObjectByPath.
IWbemClassObject* pObj = NULL; IWbemServices* pNameSpace = NULL; // Add the instance to be refreshed. hr = pConfig->AddObjectByPath( pNameSpace, L"Win32_PerfRawData_PerfProc_Process.Name=\"WINWORD\"", 0L, NULL, &pObj, NULL ); if (FAILED(hr)) { cout << "Could not add object. Error code: 0x" << hex << hr << endl; pNameSpace->Release(); return hr; }
Para configurar um acesso mais rápido ao objeto, conecte-se à interfaceIWbemObjectAccess dopor meio QueryInterface na interfaceIWbemClassObject.
O exemplo de código C++ a seguir mostra como recuperar um ponteiro para o objeto usando IWbemObjectAccess em vez de IWbemClassObject.
// For quick property retrieval, use IWbemObjectAccess. IWbemObjectAccess* pAcc = NULL; pObj->QueryInterface( IID_IWbemObjectAccess, (void**) &pAcc ); // This is not required. pObj->Release();
A interfaceIWbemObjectAccess aumenta o desempenho porque você pode obter identificadores para propriedades específicas do contador e requer que você bloqueie e desbloqueie o objeto em seu código, que é uma operação que IWbemClassObject executa para cada acesso à propriedade.
Obtenha os identificadores das propriedades a serem examinadas usando chamadas para o método IWbemObjectAccess::GetPropertyHandle.
Os identificadores de propriedade são os mesmos para todas as instâncias de uma classe, o que significa que use o identificador de propriedade que você recupera de uma instância específica para todas as instâncias de uma classe específica. Você também pode obter um identificador de um objeto de classe para recuperar valores de propriedade de um objeto de instância.
O exemplo de código C++ a seguir mostra como recuperar um identificador de propriedade.
// Get a property handle for the VirtualBytes property long lVirtualBytesHandle = 0; DWORD dwVirtualBytes = 0; CIMTYPE variant; hr = pAcc->GetPropertyHandle(L"VirtualBytes", &variant, &lVirtualBytesHandle ); if (FAILED(hr)) { cout << "Could not get property handle. Error code: 0x" << hex << hr << endl; return hr; }
Crie um loop de programação que execute as seguintes ações:
Atualize o objeto realizando uma chamada para IWbemRefresher::Refresh, utilizando o ponteiro criado na chamada anterior para CoCreateInstance.
Nesta chamada, o WMI Refresher atualiza o objeto cliente usando dados fornecidos pelo provedor.
Execute qualquer ação conforme necessário no objeto, como recuperar um nome de propriedade, tipo de dados ou valor.
Você pode acessar a propriedade através do identificador de propriedade obtido anteriormente. Por causa da chamada Refresh, o WMI atualiza a propriedade a cada passagem do loop.
O exemplo C++ a seguir mostra como usar a API de alto desempenho WMI.
// Get the local locator object
IWbemServices* pNameSpace = NULL;
IWbemLocator* pWbemLocator = NULL;
CIMTYPE variant;
VARIANT VT;
CoCreateInstance( CLSID_WbemLocator, NULL,
CLSCTX_INPROC_SERVER, IID_IWbemLocator, (void**) &pWbemLocator
);
// Connect to the desired namespace
BSTR bstrNameSpace = SysAllocString( L"\\\\.\\root\\cimv2" );
HRESULT hr = WBEM_S_NO_ERROR;
hr = pWbemLocator->ConnectServer(
bstrNameSpace, // Namespace name
NULL, // User name
NULL, // Password
NULL, // Locale
0L, // Security flags
NULL, // Authority
NULL, // Wbem context
&pNameSpace // Namespace
);
if ( SUCCEEDED( hr ) )
{
// Set namespace security.
IUnknown* pUnk = NULL;
pNameSpace->QueryInterface( IID_IUnknown, (void**) &pUnk );
hr = CoSetProxyBlanket(
pNameSpace,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_DEFAULT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE
);
if (FAILED(hr))
{
cout << "Cannot set proxy blanket. Error code: 0x"
<< hex << hr << endl;
pNameSpace->Release();
return hr;
}
hr = CoSetProxyBlanket(pUnk,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_DEFAULT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE
);
if (FAILED(hr))
{
cout << "Cannot set proxy blanket. Error code: 0x"
<< hex << hr << endl;
pUnk->Release();
return hr;
}
// Clean up the IUnknown.
pUnk->Release();
IWbemRefresher* pRefresher = NULL;
IWbemConfigureRefresher* pConfig = NULL;
// Create a WMI Refresher and get a pointer to the
// IWbemConfigureRefresher interface.
CoCreateInstance(CLSID_WbemRefresher,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWbemRefresher,
(void**) &pRefresher
);
pRefresher->QueryInterface(IID_IWbemConfigureRefresher,
(void**) &pConfig );
IWbemClassObject* pObj = NULL;
// Add the instance to be refreshed.
pConfig->AddObjectByPath(
pNameSpace,
L"Win32_PerfRawData_PerfProc_Process.Name=\"WINWORD\"",
0L,
NULL,
&pObj,
NULL
);
if (FAILED(hr))
{
cout << "Cannot add object. Error code: 0x"
<< hex << hr << endl;
pNameSpace->Release();
return hr;
}
// For quick property retrieval, use IWbemObjectAccess.
IWbemObjectAccess* pAcc = NULL;
pObj->QueryInterface(IID_IWbemObjectAccess,
(void**) &pAcc );
// This is not required.
pObj->Release();
// Get a property handle for the VirtualBytes property.
long lVirtualBytesHandle = 0;
DWORD dwVirtualBytes = 0;
pAcc->GetPropertyHandle(L"VirtualBytes",
&variant,
&lVirtualBytesHandle );
// Refresh the object ten times and retrieve the value.
for( int x = 0; x < 10; x++ )
{
pRefresher->Refresh( 0L );
pAcc->ReadDWORD( lVirtualBytesHandle, &dwVirtualBytes );
printf( "Process is using %lu bytes\n", dwVirtualBytes );
// Sleep for a second.
Sleep( 1000 );
}
// Clean up all the objects.
pAcc->Release();
// Done with these too.
pConfig->Release();
pRefresher->Release();
pNameSpace->Release();
}
SysFreeString( bstrNameSpace );
pWbemLocator->Release();
Tópicos relacionados