调用Windows API
在C#中可以通过Pinvoke调用windows API方式来进行网络连接的检查:
[DllImport("wininet.dll", SetLastError=true)]
extern static bool InternetGetConnectedState(out int lpdwFlags, int dwReserved);
[Flags]
enum ConnectionStates
{
Modem = 0x1,
LAN = 0x2,
Proxy = 0x4,
RasInstalled = 0x10,
Offline = 0x20,
Configured = 0x40,
}
MSDN地址 https://learn.microsoft.com/en-us/windows/win32/api/wininet/nf-wininet-internetgetconnectedstate 对应的返回值Description如下:
Value | Meaning |
---|---|
INTERNET_CONNECTION_CONFIGURED0x40 | Local system has a valid connection to the Internet, but it might or might not be currently connected. |
INTERNET_CONNECTION_LAN0x02 | Local system uses a local area network to connect to the Internet. |
INTERNET_CONNECTION_MODEM0x01 | Local system uses a modem to connect to the Internet. |
INTERNET_CONNECTION_MODEM_BUSY0x08 | No longer used. |
INTERNET_CONNECTION_OFFLINE0x20 | Local system is in offline mode. |
INTERNET_CONNECTION_PROXY0x04 | Local system uses a proxy server to connect to the Internet. |
INTERNET_RAS_INSTALLED0x10 | Local system has RAS installed. |
例子 :
using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication2
{
internal class Program
{
[DllImport("wininet.dll", SetLastError = true)]
private static extern bool InternetGetConnectedState(out int lpdwFlags, int dwReserved);
private static void Main(string[] args)
{
int flags;
bool isConnected = InternetGetConnectedState(out flags, 0);
Console.WriteLine(string.Format("Is connected :{0} Flags:{1}", isConnected, flags));
}
}
}
使用NCSI
Windows进行网络检查的地址是 http://www.msftconnecttest.com/connecttest.txt
这些配置可以在注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NlaSvc\Parameters\Internet
中找到。注册表内容可以参考这个项目。下面是通过NCSI来检查网络是否连接的代码:
首先先遍历注册表相关的键值对,因为用户可能修改相关配置。
public Dictionary<string, string> GetNCSIData()
{
RegistryKey internetKey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Services\NlaSvc\Parameters\Internet");
if (internetKey != null)
{
Dictionary<string, string> NCSIData = new Dictionary<string, string>();
string[] valueNames = internetKey.GetValueNames();
foreach (string key in valueNames)
{
object value = internetKey.GetValue(key);
if (value is string v)
{
NCSIData.Add(key, v);
}
}
return NCSIData;
}
return null;
}
然后进行检查
public async Task<bool> IsInternetConnected()
{
var ncsiDataDic = GetNCSIData();
string probeHost = ncsiDataDic["ActiveDnsProbeHost"];
string NCSIDnsIpAddress = ncsiDataDic["ActiveDnsProbeContent"];
string webProbeHost = ncsiDataDic["ActiveWebProbeHost"];
string WebProbePath = ncsiDataDic["ActiveWebProbePath"];
string NCSITestResult = ncsiDataDic["ActiveWebProbeContent"];
string NCSITestUrl = new UriBuilder()
{
Scheme = "http",
Host = webProbeHost,
Port = 80,
Path = WebProbePath
}.Uri.ToString();
string NCSIDns = probeHost;
try
{
using (var webClient = new WebClient())
{
string result = await webClient.DownloadStringTaskAsync(NCSITestUrl);
if (result != NCSITestResult)
{
return false;
}
}
// Check NCSI DNS IP
var dnsIpAddresses = await Dns.GetHostAddressesAsync(NCSIDns);
return dnsIpAddresses.Any(addr => addr.ToString() == NCSIDnsIpAddress);
}
catch (Exception )
{
return false;
}
}
其他方式
可以参考下 Stackoverflow这个问题 https://stackoverflow.com/questions/520347/how-do-i-check-for-a-network-connection