你可以从C中调用COM。语法比C ++不太友好,但它确实可以工作。最初设计COM时,它可以从C或C ++中工作,原生的C语言支持包含在COM和WMI头文件中。不过需要注意,你的程序将负责分配所有必要的对象,检查每个COM调用的错误条件,并释放其实例化的对象。
当使用以C++为目标的文档时,请转换形式为COM调用:
pSomething->Method(arg1, ...); // C++
目标:
pSomething->lpVtbl->Method(pSomething, arg1, ...)
以下是我最短的 C 代码,可以从 WMI 获取一些信息。如果成功,它应该列出计算机上的处理器以及它们的时钟频率(单位为 MHz)。该程序会处理它分配的资源,但它不进行任何错误检查(在继续每个步骤之前,您应该查看这些 hr 值)。
这是一个 Visual Studio 2008 的“Win32 控制台应用程序”,主文件已重命名为 .c 扩展名,并删除了额外的 stdafx 文件。要使程序链接,请确保在项目属性下的“配置属性/链接器/输入/附加依赖项”中包含 wbemuuid.lib。它在我的 Vista 上成功运行。
#define _WIN32_WINNT 0x0400
#define _WIN32_DCOM
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <wbemidl.h>
void _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr = 0;
IWbemLocator *locator = NULL;
IWbemServices *services = NULL;
IEnumWbemClassObject *results = NULL;
BSTR resource = SysAllocString(L"ROOT\\CIMV2");
BSTR language = SysAllocString(L"WQL");
BSTR query = SysAllocString(L"SELECT * FROM Win32_Processor");
hr = CoInitializeEx(0, COINIT_MULTITHREADED);
hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
hr = CoCreateInstance(&CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, &IID_IWbemLocator, (LPVOID *) &locator);
hr = locator->lpVtbl->ConnectServer(locator, resource, NULL, NULL, NULL, 0, NULL, NULL, &services);
hr = services->lpVtbl->ExecQuery(services, language, query, WBEM_FLAG_BIDIRECTIONAL, NULL, &results);
if (results != NULL) {
IWbemClassObject *result = NULL;
ULONG returnedCount = 0;
while((hr = results->lpVtbl->Next(results, WBEM_INFINITE, 1, &result, &returnedCount)) == S_OK) {
VARIANT name;
VARIANT speed;
hr = result->lpVtbl->Get(result, L"Name", 0, &name, 0, 0);
hr = result->lpVtbl->Get(result, L"MaxClockSpeed", 0, &speed, 0, 0);
wprintf(L"%s, %dMHz\r\n", name.bstrVal, speed.intVal);
result->lpVtbl->Release(result);
}
}
results->lpVtbl->Release(results);
services->lpVtbl->Release(services);
locator->lpVtbl->Release(locator);
CoUninitialize();
SysFreeString(query);
SysFreeString(language);
SysFreeString(resource);
}