当前位置: 首页 > news >正文

获取系统的网络状态与无线网的信号强度(格数)

原文: 获取系统的网络状态与无线网的信号强度(格数)

一台电脑,有时通过有线网连接网络(调制解调器/局域网),如有网卡也可连接wifi。
那么如何获取WLAN是否连接,和相应的信号强度呢?

就以下俩点:

  • 获取电脑连网状态
  • 获取无线网络的信号强度

 获取电脑连网状态

 1. InternetGetConnectedState

此函数获取网络状态有延时,且对网上伤害较大,所以下面不用它~

在看下文之前,可以浏览:通过InternetGetConnectedState方法对网络状态的获取

如上InternetGetConnectedState方法介绍中

  • dwReversed必须设置为0
  • 通过输出值lpdwFlags可以获取当前网络连接的信息,通过拼装对比可以得到当前连接的网络类型,如拨号上网/局域网等
bool InternetGetConnectedState( out LPDWORD lpdwFlags, int dwReversed);

首先,添加非托管函数并调用,可以获取网络是否联网

//声明外部的函数
[DllImport("winInet.dll ")]
private static extern bool InternetGetConnectedState(ref int flag,int dwReserved);

 2. IsNetworkAlive

需要服务System Event Notification的支持(系统默认自动启动该服务),且需要安装最新的SDK(如.NET)

浏览:MSDN对IsNetworkAlive的详细描述

由API中翻译:该功能可在Windows XP、2000(或Windows NT 4.0与Internet Explorer 5或更高版本)上使用,在windows95或更高版本上使用Internet Explorer 5或更高版本。所以,一般的系统都是支持的

输出值lpdwFlags

具体类型的详细内容可链接QOCINFO structure

  • NETWORK_ALIVE_LAN=1 局域网(此处并非指有线网)
  • NETWORK_ALIVE_WAN=2 远程访问-拨号访问和vpn访问(此处并非只无线网,按DPI所示,指的是RAS connections)
  • NETWORK_ALIVE_AOL=4 无效的值。。。因为只有Win9x系统才有此第三个选项。参考链接

所以,lpdwFlags对是否无线网络,判断并不准确。

eg:无论是有线还是无线,如下图,我获取的值是1!1指的是局域网~~~

返回值(bool)

  • 当返回值为true,且无错误Code时,表示网络已连接
  • 当返回值为false,且无错误Code时,表示网络未连接

那么,错误Code(异常)怎么获取呢?

获取上一次异常Code-GetLastError

参考链接

此处推荐使用Marshal中的GetLastWin32Error,见如下源代码:

 1     /// <summary>
 2     ///   通过使用平台调用的最后一个非托管函数返回的错误代码返回调用具有 <see cref="F:System.Runtime.InteropServices.DllImportAttribute.SetLastError" /> 标志设置。
 3     /// </summary>
 4     /// <returns>最后一个错误代码设置通过调用 Win32 SetLastError 函数。</returns>
 5     [SecurityCritical]
 6     [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
 7     [MethodImpl(MethodImplOptions.InternalCall)]
 8     public static extern int GetLastWin32Error();

GetLastWin32Error可获取最后一个非托管函数的错误Code

 int errCode = Marshal.GetLastWin32Error(); 

值得注意的是,非托管函数声明时,要添加SetLastError=true;如:

1 [DllImport("sensapi.dll", SetLastError = true)]
2 private static extern bool IsNetworkAlive(out int connectionDescription);

 

综上,通过IsNetworkAlive可获取当前环境是否已经连接网络。

流程:网络是否连接->是否有无线网连接->获取无线网状态(信号强度)->返回网络状态

 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         else
24         {
25             networkStatus = wlanStatus;
26         }
27     }
28     return networkStatus;
29 }

那么,具体是否有线/还是无线网络,如何判断?见下文~

 

获取无线网络的信号强度

获取WLAN的名称与信号强度

无线网的信息,可以通过第三方开源ManagedWifi来获取。

ManagedWifi.Dll也可以从我的云盘下载:https://pan.baidu.com/s/1CjSUIMr0DuVqDZrdZCx_mA 密码:2d2o

下载后引用到项目中

1. WlanClient wlanClient = new WlanClient();

2. 循环foreach(WlanClient.WlanInterface wlanIface in wlanClient.Interfaces)

