Příklad: Získání dat rozhraní WMI ze vzdáleného počítače
Pomocí postupu a příkladů kódu v tomto tématu můžete vytvořit úplnou klientskou aplikaci rozhraní WMI, která provádí inicializaci modelu COM, připojuje se k rozhraní WMI na vzdáleném počítači, získává data polosynchronně a pak se vyčistí. Další informace o tom, jak získat data z místního počítače, naleznete v tématu Příklad: Získání dat rozhraní WMI z místního počítače. Další informace o tom, jak získat data asynchronně, naleznete v tématu Příklad: Získání dat rozhraní WMI z místního počítače asynchronně.
Poznámka
Pokud se pokoušíte připojit ke vzdálenému počítači, přečtěte si informace v Připojení k rozhraní WMI Vzdáleně.
Následující postup ukazuje, jak spustit aplikaci WMI. Kroky 1 až 5 obsahují všechny kroky potřebné k nastavení a připojení k rozhraní WMI a kroky 6 a 7 jsou místem, kde se data dotazují a přijímají.
Získání dat rozhraní WMI ze vzdáleného počítače
Inicializace parametrů com voláním CoInitializeEx.
Další informace naleznete v tématu Inicializace modelu COM proaplikace rozhraní WMI .
Inicializace zabezpečení procesu COM voláním CoInitializeSecurity.
Další informace naleznete v tématu Nastavení výchozí úrovně zabezpečení procesu pomocí jazyka C++.
Získejte počáteční lokátor rozhraní WMI voláním CoCreateInstance.
Další informace naleznete v tématu Vytvoření připojení k oboru názvů rozhraní WMI.
Získejte ukazatel na IWbemServices pro obor názvů \\root\cimv2 na vzdáleném počítači voláním IWbemLocator::ConnectServer. Při připojování ke vzdálenému počítači potřebujete znát název počítače, doménu, uživatelské jméno a heslo vzdáleného počítače, ke kterému se připojujete. Všechny tyto atributy se předávají do metody IWbemLocator::ConnectServer. Také se ujistěte, že uživatelské jméno v počítači, který se pokouší připojit ke vzdálenému počítači, má správná přístupová oprávnění na vzdáleném počítači. Další informace naleznete v tématu připojení prostřednictvím brány Windows Firewall. Pokud se chcete připojit k místnímu počítači, přečtěte si příklad: Získání dat rozhraní WMI z místního počítače a Vytvoření připojení koboru názvů rozhraní WMI .
Při zpracování uživatelských jmen a hesel se doporučuje, aby se uživateli zobrazila výzva k zadání informací, použití těchto informací a následné odstranění těchto informací, aby nedošlo k menší pravděpodobnosti zachycení informací neoprávněným uživatelem. Krok 4 v následujícím ukázkovém kódu používá CredUIPromptForCredentials získat uživatelské jméno a heslo a pak pomocí SecureZeroMemory zbavit informací po použití v IWbemLocator::ConnectServer. Další informace naleznete v tématu zpracování hesel a požádat uživatele o přihlašovací údaje.
Vytvořte strukturu COAUTHIDENTITY a zadejte přihlašovací údaje pro nastavení zabezpečení proxy serveru.
Nastavte IWbemServices zabezpečení proxy serveru, aby služba WMI mohl zosobnit klienta voláním CoSetProxyBlanket.
Další informace najdete v tématu Nastavení úrovní zabezpečení napřipojení rozhraní WMI .
Pomocí ukazatele IWbemServices proveďte požadavky rozhraní WMI. Dotaz se spustí pro získání názvu operačního systému a množství volné fyzické paměti voláním IWbemServices::ExecQuery.
Následující dotaz WQL je jedním z argumentů metody.
SELECT * FROM Win32_OperatingSystem
Výsledek tohoto dotazu je uložen v IEnumWbemClassObject ukazatel. To umožňuje načtení datových objektů z dotazu polosynchronně pomocí rozhraní IEnumWbemClassObject. Další informace naleznete v tématu Výčet rozhraní WMI. Asynchronní získání dat naleznete v tématu Příklad: Získání dat rozhraní WMI z místního počítače asynchronně.
Další informace o vytváření požadavků rozhraní WMI naleznete v tématu manipulace s informacemi třídy a instance, dotazování rozhraní WMIa volání metody.
Nastavte IEnumWbemClassObject zabezpečení proxy enumerátoru. Po dokončení použití přihlašovacích údajů z paměti nezapomeňte přihlašovací údaje vymazat.
Další informace naleznete v tématu Nastavení zabezpečení pro služby IWbemServices a další proxy servery.
Získejte a zobrazte data z dotazu WQL. Ukazatel IEnumWbemClassObject je propojený s datovými objekty, které vrátil dotaz, a datové objekty lze načíst pomocí IEnumWbemClassObject::Next metoda. Tato metoda propojí datové objekty s IWbemClassObject ukazatel, který je předán do metody. K získání požadovaných informací z datových objektů použijte metodu IWbemClassObject::Get.
Následující příklad kódu se používá k získání
Name
vlastnosti z datového objektu, který poskytuje název operačního systému.VARIANT vtProp; // Get the value of the Name property hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0); wcout << " OS Name : " << vtProp.bstrVal << endl;
Jakmile je hodnota vlastnosti
Name
uložena v proměnné VARIANTvtProp
, můžete ji zobrazit uživateli.Následující příklad kódu ukazuje, jak VARIANT proměnnou lze znovu použít k uložení a zobrazení hodnoty množství volné fyzické paměti.
hr = pclsObj->Get(L"FreePhysicalMemory", 0, &vtProp, 0, 0); wcout << " Free physical memory (in kilobytes): " << vtProp.uintVal << endl;
Další informace naleznete v tématu Výčet rozhraní WMI.
Následující příklad kódu ukazuje, jak získat data WMI polosynchronně ze vzdáleného počítače.
#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.
}