2009-09-16 12 views
6

Mam czystą aplikację C, która wywołuje wywołania IOCTL do mojego sterownika karty i wyświetla informacje, jest to jednak kompilowane przy użyciu Visual Developer Studio 5 (niezarządzanego kodu) ... Muszę jednak uzyskać pewne informacje z mojego adaptera za pomocą WMI ... Moje wysiłki związane z szukaniem hasła pokazują, że będę musiał napisać aplikację C++ za pomocą COM, aby osiągnąć dowolną formę komunikacji z wMI lub C# z aplikacją .NET a) Czy tak naprawdę jest tak? ŻADNY nie obejść dla mojej aplikacji C? b) Jeśli powyższe jest prawdziwe, jakie są minimalne zmiany poziomu, które musiałbym wykonać w ustawieniach projektu/wp/przestrzeni roboczej?Jak uzyskać dane z WMI za pomocą aplikacji C?

Dzięki Som

Odpowiedz

13

Można powołać COM z C. Składnia jest nieco mniej przyjazny niż C++, ale to działa. COM został pierwotnie zaprojektowany do pracy z C lub C++, a natywna obsługa języka C jest zawarta w plikach nagłówkowych COM i WMI. Będzie jednak długo ... Twój program będzie odpowiedzialny za przydzielenie wszystkich potrzebnych obiektów, sprawdzanie warunków błędów od każdego wywołania COM i uwolnienie obiektów, które zostały utworzone.

Podczas korzystania dokumentację pisemną z C++ na uwadze, konwersja połączenia COM w postaci:

pSomething->Method(arg1, ...); // C++ 

do:

pSomething->lpVtbl->Method(pSomething, arg1, ...); // C 

Poniżej jest najkrótszy kawałek kodu C mogłem dostać się do faktycznie ciągnąć niektóre informacje z WMI. Jeśli się powiedzie, powinien wymienić procesory na komputerze wraz z częstotliwością taktowania w MHz. Program zajmuje się wyrzucaniem przydzielonych zasobów, ale nie sprawdza żadnych błędów (powinieneś spojrzeć na te wartości hr przed kontynuowaniem każdego kroku).

To jest wizualne studio 2008 "Win32 Console Application" z głównym plikiem zmienionym na rozszerzenie .c, a dodatkowe pliki stdafx usunięte. Aby uzyskać dostęp do programu, upewnij się, że wbemuuid.lib zawiera właściwości projektu, w obszarze Właściwości konfiguracji/Linker/Wejście/Dodatkowe zależności. Uruchomił się pomyślnie na moim pudełku 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); 
} 
+0

Hi Oren, Dzięki ton, który pracował jak mistrz na Win2008 .Jednak wpadłem na kwestie kompilacji kiedy pierwszy raz spróbowałem w Visual Studio 2005, umieszczając je poniżej: error C2065: „COINIT_MULTITHREADED”: niezadeklarowany identyfikator błąd C2065: "EOAC_NONE": niezadeklarowany identyfikator Czy masz pomysł, jak je rozwiązać na rok 2005? Dzięki Som – smam

+0

Spróbuj dodać #define _WIN32_WINNT 0x0400 i #define _WIN32_DCOM przed dołączeniem plików. Jeśli to nie rozwiąże problemu, po prostu zastąp obie brakujące stałe wartością 0. –

+0

Hi Oren, Tak, zadziałało to przy pierwszym zderzeniu, po raz kolejny bardzo dziękuję Som – smam

2

Inną opcją, jeśli chcesz zachować wpływ na istniejącej aplikacji C niskie, to napisać DLL, która wewnętrznie mogą używać C++ i klas COM otoki kwerendy żądane informacje WMI.

Ta biblioteka DLL może zapewniać zwykły interfejs C w celu dostosowania do aplikacji. To tak, jak chciałbym.

+1

Absolutnie, obsługa wszystkich rzeczy COM w C to nie tylko ból, ale także zupełnie inny poziom abstrakcji w porównaniu do rzeczywistej aplikacji. – Wolf

Powiązane problemy