3. Wlan.WlanAvailableNetwork[] networks = wlanIface.GetAvailableNetworkList(0);

值得注意的是,

  • WlanClient只在有网卡的系统中能初始化--所以如果WlanClient不能初始化,且IsNetworkAlive返回true,则意味着当前是有线连接网线
  • WlanInterfacer的GetAvailableNetworkList方法,获取的是附近wifi热点列表,和任务栏下热点列表的顺序无关。
  • WlanAvailableNetwork的wlanSignalQuality信号强度,100以内,如要转换成信号格数,需要整除25
  • profileName,对已连接的热点profileName显示完整,未连接的热点profileName为empty.

定义枚举值:

暂时只定义了有线网和无线网的状态 

 1 /// <summary>
 2 /// 网络状态
 3 /// </summary>
 4 public enum NetworkStatus
 5 {
 6     Internet,
 7     InternetWithError,
 8     WifiWithError,
 9     WifiWithOneBar,
10     WifiWithTwoBars,
11     WifiWithThreeBars,
12     WifiWithFourBars,
13 }

获取无线网连接状态:

 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.profileName
16                         && (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 }

 

相关文章:

  • 实验-创建文件系统
  • 一直困扰设计师多年的Android 单位 dp
  • flask模板
  • request.getParameter() request.getAttribute()
  • 开发了一款写作软件(OSX,Windows),附带Electron开发指南
  • 大数据时代事业单位利用数据分析提高工作效率
  • 服务(service)使用指南
  • 循环数组赋值给对象并push到数组中
  • spring源码解析bean初始化与依赖注入四
  • linux根分区满了如何处理,查找大文件方法
  • 机器中的灵魂会是量子比特么?
  • Android lrucache 实现与使用(Android内存优化)
  • 趣谈网络协议:像小说一样的网络协议入门课
  • 5.16 Stacks and Queues
  • iBatis和MyBatis在使用ResultMap对应关系时的区别
  • 2017-08-04 前端日报
  • overflow: hidden IE7无效
  • PHP 的 SAPI 是个什么东西
  • weex踩坑之旅第一弹 ~ 搭建具有入口文件的weex脚手架
  • 阿里云应用高可用服务公测发布
  • 技术攻略】php设计模式(一):简介及创建型模式
  • 开发基于以太坊智能合约的DApp
  • 微信开源mars源码分析1—上层samples分析
  • 硬币翻转问题,区间操作
  • - 语言经验 - 《c++的高性能内存管理库tcmalloc和jemalloc》
  • 运行时添加log4j2的appender
  • 主流的CSS水平和垂直居中技术大全
  • nb
  • media数据库操作,可以进行增删改查,实现回收站,隐私照片功能 SharedPreferences存储地址:
  • 通过调用文摘列表API获取文摘
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • #HarmonyOS:基础语法
  • (4)Elastix图像配准:3D图像
  • (Forward) Music Player: From UI Proposal to Code
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (附源码)springboot教学评价 毕业设计 641310
  • (免费领源码)Python#MySQL图书馆管理系统071718-计算机毕业设计项目选题推荐
  • ..thread“main“ com.fasterxml.jackson.databind.JsonMappingException: Jackson version is too old 2.3.1
  • .NET Core Web APi类库如何内嵌运行?
  • .Net Core 中间件验签
  • .net 前台table如何加一列下拉框_如何用Word编辑参考文献
  • .NET连接MongoDB数据库实例教程
  • /run/containerd/containerd.sock connect: connection refused
  • /var/spool/postfix/maildrop 下有大量文件
  • :not(:first-child)和:not(:last-child)的用法
  • ?php echo $logosrc[0];?,如何在一行中显示logo和标题?
  • [ solr入门 ] - 利用solrJ进行检索
  • [ 英语 ] 马斯克抱水槽“入主”推特总部中那句 Let that sink in 到底是什么梗?
  • [04]Web前端进阶—JS伪数组
  • [CF494C]Helping People
  • [CSS]CSS 的背景
  • [Django ]Django 的数据库操作
  • [ffmpeg] av_opt_set 解析
  • [FxCop.设计规则]8. 也许参数类型应该是基类型
  • [iOS]Win8下iTunes无法连接iPhone版本的解决方法