在C++程序中开启和禁用Windows设备的无线网卡的方法
作者:全速前行
1.列出当前网卡:SetupDiEnumDeviceInfo
2.找出当前无线网卡的名字(用natvie wifi api)
3.卸载\安装此驱动
问题:
log为:SetupDiSetClassInstallParams failed. -536870347
完整代码如下:
// ControlWirelessCard.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <windows.h> #include <SetupAPI.h> #include <devguid.h> #include <string> #include <cfgmgr32.h> #include <wlanapi.h> #pragma comment(lib,"setupapi.lib") #pragma comment(lib, "wlanapi.lib") using namespace std; wstring getWirelessNetworkCardName() { wstring wirelessName; HANDLE hClient = NULL; DWORD dwMaxClient = 2; // DWORD dwCurVersion = 0; DWORD dwResult = 0; DWORD dwRetVal = 0; int iRet = 0; WCHAR GuidString[39] = {0}; unsigned int i; /* variables used for WlanEnumInterfaces */ PWLAN_INTERFACE_INFO_LIST pIfList = NULL; PWLAN_INTERFACE_INFO pIfInfo = NULL; dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &hClient); if (dwResult != ERROR_SUCCESS) { wprintf(L"WlanOpenHandle failed with error: %u\n", dwResult); return wirelessName; } dwResult = WlanEnumInterfaces(hClient, NULL, &pIfList); if (dwResult != ERROR_SUCCESS) { wprintf(L"WlanEnumInterfaces failed with error: %u\n", dwResult); return wirelessName; } else { PWLAN_AVAILABLE_NETWORK_LIST pWLAN_AVAILABLE_NETWORK_LIST = NULL; dwResult = WlanGetAvailableNetworkList(hClient, &pIfList->InterfaceInfo[0].InterfaceGuid, WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_MANUAL_HIDDEN_PROFILES, NULL, &pWLAN_AVAILABLE_NETWORK_LIST); if (dwResult != ERROR_SUCCESS) { printf("WlanGetAvailableNetworkList failed with error: %u\n",dwResult); WlanFreeMemory(pWLAN_AVAILABLE_NETWORK_LIST); return wirelessName; } for (i = 0; i < (int) pIfList->dwNumberOfItems; i++) { pIfInfo = (WLAN_INTERFACE_INFO *) &pIfList->InterfaceInfo[i]; iRet = StringFromGUID2(pIfInfo->InterfaceGuid, (LPOLESTR) &GuidString, sizeof(GuidString)/sizeof(*GuidString)); wirelessName = pIfInfo->strInterfaceDescription; } } return wirelessName; } BOOL changeStatus(DWORD NewStatus, DWORD SelectedItem, HDEVINFO hDevInfo) { LPTSTR lpszMsg = NULL; HCURSOR hCursor = NULL; try { SP_PROPCHANGE_PARAMS PropChangeParams = {sizeof(SP_CLASSINSTALL_HEADER)}; SP_DEVINFO_DATA DeviceInfoData = {sizeof(SP_DEVINFO_DATA)}; hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); // Get a handle to the Selected Item. if (!SetupDiEnumDeviceInfo(hDevInfo, SelectedItem, &DeviceInfoData)) { wprintf(L"SetupDiEnumDeviceInfo failed. %d\n",GetLastError()); throw lpszMsg; } // Set the PropChangeParams structure. PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; PropChangeParams.Scope = DICS_FLAG_GLOBAL; PropChangeParams.StateChange = NewStatus; if (!SetupDiSetClassInstallParams(hDevInfo, &DeviceInfoData, (SP_CLASSINSTALL_HEADER *)&PropChangeParams, sizeof(PropChangeParams))) { wprintf(L"SetupDiSetClassInstallParams failed. %d\n",GetLastError()); throw lpszMsg; } // Call the ClassInstaller and perform the change. if (!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,hDevInfo,&DeviceInfoData)) { wprintf(L"SetupDiCallClassInstaller failed. %d\n",GetLastError()); throw lpszMsg; } SetCursor(hCursor); return TRUE; } catch (TCHAR * pszError) { SetCursor(hCursor); if (NULL != lpszMsg) { LocalFree((HLOCAL)lpszMsg); } return FALSE; } } int _tmain(int argc, _TCHAR* argv[]) { LPTSTR lpszMsg = NULL; try { /* TCHAR * GUIDString = NULL; GUID guid; ZeroMemory(&guid, sizeof(GUID)); GUIDString = _T("4d36e972-e325-11ce-bfc1-08002be10318"); UuidFromString((unsigned char *)GUIDString, &guid); */ //GUID guid = getWirelessNetworkCardGUID(); HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_NET,/*L"WIRELESS"*/NULL,NULL,DIGCF_PRESENT); //HDEVINFO hDevInfo = SetupDiGetClassDevs(&guid,/*L"WIRELESS"*/NULL,NULL,DIGCF_PRESENT); if (INVALID_HANDLE_VALUE == hDevInfo) { wprintf(L"INVALID_HANDLE_VALUE"); return -1; } DWORD i; int Icount=0; SP_DEVINFO_DATA DeviceInfoData; ZeroMemory(&DeviceInfoData, sizeof(SP_DEVINFO_DATA)); DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData); ++i) { //Get DeviceInfo LPTSTR buffer = NULL; DWORD buffersize = 0; DWORD Status, Problem; BOOL bDisabled = FALSE; while (!SetupDiGetDeviceRegistryProperty( hDevInfo, &DeviceInfoData, SPDRP_DEVICEDESC, //Read the names of the designated card NULL, (PBYTE) buffer, buffersize, &buffersize) ) { if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) { if (buffer) LocalFree(buffer); buffer=(LPTSTR)LocalAlloc(LPTR,buffersize); } else { wprintf(L"read network card failed!"); } } std::wstring strEthernet = buffer; //wprintf(L"the buffer is %ws\n",buffer); wstring wirelessName = getWirelessNetworkCardName(); if(wirelessName.empty()) { wprintf(L"wirelessName IS empty\n"); return -1; } //wprintf(L"wirelessName is %ws\n",wirelessName); if(wirelessName == buffer) { wprintf(L"Found the wireless card: %ws\n",wirelessName); if (int i= CM_Get_DevNode_Status(&Status, &Problem, DeviceInfoData.DevInst,0) != CR_SUCCESS) { wprintf(L"CM_Get_DevNode_Status failed. %d\n",GetLastError()); throw "failed\n"; } if (!((Status & DN_HAS_PROBLEM) && (CM_PROB_DISABLED == Problem))) { bDisabled = FALSE; } if ((Status & DN_HAS_PROBLEM) && (CM_PROB_DISABLED == Problem)) { bDisabled = TRUE; } if(bDisabled==FALSE) { wprintf(L"disable the network card\n"); changeStatus(DICS_DISABLE, i, hDevInfo);//disable } if(bDisabled==TRUE) { wprintf(L"enable the network card\n"); changeStatus(DICS_ENABLE, i, hDevInfo);// enable } } } return SetupDiDestroyDeviceInfoList(hDevInfo); } catch (TCHAR * pszError) { if (NULL != lpszMsg) { LocalFree((HLOCAL)lpszMsg); } return FALSE; } return 0; }
一些常见错误解决
一、
从错误返回值入手。
-536870347,用windows自带计算器,选择程序员模式,将此十进制转换为16进制为E0000235.
用此错误号搜索,就是大名鼎鼎的32位程序跑在64位系统中报错。
虽然我用的64位win8下VS编译的程序,但是编译选项中仍然是WIN32程序。那么我们只需要修改成x64编译即可,操作如下。
BUILD-->Configuration Manager...-->找到要修改的project,将platform选择为x64.
如果没有,说明没有添加x64编译项,接着上面,在platform中选择<New...> -->New platform下选x64-->OK.
二、
编译64位程序,运行之。
仍然报错,返回值是5.ACCESS_DENIED.
权限不够,我们需要申请高权限。如下申请Admin权限:
你项目的Properties-->Linker-->Manifest File-->UAC Execution Level选requireAdministrator。
三、
继续运行。卸载无线网卡驱动成功。
但是上一篇的程序仍然有个问题,由于驱动卸载了,就不能用wlan api得到无线网卡名称,
所以程序加载无线网卡驱动就会失败。
我们可以用关键字“Wireless Network Adapter”来查找无线网卡,省掉使用wlan api那一步。