Вы можете вызывать COM из C. Синтаксис несколько менее дружественный, чем в C ++, но он работает. Изначально COM был разработан для работы с C или C ++, а поддержка родного языка C включена в заголовочные файлы COM и WMI. Это будет долго, хотя ... ваша программа будет отвечать за выделение всех необходимых объектов, проверку на наличие ошибок при каждом вызове COM и за освобождение объектов, для которых она была создана.
При использовании документации, написанной на языке C ++, преобразуйте вызовы COM в форму:
pSomething->Method(arg1, ...); // C++
до:
pSomething->lpVtbl->Method(pSomething, arg1, ...); // C
Ниже приведен самый короткий фрагмент кода на C, который я мог получить, чтобы получить некоторую информацию из WMI. В случае успеха он должен перечислить процессоры на вашем компьютере вместе с их тактовой частотой в МГц. Программа заботится об использовании ресурсов, которые она выделяет, но она не проверяет ошибки вообще (вы должны посмотреть на эти значения 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[])
{
// result code from COM calls
HRESULT hr = 0;
// COM interface pointers
IWbemLocator *locator = NULL;
IWbemServices *services = NULL;
IEnumWbemClassObject *results = NULL;
// BSTR strings we'll use (http://msdn.microsoft.com/en-us/library/ms221069.aspx)
BSTR resource = SysAllocString(L"ROOT\\CIMV2");
BSTR language = SysAllocString(L"WQL");
BSTR query = SysAllocString(L"SELECT * FROM Win32_Processor");
// initialize COM
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);
// connect to WMI
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);
// issue a WMI query
hr = services->lpVtbl->ExecQuery(services, language, query, WBEM_FLAG_BIDIRECTIONAL, NULL, &results);
// list the query results
if (results != NULL) {
IWbemClassObject *result = NULL;
ULONG returnedCount = 0;
// enumerate the retrieved objects
while((hr = results->lpVtbl->Next(results, WBEM_INFINITE, 1, &result, &returnedCount)) == S_OK) {
VARIANT name;
VARIANT speed;
// obtain the desired properties of the next result and print them out
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);
// release the current result object
result->lpVtbl->Release(result);
}
}
// release WMI COM interfaces
results->lpVtbl->Release(results);
services->lpVtbl->Release(services);
locator->lpVtbl->Release(locator);
// unwind everything else we've allocated
CoUninitialize();
SysFreeString(query);
SysFreeString(language);
SysFreeString(resource);
}