В C++ это немного длиннее! Это полный рабочий пример, обратите внимание, что если вы измените запрос с
SELECT ProcessorId FROM Win32_Processor
to
SELECT * FROM Win32_Processor
Затем вы можете использовать функцию QueryValue
для запроса любого значения свойства.
HRESULT GetCpuId(char* cpuId, int bufferLength)
{
HRESULT result = InitializeCom();
if (FAILED(result))
return result;
IWbemLocator* pLocator = NULL;
IWbemServices* pService = NULL;
result = GetWbemService(&pLocator, &pService);
if (FAILED(result))
{
CoUninitialize();
return result;
}
memset(cpuId, 0, bufferLength);
result = QueryValue(pService,
L"SELECT ProcessorId FROM Win32_Processor", L"ProcessorId",
cpuId, bufferLength);
if (FAILED(result))
{
pService->Release();
pLocator->Release();
CoUninitialize();
return result;
}
pService->Release();
pLocator->Release();
CoUninitialize();
return NOERROR;
}
Сначала вам нужно выполнить все действия по инициализации, они упакованы в эти две функции:
HRESULT InitializeCom()
{
HRESULT result = CoInitializeEx(0, COINIT_APARTMENTTHREADED);
if (FAILED(result))
return result;
result = CoInitializeSecurity(
NULL, // pSecDesc
-1, // cAuthSvc (COM authentication)
NULL, // asAuthSvc
NULL, // pReserved1
RPC_C_AUTHN_LEVEL_DEFAULT, // dwAuthnLevel
RPC_C_IMP_LEVEL_IMPERSONATE, // dwImpLevel
NULL, // pAuthList
EOAC_NONE, // dwCapabilities
NULL // Reserved
);
if (FAILED(result) && result != RPC_E_TOO_LATE)
{
CoUninitialize();
return result;
}
return NOERROR;
}
HRESULT GetWbemService(IWbemLocator** pLocator, IWbemServices** pService)
{
HRESULT result = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
IID_IWbemLocator, reinterpret_cast<LPVOID*>(pLocator));
if (FAILED(result))
{
return result;
}
result = (*pLocator)->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"), // strNetworkResource
NULL, // strUser
NULL, // strPassword
NULL, // strLocale
0, // lSecurityFlags
NULL, // strAuthority
NULL, // pCtx
pService // ppNamespace
);
if (FAILED(result))
{
(*pLocator)->Release();
return result;
}
result = CoSetProxyBlanket(
*pService, // pProxy
RPC_C_AUTHN_WINNT, // dwAuthnSvc
RPC_C_AUTHZ_NONE, // dwAuthzSvc
NULL, // pServerPrincName
RPC_C_AUTHN_LEVEL_CALL, // dwAuthnLevel
RPC_C_IMP_LEVEL_IMPERSONATE, // dwImpLevel
NULL, // pAuthInfo
EOAC_NONE // dwCapabilities
);
if (FAILED(result))
{
(*pService)->Release();
(*pLocator)->Release();
return result;
}
return NOERROR;
}
После этого вы можете запустить свой WQL-запрос, затем вам нужно перечислить возвращенные свойства, чтобы найти то, что вам нужно (вы можете сделать это проще, но таким образом вы можете запрашивать несколько значений). Обратите внимание, что если вы запросите ВСЕ значения из Win32_Processor, вы получите много данных. Я видел, что в некоторых системах для завершения запроса и перечисления свойств требуется даже 2 секунды (поэтому отфильтруйте свой запрос, чтобы включить только те данные, которые вам нужны).
HRESULT QueryValue(IWbemServices* pService, const wchar_t* query, const wchar_t* propertyName, char* propertyValue, int maximumPropertyValueLength)
{
USES_CONVERSION;
IEnumWbemClassObject* pEnumerator = NULL;
HRESULT result = pService->ExecQuery(
bstr_t(L"WQL"), // strQueryLanguage
bstr_t(query), // strQuery
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, // lFlags
NULL, // pCtx
&pEnumerator // ppEnum
);
if (FAILED(result))
return result;
IWbemClassObject *pQueryObject = NULL;
while (pEnumerator)
{
try
{
ULONG returnedObjectCount = 0;
result = pEnumerator->Next(WBEM_INFINITE, 1, &pQueryObject, &returnedObjectCount);
if (returnedObjectCount == 0)
break;
VARIANT objectProperty;
result = pQueryObject->Get(propertyName, 0, &objectProperty, 0, 0);
if (FAILED(result))
{
if (pEnumerator != NULL)
pEnumerator->Release();
if (pQueryObject != NULL)
pQueryObject->Release();
return result;
}
if ((objectProperty.vt & VT_BSTR) == VT_BSTR)
{
strcpy_s(propertyValue, maximumPropertyValueLength, OLE2A(objectProperty.bstrVal));
break;
}
VariantClear(&objectProperty);
}
catch (...)
{
if (pEnumerator != NULL)
pEnumerator->Release();
if (pQueryObject != NULL)
pQueryObject->Release();
return NOERROR;
}
}
if (pEnumerator != NULL)
pEnumerator->Release();
if (pQueryObject != NULL)
pQueryObject->Release();
return NOERROR;
}
ПРИМЕЧАНИЕ: этот код полезен, если вам нужно собрать больше информации, чем простой ID процессора. Это общий пример получения одного (или нескольких) свойств из запроса WQL (как вы это делали в C#). Если вам не нужно получать какую-либо другую информацию (и вы не планируете использовать WMI в своих программах на C++), вы можете использовать встроенную функцию __cpuid()
, как указано в комментарии.
__процессор()
Свойство ProcessorId
из WMI имеет следующее описание:
Информация о процессоре, описывающая функции процессора. Для ЦП класса x86 формат поля зависит от поддержки процессором инструкции CPUID. Если инструкция поддерживается, свойство содержит 2 (два) значения в формате DWORD. Первое — это смещение 08h-0Bh, которое представляет собой значение EAX, которое возвращает инструкция CPUID, когда входной EAX установлен в 1. Второе — это смещение 0Ch-0Fh, которое является значением EDX, которое возвращает инструкция. Только первые два байта свойства являются значимыми и содержат содержимое регистра DX при сбросе ЦП — все остальные устанавливаются в 0 (ноль), а содержимое имеет формат DWORD.
Хорошая реализация должна проверять больше странных случаев, но наивная реализация может быть:
std::string GetProcessorId()
{
int info[4] = { -1 };
__cpuid(info, 0);
if (info[0] < 1)
return ""; // Not supported?!
// Up to you...you do not need to mask results and you may use
// features bits "as is".
__cpuid(info, 1);
int family = info[0];
int features = info[3];
std::stringstream id;
id << std::hex << std::setw(4) << std::setfill('0') << family << features;
return id.str();
}
См. также это сообщение для лучшей реализации C++.
person
Adriano Repetti
schedule
19.04.2012