Mengakses Data Kinerja pada C++
API berkinerja tinggi WMI adalah serangkaian antarmuka yang mendapatkan data dari Kelas Penghitung Kinerja . Antarmuka ini memerlukan penggunaan objek penyegar untuk meningkatkan laju pengambilan sampel. Untuk informasi selengkapnya tentang menggunakan objek penyegaran dalam pembuatan skrip, lihat Mengakses Data Kinerja dalam Skrip dan Tugas WMI: Pemantauan Kinerja.
Bagian berikut dibahas dalam topik ini:
- Memperbarui Data Kinerja
- Menambahkan Enumerator ke Pemuat Ulang WMI
- Contoh
- Topik terkait
Memperbarui Data Kinerja
Objek penyegar meningkatkan kinerja penyedia data dan klien dengan mengambil data tanpa melewati batas proses. Jika klien dan server terletak di komputer yang sama, penyegaran memuat penyedia berkinerja tinggi dalam proses ke klien, dan menyalin data langsung dari objek penyedia ke objek klien. Jika klien dan server berada di komputer yang berbeda, penyegaran meningkatkan performa dengan penyimpanan sementara objek di komputer jarak jauh, dan mengirimkan data minimal ke klien.
Sebagai penyegaran tambahan:
Secara otomatis menyambungkan ulang klien ke layanan WMI jarak jauh ketika terjadi kesalahan jaringan, atau komputer jarak jauh dimulai ulang.
Sebagai pengaturan awal, penyegaran mencoba menyambungkan kembali aplikasi Anda ke penyedia berkinerja tinggi yang relevan saat koneksi jarak jauh antara kedua komputer gagal. Untuk mencegah koneksi ulang, berikan bendera WBEM_FLAG_REFRESH_NO_AUTO_RECONNECT dalam panggilan metode Refresh. Klien scripting harus menyetel properti SWbemRefresher.AutoReconnect ke FALSE.
Memuat beberapa objek dan enumerator yang disediakan oleh penyedia yang sama atau berbeda.
Memungkinkan Anda menambahkan beberapa objek, enumerator, atau keduanya ke penyegaran.
Menghitung objek.
Seperti penyedia lain, penyedia berkinerja tinggi dapat menghitung objek.
Setelah Anda selesai menulis aplikasi klien berkinerja tinggi, Anda mungkin ingin mempercepat waktu respons. Karena antarmuka IWbemObjectAccess dioptimalkan untuk kecepatan, antarmuka ini tidak intrinsik aman terhadap lintas thread. Oleh karena itu, selama operasi refresh, jangan akses objek atau enumerasi yang dapat di-refresh. Untuk melindungi objek antar-utas selama panggilan metode IWbemObjectAccess, gunakan metode IWbemObjectAccess::Lock dan Unlock. Untuk meningkatkan kinerja, sinkronkan benang Anda sehingga Anda tidak perlu mengunci setiap benang secara individual. Mengurangi utas dan menyinkronkan grup objek untuk operasi refresh memberikan performa keseluruhan terbaik.
Menambahkan Enumerator ke Penyegar WMI
Baik jumlah instans maupun data di setiap instans diperbarui dengan menambahkan enumerator ke penyegar sehingga setiap pemanggilan ke IWbemRefresher::Refresh menghasilkan enumerasi yang lengkap.
Contoh kode C++ berikut memerlukan referensi berikut dan pernyataan #include untuk dikompilasi dengan benar.
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
Prosedur berikut menggambarkan cara menambahkan enumerator ke pemutakhiran.
Untuk menambahkan enumerator ke pemutakhiran
Panggil metode IWbemConfigureRefresher::AddEnum menggunakan jalur ke objek yang dapat di-refresh dan antarmukaIWbemServices.
Penyegar mengembalikan penunjuk ke antarmuka IWbemHiPerfEnum. Anda dapat menggunakan antarmuka IWbemHiPerfEnum untuk mengakses objek dalam enumerasi.
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;
Buat perulangan yang melakukan tindakan berikut:
Refresh objek dengan menggunakan panggilan ke IWbemRefresher::Refresh.
Menyediakan penunjuk antarmuka array IWbemObjectAccess ke metode IWbemHiPerfEnum::GetObjects.
Mengakses properti enumerator dengan menggunakan metodeIWbemObjectAccess yang diteruskan ke GetObjects.
Pegangan properti dapat diteruskan ke setiap instans IWbemObjectAccess untuk mendapatkan nilai terbaru. Klien harus memanggilRilisuntuk merilis pointer IWbemObjectAccess yang dikembalikan oleh GetObjects.
Contoh
Contoh kode C++ berikut menjumlahkan kelas berkinerja tinggi, di mana klien mengambil handle properti dari objek pertama, dan menggunakan kembali handle tersebut untuk sisa operasi pembaruan. Setiap panggilan ke metode Refresh memperbarui jumlah instans dan data instans.
#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;
}
Topik terkait