Voorbeeld: WMI-gegevens ophalen van een externe computer
U kunt de procedure en codevoorbeelden in dit onderwerp gebruiken om een volledige WMI-clienttoepassing te maken die COM-initialisatie uitvoert, verbinding maakt met WMI op een externe computer, gegevens semisynchroon ophaalt en vervolgens opschoont. Zie Voorbeeld: WMI-gegevens ophalen van de lokale computervoor meer informatie over het ophalen van gegevens van de lokale computer. Zie Voorbeeld: WMI-gegevens ophalen van de lokale computer asynchroonvoor meer informatie over het asynchroon ophalen van de gegevens.
Notitie
Als u verbinding probeert te maken met een externe computer, raadpleegt u de informatie in Verbinding maken met WMI op afstand.
In de volgende procedure ziet u hoe u de WMI-toepassing uitvoert. Stap 1 tot en met 5 bevat alle stappen die nodig zijn om WMI in te stellen en er verbinding mee te maken, en stap 6 en 7 zijn waar gegevens worden opgevraagd en ontvangen.
WMI-gegevens ophalen van een externe computer
Initialiseer COM-parameters met een aanroep naar CoInitializeEx.
Zie COM initialiseren voor een WMI-toepassingvoor meer informatie.
Initialiseer com-procesbeveiliging door CoInitializeSecurityaan te roepen.
Zie Het standaardniveau voor procesbeveiliging instellen met C++voor meer informatie.
Haal de eerste locator naar WMI op door CoCreateInstance-aan te roepen.
Zie Een verbinding maken met een WMI-naamruimtevoor meer informatie.
Vraag een aanwijzer naar IWbemServices- voor de \\root\cimv2-naamruimte op een externe computer door IWbemLocator::ConnectServeraan te roepen. Wanneer u verbinding maakt met een externe computer, moet u de computernaam, het domein, de gebruikersnaam en het wachtwoord weten van de externe computer waarmee u verbinding maakt. Deze kenmerken worden allemaal doorgegeven aan de methode IWbemLocator::ConnectServer. Zorg er ook voor dat de gebruikersnaam op de computer die verbinding probeert te maken met de externe computer de juiste toegangsrechten heeft op de externe computer. Zie Verbinding maken via Windows Firewallvoor meer informatie. Zie voorbeeld: WMI-gegevens ophalen van de lokale computer en Verbinding maken met een WMI-naamruimteom verbinding te maken met de lokale computer.
Bij het afhandelen van gebruikersnamen en wachtwoorden wordt aanbevolen dat de gebruiker om de informatie wordt gevraagd, de informatie gebruikt en vervolgens de informatie verwijdert, zodat er minder kans is dat de gegevens worden onderschept door een onbevoegde gebruiker. Stap 4 in de onderstaande voorbeeldcode maakt gebruik van CredUIPromptForCredentials om de gebruikersnaam en het wachtwoord op te halen en gebruikt vervolgens SecureZeroMemory- om de informatie te verwijderen nadat deze is gebruikt in IWbemLocator::ConnectServer. Zie voor meer informatie het verwerken van wachtwoorden en de gebruiker vragen om referenties.
Maak een COAUTHIDENTITY- structuur om referenties op te geven voor het instellen van de proxybeveiliging.
Stel IWbemServices proxybeveiliging in, zodat de WMI-service de client kan imiteren door CoSetProxyBlanket-aan te roepen.
Zie Beveiligingsniveaus instellen voor een WMI-verbindingvoor meer informatie.
Gebruik de IWbemServices aanwijzer om aanvragen van WMI te doen. Er wordt een query uitgevoerd om de naam van het besturingssysteem en de hoeveelheid gratis fysiek geheugen te verkrijgen door IWbemServices::ExecQueryaan te roepen.
De volgende WQL-query is een van de methodeargumenten.
SELECT * FROM Win32_OperatingSystem
Het resultaat van deze query wordt opgeslagen in een IEnumWbemClassObject aanwijzer. Hierdoor kunnen de gegevensobjecten van de query semisynchroon worden opgehaald met de interface IEnumWbemClassObject. Zie WMI-opsommen voor meer informatie. Zie voorbeeld: WMI-gegevens ophalen van de lokale computer asynchroonvoor informatie over het asynchroon ophalen van de gegevens.
Zie Manipulating Class and Instance Information, Query's uitvoeren op WMI-en Een methode aanroepenvoor meer informatie over het uitvoeren van aanvragen van WMI.
Stel IEnumWbemClassObject in enumerator-proxybeveiliging. Zorg ervoor dat u de referenties uit het geheugen wist nadat u klaar bent met het gebruik ervan.
Zie Security on IWbemServices and Other Proxiesvoor meer informatie.
Haal de gegevens op uit de WQL-query en geef deze weer. De IEnumWbemClassObject aanwijzer is gekoppeld aan de gegevensobjecten die de query heeft geretourneerd en de gegevensobjecten kunnen worden opgehaald met de methode IEnumWbemClassObject::Next. Met deze methode worden de gegevensobjecten gekoppeld aan een IWbemClassObject aanwijzer die wordt doorgegeven aan de methode. Gebruik de methode IWbemClassObject::Get om de gewenste informatie op te halen uit de gegevensobjecten.
Het volgende codevoorbeeld wordt gebruikt om de eigenschap
Name
op te halen uit het gegevensobject, dat de naam van het besturingssysteem bevat.VARIANT vtProp; // Get the value of the Name property hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0); wcout << " OS Name : " << vtProp.bstrVal << endl;
Zodra de waarde van de eigenschap
Name
is opgeslagen in de VARIANT variabelevtProp
, kan deze vervolgens aan de gebruiker worden weergegeven.In het volgende codevoorbeeld ziet u hoe de variabele VARIANT opnieuw kan worden gebruikt om de waarde van de hoeveelheid vrij fysiek geheugen op te slaan en weer te geven.
hr = pclsObj->Get(L"FreePhysicalMemory", 0, &vtProp, 0, 0); wcout << " Free physical memory (in kilobytes): " << vtProp.uintVal << endl;
Zie WMI-opsommen voor meer informatie.
In het volgende codevoorbeeld ziet u hoe u WMI-gegevens semisynchroon kunt ophalen van een externe computer.
#define _WIN32_DCOM
#define UNICODE
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
#pragma comment(lib, "credui.lib")
#pragma comment(lib, "comsuppw.lib")
#include <wincred.h>
#include <strsafe.h>
int __cdecl main(int argc, char **argv)
{
HRESULT hres;
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
cout << "Failed to initialize COM library. Error code = 0x"
<< hex << hres << endl;
return 1; // Program has failed.
}
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
hres = CoInitializeSecurity(
NULL,
-1, // COM authentication
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IDENTIFY, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
if (FAILED(hres))
{
cout << "Failed to initialize security. Error code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pLoc);
if (FAILED(hres))
{
cout << "Failed to create IWbemLocator object."
<< " Err code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 4: -----------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices *pSvc = NULL;
// Get the user name and password for the remote computer
CREDUI_INFO cui;
bool useToken = false;
bool useNTLM = true;
wchar_t pszName[CREDUI_MAX_USERNAME_LENGTH+1] = {0};
wchar_t pszPwd[CREDUI_MAX_PASSWORD_LENGTH+1] = {0};
wchar_t pszDomain[CREDUI_MAX_USERNAME_LENGTH+1];
wchar_t pszUserName[CREDUI_MAX_USERNAME_LENGTH+1];
wchar_t pszAuthority[CREDUI_MAX_USERNAME_LENGTH+1];
BOOL fSave;
DWORD dwErr;
memset(&cui,0,sizeof(CREDUI_INFO));
cui.cbSize = sizeof(CREDUI_INFO);
cui.hwndParent = NULL;
// Ensure that MessageText and CaptionText identify
// what credentials to use and which application requires them.
cui.pszMessageText = TEXT("Press cancel to use process token");
cui.pszCaptionText = TEXT("Enter Account Information");
cui.hbmBanner = NULL;
fSave = FALSE;
dwErr = CredUIPromptForCredentials(
&cui, // CREDUI_INFO structure
TEXT(""), // Target for credentials
NULL, // Reserved
0, // Reason
pszName, // User name
CREDUI_MAX_USERNAME_LENGTH+1, // Max number for user name
pszPwd, // Password
CREDUI_MAX_PASSWORD_LENGTH+1, // Max number for password
&fSave, // State of save check box
CREDUI_FLAGS_GENERIC_CREDENTIALS |// flags
CREDUI_FLAGS_ALWAYS_SHOW_UI |
CREDUI_FLAGS_DO_NOT_PERSIST);
if(dwErr == ERROR_CANCELLED)
{
useToken = true;
}
else if (dwErr)
{
cout << "Did not get credentials " << dwErr << endl;
pLoc->Release();
CoUninitialize();
return 1;
}
// change the computerName strings below to the full computer name
// of the remote computer
if(!useNTLM)
{
StringCchPrintf(pszAuthority, CREDUI_MAX_USERNAME_LENGTH+1, L"kERBEROS:%s", L"COMPUTERNAME");
}
// Connect to the remote root\cimv2 namespace
// and obtain pointer pSvc to make IWbemServices calls.
//---------------------------------------------------------
hres = pLoc->ConnectServer(
_bstr_t(L"\\\\COMPUTERNAME\\root\\cimv2"),
_bstr_t(useToken?NULL:pszName), // User name
_bstr_t(useToken?NULL:pszPwd), // User password
NULL, // Locale
NULL, // Security flags
_bstr_t(useNTLM?NULL:pszAuthority),// Authority
NULL, // Context object
&pSvc // IWbemServices proxy
);
if (FAILED(hres))
{
cout << "Could not connect. Error code = 0x"
<< hex << hres << endl;
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;
// step 5: --------------------------------------------------
// Create COAUTHIDENTITY that can be used for setting security on proxy
COAUTHIDENTITY *userAcct = NULL ;
COAUTHIDENTITY authIdent;
if( !useToken )
{
memset(&authIdent, 0, sizeof(COAUTHIDENTITY));
authIdent.PasswordLength = wcslen (pszPwd);
authIdent.Password = (USHORT*)pszPwd;
LPWSTR slash = wcschr (pszName, L'\\');
if( slash == NULL )
{
cout << "Could not create Auth identity. No domain specified\n" ;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
StringCchCopy(pszUserName, CREDUI_MAX_USERNAME_LENGTH+1, slash+1);
authIdent.User = (USHORT*)pszUserName;
authIdent.UserLength = wcslen(pszUserName);
StringCchCopyN(pszDomain, CREDUI_MAX_USERNAME_LENGTH+1, pszName, slash - pszName);
authIdent.Domain = (USHORT*)pszDomain;
authIdent.DomainLength = slash - pszName;
authIdent.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
userAcct = &authIdent;
}
// Step 6: --------------------------------------------------
// Set security levels on a WMI connection ------------------
hres = CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_DEFAULT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_DEFAULT, // RPC_C_AUTHZ_xxx
COLE_DEFAULT_PRINCIPAL, // Server principal name
RPC_C_AUTHN_LEVEL_PKT_PRIVACY, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
userAcct, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hres))
{
cout << "Could not set proxy blanket. Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Step 7: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
// For example, get the name of the operating system
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("Select * from Win32_OperatingSystem"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres))
{
cout << "Query for operating system name failed."
<< " Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Step 8: -------------------------------------------------
// Secure the enumerator proxy
hres = CoSetProxyBlanket(
pEnumerator, // Indicates the proxy to set
RPC_C_AUTHN_DEFAULT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_DEFAULT, // RPC_C_AUTHZ_xxx
COLE_DEFAULT_PRINCIPAL, // Server principal name
RPC_C_AUTHN_LEVEL_PKT_PRIVACY, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
userAcct, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hres))
{
cout << "Could not set proxy blanket on enumerator. Error code = 0x"
<< hex << hres << endl;
pEnumerator->Release();
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// When you have finished using the credentials,
// erase them from memory.
SecureZeroMemory(pszName, sizeof(pszName));
SecureZeroMemory(pszPwd, sizeof(pszPwd));
SecureZeroMemory(pszUserName, sizeof(pszUserName));
SecureZeroMemory(pszDomain, sizeof(pszDomain));
// Step 9: -------------------------------------------------
// Get the data from the query in step 7 -------------------
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
&pclsObj, &uReturn);
if(0 == uReturn)
{
break;
}
VARIANT vtProp;
// Get the value of the Name property
hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);
wcout << " OS Name : " << vtProp.bstrVal << endl;
// Get the value of the FreePhysicalMemory property
hr = pclsObj->Get(L"FreePhysicalMemory",
0, &vtProp, 0, 0);
wcout << " Free physical memory (in kilobytes): "
<< vtProp.uintVal << endl;
VariantClear(&vtProp);
pclsObj->Release();
pclsObj = NULL;
}
// Cleanup
// ========
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
if( pclsObj )
{
pclsObj->Release();
}
CoUninitialize();
return 0; // Program successfully completed.
}