[C++] WMI und WLAN
-
Hallo zusammen,
ich versuche grad WLAN-Daten über die MSNdis_80211-Klassen über WMI abzurufen. Leider wills bisher nicht so funktionieren. Auf die Win32-Klassen kann ich allerdings problemlos zugreifen.
Ich verwende den Code aus dem MSDN in abgeänderter Form, siehe auch http://pages.infinit.net/codeguru/WiFiArticle.htm ganz unten auf der Seite.
Hier der vollständige Code:
#define _WIN32_DCOM #include <iostream> using namespace std; #include <comdef.h> #include <Wbemidl.h> # pragma comment(lib, "wbemuuid.lib") int main(int argc, char **argv) { HRESULT hres; // Step 1: -------------------------------------------------- // Initialize COM. ------------------------------------------ hres = CoInitializeEx(0, COINIT_MULTITHREADED); if (FAILED(hres)) { cout << "Failed to initialize COM library. Error code = 0x" << hex << hres << endl; return 1; // Program has failed. } // Step 2: -------------------------------------------------- // Set general COM security levels -------------------------- // Note: If you are using Windows 2000, you need to specify - // the default authentication credentials for a user by using // a SOLE_AUTHENTICATION_LIST structure in the pAuthList ---- // parameter of CoInitializeSecurity ------------------------ hres = CoInitializeSecurity( NULL, -1, // COM authentication NULL, // Authentication services NULL, // Reserved RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation NULL, // Authentication info EOAC_NONE, // Additional capabilities NULL // Reserved ); if (FAILED(hres)) { cout << "Failed to initialize security. Error code = 0x" << hex << hres << endl; CoUninitialize(); return 1; // Program has failed. } // Step 3: --------------------------------------------------- // Obtain the initial locator to WMI ------------------------- IWbemLocator *pLoc = NULL; hres = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc); if (FAILED(hres)) { cout << "Failed to create IWbemLocator object." << " Err code = 0x" << hex << hres << endl; CoUninitialize(); return 1; // Program has failed. } // Step 4: ----------------------------------------------------- // Connect to WMI through the IWbemLocator::ConnectServer method IWbemServices *pSvc = NULL; // Connect to the root\wmi namespace with // the current user and obtain pointer pSvc // to make IWbemServices calls. hres = pLoc->ConnectServer( _bstr_t(L"ROOT\\WMI"), // Object path of WMI namespace NULL, // User name. NULL = current user NULL, // User password. NULL = current 0, // Locale. NULL indicates current NULL, // Security flags. 0, // Authority (e.g. Kerberos) 0, // Context object &pSvc // pointer to IWbemServices proxy ); if (FAILED(hres)) { cout << "Could not connect. Error code = 0x" << hex << hres << endl; pLoc->Release(); CoUninitialize(); return 1; // Program has failed. } cout << "Connected to ROOT\\WMI namespace" << endl; // Step 5: -------------------------------------------------- // Set security levels on the proxy ------------------------- hres = CoSetProxyBlanket( pSvc, // Indicates the proxy to set RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx NULL, // Server principal name RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx NULL, // client identity EOAC_NONE // proxy capabilities ); if (FAILED(hres)) { cout << "Could not set proxy blanket. Error code = 0x" << hex << hres << endl; pSvc->Release(); pLoc->Release(); CoUninitialize(); return 1; // Program has failed. } // Step 6: -------------------------------------------------- // Use the IWbemServices pointer to make requests of WMI ---- // For example, get the name of the operating system IEnumWbemClassObject* pEnumerator = NULL; hres = pSvc->ExecQuery( bstr_t("WQL"), bstr_t("SELECT * FROM MSNdis_80211_WEPStatus"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator); if (FAILED(hres)) { cout << "Query for WEP-status failed." << " Error code = 0x" << hex << hres << endl; pSvc->Release(); pLoc->Release(); CoUninitialize(); return 1; // Program has failed. } // Step 7: ------------------------------------------------- // Get the data from the query in step 6 ------------------- IWbemClassObject *pclsObj; ULONG uReturn = 0; while (pEnumerator){ HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); if(0 == uReturn) { break; } VARIANT vtProp; // Get the value of the WEP-Status property hr = pclsObj->Get(L"Ndis80211WEPStatus", 0, &vtProp, 0, 0); wcout << "Ndis80211WEPStatus : " << vtProp.iVal << endl; VariantClear(&vtProp); pclsObj->Release(); } // Cleanup // ======== pSvc->Release(); pLoc->Release(); pEnumerator->Release(); CoUninitialize(); cin.get(); return 0; // Program successfully completed. }
Die Abfrage scheint zu funktionieren. Allerdings bekomm ich kein Ergebnis (uReturn=0):
while (pEnumerator){ HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); if(0 == uReturn) { break; }
Kann mal jemand evtl. den Code testen und mir auf die Sprünge helfen, was ich falsch mache? Falls relevant: Mein Betriebssystem ist Windows 7.
Gruß
-
Hi,
So weit ich sehen kann funktioniert dein Code auch (unter XP), aber zur WMI Schnittstelle diverser Klassen kann ich folgendes aussagen: Sie wird nicht von allen Systemen vollständig implementiert. Während unter XP noch alle WMI-WLAN-Klassen mit Instanzen verfügbar waren, werden unter Vista/Win7 keine Instanzen mehr bereitgestellt.
Leider kann man sich nur auf die üblichen CIMV2 Klassen verlassen, die im Scripting eingesetzt werden. Die sind in der Regel immer auf allen System vorhanden. Bei den anderen Namensräumen muss man immer auf die Unterstützung der jeweiligen Platform achten.Unter C++ kann man aber mit der Native Wifi API an alle notwendigen Infos kommen: http://msdn.microsoft.com/en-us/library/ms706274(v=VS.85).aspx
Und diese API funktionierte (zumindest bei mir) dann mit allen Systemen ab XPcu
-
Mmhh,
hatte fast vermutet, dass es was mit dem Betriebssystem zu tun hat. Dann kommt das schonmal nicht für mich in Frage. Vielen Dank für den Hinweis mit der Native Wifi API. Ich werde mir das mal genauer ansehen.
Gruß
-
Habe es übrigens hinbekommen und poste hier mal den Code. Es werden nur die Daten des verbundenen WLAN-Netzes ausgegeben.
Eine Frage hab ich noch: Kann man auf einem Windows-Rechner eigentlich mit mehreren Netzwerken gleichzeitig verbunden sein?Gruß
#include <windows.h> #include <wlanapi.h> #include <iostream> using namespace std; #pragma comment(lib, "wlanapi.lib") void printError(DWORD); int main(){ HANDLE myHandle = NULL; DWORD returnCode = 0; DWORD highestApiVersion = 2; DWORD usedApiVersion = 0; PWLAN_INTERFACE_INFO_LIST wlanList = NULL; PWLAN_INTERFACE_INFO wlanInfo = NULL; PWLAN_AVAILABLE_NETWORK_LIST networkList = NULL; PWLAN_AVAILABLE_NETWORK networkInfo = NULL; unsigned int i, j, k; int wlanSignalStrength = 200; returnCode = WlanOpenHandle(highestApiVersion, NULL, &usedApiVersion, &myHandle); if (returnCode != ERROR_SUCCESS) printError(returnCode); else{ returnCode = WlanEnumInterfaces(myHandle, NULL, &wlanList); if (returnCode != ERROR_SUCCESS) printError(returnCode); else{ cout << "Anzahl vorhandener WLAN-Adapter: " << wlanList->dwNumberOfItems << endl << endl; for(i=0; i<wlanList->dwNumberOfItems; i++){ wlanInfo = (WLAN_INTERFACE_INFO *) &wlanList->InterfaceInfo[i]; if(wlanInfo->isState == wlan_interface_state_connected){ wcout << "Adapter: " << wlanInfo->strInterfaceDescription << endl; returnCode = WlanGetAvailableNetworkList(myHandle, &wlanInfo->InterfaceGuid, 0, NULL, &networkList); if (returnCode != ERROR_SUCCESS) printError(returnCode); else{ cout << "Anzahl gefundener WLAN-Netze: " << networkList->dwNumberOfItems << endl; for(j=0; j<networkList->dwNumberOfItems; j++){ networkInfo = (WLAN_AVAILABLE_NETWORK *) &networkList->Network[j]; if(networkInfo->dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED){ cout << "Verbundenes WLAN-Netzwerk: "; for(k=0; k<networkInfo->dot11Ssid.uSSIDLength; k++) cout << networkInfo->dot11Ssid.ucSSID[k]; wlanSignalStrength = -100 + networkInfo->wlanSignalQuality/2; cout << endl << "Signalstaerke: " << wlanSignalStrength << "dBm" << endl; } } } } } } } cin.get(); return 0; } void printError(DWORD errorCode){ switch(errorCode){ case ERROR_INVALID_PARAMETER: cout << "Falscher Parameter" << endl; break; case ERROR_INVALID_HANDLE: cout << "Handle nicht gefunden" << endl; break; case ERROR_NOT_ENOUGH_MEMORY: cout << "Zu wenig Speicher" << endl; break; case ERROR_REMOTE_SESSION_LIMIT_EXCEEDED: cout << "Zu viele Handles" << endl; break; case ERROR_NDIS_DOT11_POWER_STATE_INVALID: cout << "Power State Error" << endl; break; default: cout << "Anderer Fehler" << endl; } }
-
Auch wenn der Thread nicht mehr ganz neu ist: Wenn ich auf diese Art Informationen über die erreichbaren WLAN-Netzwerke ermittele, wie kann ich dann zusätzlich noch an die BSSID (=MAC-Adresse) des APS kommen? Die Struktur WLAN_AVAILABLE_NETWORK enthält ja leider nur die SSID (=Netzwerkname).