Как получить данные из WMI с помощью Приложения C?

Нет наверняка никакого прямого способа сделать это в Ruby (по крайней мере, не было, когда я пытался сделать это несколько месяцев назад). Если Вы действительно не можете постараться не генерировать свой pdfs от HTML, необходимо, вероятно, навести справки о некоторых внешних инструментах или сервисах с этой целью.

Удачи!

6
задан smam 16 September 2009 в 05:24
поделиться

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 перед тем, как продолжить каждый шаг).

Это консольное приложение Win32 Visual Studio 2008 с основным файлом, переименованным в расширение .c, и дополнительным stdafx файлы удалены. Чтобы связать программу, обязательно включите wbemuuid.lib в свойствах проекта в разделе Configuration Properties / Linker / Input / Additional Dependencies. Он успешно работал на моем компьютере с 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);
}
13
ответ дан 8 December 2019 в 16:06
поделиться

Другой вариант, если вы хотите снизить влияние на существующее приложение C, - это написать DLL, которая внутренне может использовать классы-оболочки C ++ и COM для запроса желаемой информации WMI.

Эта DLL может предоставить простой интерфейс C для адаптации к вашему приложению. Я бы пошел по этому пути.

2
ответ дан 8 December 2019 в 16:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: