C ++では少し長くなります!これは完全に機能する例です。クエリをから変更する場合は注意してください。
SELECT ProcessorId FROM Win32_Processor
に
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;
}
まず、すべての初期化を行う必要があります。これらは次の2つの関数にパックされています。
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;
}
注:このコードは、CPUの単純なIDよりも多くの情報を収集する必要がある場合に役立ちます。これは、(C#で行ったように)WQLクエリから1つ(または複数)のプロパティを取得する一般的な例です。他の情報を取得する必要がない場合(およびC ++プログラムでWMIを使用することを考えていない場合)__cpuid()
、コメントに投稿されている組み込み関数を使用できます。
__cpuid()
WMIのProcessorId
プロパティには次の説明があります。
プロセッサー機能を説明するプロセッサー情報。x86クラスCPUの場合、フィールド形式はCPUID命令のプロセッササポートによって異なります。命令がサポートされている場合、プロパティには2つのDWORD形式の値が含まれます。1つ目は08h-0Bhのオフセットで、CPUID命令が入力EAXを1に設定して返すEAX値です。2つ目は0Ch-0Fhのオフセットで、命令が返すEDX値です。プロパティの最初の2バイトのみが重要であり、CPUリセット時の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++風の実装については、この投稿も参照してください。