本文共 6094 字,大约阅读时间需要 20 分钟。
一台电脑,有时通过有线网连接网络(调制解调器/局域网),如有网卡也可连接wifi。
那么如何获取WLAN是否连接,和相应的信号强度呢?就以下俩点:
在看下文之前,可以浏览MSDN:
如上InternetGetConnectedState方法介绍中
bool InternetGetConnectedState( out LPDWORD lpdwFlags, int dwReversed);
首先,添加非托管函数并调用,可以获取网络是否联网
//声明外部的函数[DllImport("winInet.dll ")]private static extern bool InternetGetConnectedState(ref int flag,int dwReserved);
需要服务System Event Notification的支持(系统默认自动启动该服务),且需要安装最新的SDK(如.NET)
浏览:
由API中翻译:该功能可在Windows XP、2000(或Windows NT 4.0与Internet Explorer 5或更高版本)上使用,在windows95或更高版本上使用Internet Explorer 5或更高版本。所以,一般的系统都是支持的
具体类型的详细内容可链接
所以,lpdwFlags对是否无线网络,判断并不准确。
eg:无论是有线还是无线,如下图,我获取的值是1!1指的是局域网~~~
那么,错误Code(异常)怎么获取呢?
此处推荐使用Marshal中的GetLastWin32Error,见如下源代码:
1 ///2 /// 通过使用平台调用的最后一个非托管函数返回的错误代码返回调用具有 4 ///标志设置。 3 /// 最后一个错误代码设置通过调用 Win32 SetLastError 函数。 5 [SecurityCritical] 6 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 7 [MethodImpl(MethodImplOptions.InternalCall)] 8 public static extern int GetLastWin32Error();
GetLastWin32Error可获取最后一个非托管函数的错误Code
int errCode = Marshal.GetLastWin32Error();
--获取 error code的详细描述信息,可参考
值得注意的是,非托管函数声明时,要添加SetLastError=true;如:
1 [DllImport("sensapi.dll", SetLastError = true)]2 private static extern bool IsNetworkAlive(out int connectionDescription);
流程:网络是否连接->是否有无线网连接->获取无线网状态(信号强度)->返回网络状态
1 [DllImport("sensapi.dll", SetLastError = true)] 2 private static extern bool IsNetworkAlive(out int connectionDescription); 3 public NetworkStatus GetNetworkStatusByNetworkAlive() 4 { 5 var networkStatus = NetworkStatus.InternetWithError; 6 7 int flags = 0; 8 var isNetworkAlive = IsNetworkAlive(out flags); 9 10 int errCode = Marshal.GetLastWin32Error();11 if (errCode != 0)12 {13 throw new InvalidOperationException($"通过{nameof(IsNetworkAlive)}非托管DLL,获取网络状态时,遇到异常");14 }15 if (isNetworkAlive)16 {17 // 获取WLAN网络状态18 var wlanStatus = GetWlanStatus();19 if (isNetworkAlive && wlanStatus == NetworkStatus.WifiWithErro)20 {21 networkStatus = NetworkStatus.Internet;22 }23 else24 {25 networkStatus = wlanStatus;26 }27 }28 return networkStatus;29 }
如上,获取网络状态是否连接,建议通过IsNetworkAlive函数获取。那么IsNetworkAlive是否准确呢?
答案是否!
案例:
所以:IsNetworkAlive函数,建议可以用来,减少断网后请求服务器的次数,或者对有网情况下网络的判断(暂时没发现有网时判断出错的问题)
或者也可以直接使用ping
1 using (var ping = new Ping())2 {3 //ping给定的host,超时时间为1s4 var reply = ping.Send(host, 1000);5 var pingResult= reply != null && reply.Status == IPStatus.Success;6 }
网络状态枚举值:
暂时只定义了有线网和无线网的状态
1 ///2 /// 网络状态 3 /// 4 public enum NetworkStatus 5 { 6 Internet, 7 InternetWithError, 8 WifiWithErro, 9 WifiWithOneBar,10 WifiWithTwoBars,11 WifiWithThreeBars,12 WifiWithFourBars,13 }
那么,具体是否有线/还是无线网络,如何判断?见下文~
获取WLAN的名称与信号强度
无线网的信息,可以通过第三方开源来获取。
ManagedWifi.Dll也可以从我的云盘下载: 密码:2d2o
下载后引用到项目中
1. WlanClient wlanClient = new WlanClient();
2. 循环foreach(WlanClient.WlanInterface wlanIface in wlanClient.Interfaces)
3. Wlan.WlanAvailableNetwork[] networks = wlanIface.GetAvailableNetworkList(0);
值得注意的是,
获取无线网连接状态:
1 private NetworkStatus GetWlanStatus() 2 { 3 var wlanStatus = NetworkStatus.WifiWithErro; 4 try 5 { 6 WlanClient wlanClient = new WlanClient(); 7 8 foreach (WlanClient.WlanInterface wlanIface in wlanClient.Interfaces) 9 {10 if (wlanIface.InterfaceState == Wlan.WlanInterfaceState.Connected && wlanIface.CurrentConnection.isState == Wlan.WlanInterfaceState.Connected)11 {12 Wlan.WlanAvailableNetwork[] networks = wlanIface.GetAvailableNetworkList(0);13 foreach (var network in networks)14 {15 if (network.profileName == wlanIface.CurrentConnection.profileName16 && (int)network.flags == (int)(Wlan.WlanAvailableNetworkFlags.Connected | Wlan.WlanAvailableNetworkFlags.HasProfile))17 {18 switch (network.wlanSignalQuality / 25)19 {20 case 0:21 wlanStatus = NetworkStatus.WifiWithOneBar;22 break;23 case 1:24 wlanStatus = NetworkStatus.WifiWithTwoBars;25 break;26 case 2:27 wlanStatus = NetworkStatus.WifiWithThreeBars;28 break;29 default:30 wlanStatus = NetworkStatus.WifiWithFourBars;31 break;32 }33 break;34 }35 }36 break;37 }38 }39 }40 catch (Exception e)41 {42 }43 return wlanStatus;44 }
关键字:网络连接状态NetworkStatus,无线网络强度(格数),ManagedWifi,IsNetworkAlive,GetLastError