Как получить данные из WMI, используя приложение C?
У меня есть чистое приложение C, которое выполняет вызовы IOCTL для моего драйвера адаптера и отображает информацию, однако оно скомпилировано с использованием Visual Developer Studio 5(неуправляемый код) ... Однако мне нужно получить некоторую информацию из моего адаптера с помощью WMI .... Мои усилия по поиску в Google показывают, что мне нужно было бы написать приложение на C++ с использованием COM для достижения какой-либо формы связи с wMI или C# с приложением.NET a) Это действительно так? НЕТ работы вокруг моего приложения C? б) Если приведенное выше верно, каковы минимальные изменения уровня, необходимые для настройки моего проекта /wp /workspace?
Спасибо сом
2 ответа
Вы можете вызывать 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);
}
Другой вариант, если вы хотите сохранить низкий уровень воздействия на ваше существующее C-приложение, это написать DLL, которая внутри может использовать классы-обертки C++ и COM для запроса нужной информации WMI.
Эта DLL может предоставить простой интерфейс C для адаптации к вашему приложению. Вот так я бы поступил.