Как получить данные из 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 для адаптации к вашему приложению. Вот так я бы поступил.

Другие вопросы по тегам