WMI 사전 설치된 성능 클래스에 액세스
WMI 리포지토리에는 모든 성능 라이브러리 개체를 위한 사전 설치된 성능 클래스가 포함되어 있습니다. 예를 들어, 원시 데이터 성능 클래스 Win32_PerfRawData_PerfProc_Process는 프로세스를 나타냅니다. 이 성능 개체는 시스템 모니터에서 Process 개체로 표시됩니다.
Win32_PerfRawData_PerfProc_Process의 PageFaultsPerSec 속성은 해당 프로세스의 초당 페이지 폴트 성능 카운터를 나타냅니다. Win32_PerfFormattedData 클래스는 시스템 모니터(Perfmon.exe)에 표시되는 계산된 데이터 값을 포함합니다. Win32_PerfFormattedData_PerfProc_Process의 PageFaultsPerSec 속성 값은 시스템 모니터에 표시되는 것과 동일합니다.
성능 카운터 클래스를 통해 성능 데이터에 액세스하려면 WMI용 COM API 또는 WMI용 스크립팅 API 를 사용합니다. 두 경우 모두 각 데이터 샘플을 가져오려면 리프레셔 개체가 필요합니다. 리프레셔를 사용하고 성능 클래스에 액세스하기 위한 자세한 내용 및 스크립트 코드 예제는 WMI 작업: 성능 모니터링을 참조하세요. 자세한 내용은 스크립트에서 성능 데이터 액세스를 참조하세요.
C++에서 성능 데이터 액세스
다음 C++ 코드 예제에서는 성능 카운터 공급자를 사용하여 미리 정의된 고성능 클래스에 액세스합니다. 리프레셔 개체를 만들고 해당 리프레셔에 개체를 추가합니다. 개체는 특정 프로세스의 성능을 모니터링하는 Win32_PerfRawData_PerfProc_Process 인스턴스입니다. 코드는 프로세스 개체에서 하나의 카운터 속성(VirtualBytes 속성)만 읽습니다. 코드를 올바르게 컴파일하려면 다음 참조 및 #include 문이 필요합니다.
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
다음 절차는 C++의 고성능 공급자에서 데이터에 액세스하는 방법을 보여 줍니다.
C++의 고성능 공급자에서 데이터에 액세스하려면 다음을 수행합니다.
WMI 네임스페이스에 대한 연결을 구축하고, IWbemLocator::ConnectServer 및 CoSetProxyBlanket에 대한 호출을 사용하여 WMI 보안을 설정합니다.
이 단계는 WMI 클라이언트 애플리케이션을 만들기 위한 표준 단계입니다. 자세한 내용은 C++를 사용하여 WMI 애플리케이션 만들기를 참조하세요.
CLSID_WbemRefresher가 있는 CoCreateInstance를 사용하여 리프레셔 개체를 만듭니다. QueryInterface 메서드를 통해 IWbemConfigureRefresher 인터페이스를 요청합니다. QueryInterface 메서드를 통해 IWbemRefresher 인터페이스를 요청합니다.
IWbemRefresher 인터페이스는 WMI 리프레셔 개체의 기본 인터페이스입니다.
다음 C++ 코드 예제에서는 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 );
IWbemConfigureRefresher::AddObjectByPath 메서드에 대한 호출을 통해 리프레셔에 개체를 추가합니다.
리프레셔에 개체를 추가하면 WMI는 IWbemRefresher::Refresh 메서드가 호출될 때마다 개체를 새로 고칩니다. 개발자가 추가하는 개체는 클래스 한정자에서 공급자를 지정합니다.
다음 C++ 코드 예제에서는 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; }
개체에 대한 더 빠른 액세스를 설정하려면 IWbemClassObject 인터페이스에서 QueryInterface를 통해 IWbemObjectAccess 인터페이스에 연결합니다.
다음 C++ 코드 예제에서는 IWbemClassObject 대신 IWbemObjectAccess를 사용하여 개체에 대한 포인터를 검색하는 방법을 보여 줍니다.
// For quick property retrieval, use IWbemObjectAccess. IWbemObjectAccess* pAcc = NULL; pObj->QueryInterface( IID_IWbemObjectAccess, (void**) &pAcc ); // This is not required. pObj->Release();
IWbemObjectAccess 인터페이스의 경우 특정 카운터 속성에 대한 핸들을 가져올 수 있기 때문에 성능이 개선됩니다. 또한 이 인터페이스를 사용하려면 코드에서 개체를 잠근 후 잠금 해제해야 하는데, 이는 IWbemClassObject가 각 속성 액세스에 대해 수행하는 작업입니다.
IWbemObjectAccess::GetPropertyHandle 메서드에 대한 호출을 사용하여 검사할 속성의 핸들을 가져옵니다.
속성 핸들은 단일 클래스의 모든 인스턴스에서 동일합니다. 즉, 특정 클래스의 특정 인스턴스에서 가져온 속성 핸들을 해당 클래스의 모든 인스턴스에 사용할 수 있습니다. 클래스 개체에서 가져온 핸들을 사용하여 인스턴스 개체에서 속성 값을 가져올 수도 있습니다.
다음 C++ 코드 예제에서는 속성 핸들을 검색하는 방법을 보여 줍니다.
// 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; }
다음 작업을 수행하는 프로그래밍 루프를 만듭니다.
앞에서 CoCreateInstance를 호출하여 만든 포인터를 사용하여 IWbemRefresher::Refresh에 대한 호출로 개체를 새로 고칩니다.
이 호출에서는 WMI 리프레셔가 공급자가 제공한 데이터를 사용하여 클라이언트 개체를 새로 고칩니다.
개체에 대해 필요한 작업을 수행합니다. 예를 들어 속성 이름, 데이터 형식 또는 값을 검색하는 것입니다.
앞에서 가져온 속성 핸들을 통해 속성에 액세스할 수 있습니다. Refresh 호출로 인해 WMI는 매번 루프를 통해 속성을 새로 고칩니다.
다음 C++ 예제에서는 WMI 고성능 API를 사용하는 방법을 보여 줍니다.
// 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();
관련 항목