C#でほぼ正確なインターネット接続状況を取得するためにはどうすればよいのか,色々模索したので備忘録として残しておきます.
前提環境 #
以下の環境を前提に記載していますが,それより多少古い環境でも動くと思います.
- Windows 11 Home (24H2)
- .NET 8
結論 #
Windowsのネットワークインジケーター(正確にはNCSI)と同等の性能でよいなら,Windows API の IsInternetConnect()
関数が使えます.
以下のような定義をC#ファイルで書けばアクセスできます.アクセス修飾子は適切なものに変更してください.
[DllImport("Connect.dll")]
private static extern int IsInternetConnected();
インターネットに接続されている場合は 0
(S_OK) が,そうでなければ 1
(S_FALSE) が返ってきます.
C/C++から使用する場合 #
Microsoft公式ドキュメント(英語)に以下の記述があります:
An import library containing the IsInternetConnected function is not included in the Microsoft Windows Software Development Kit (SDK). Applications must use the GetModuleHandle and GetProcAddress functions to retrieve the function pointer from the corresponding DLL and call this function.
IsInternetConnected 関数を含むこのライブラリは Microsoft Windows Software Development Kit (SDK) に含まれていません.各アプリケーションは GetModuleHandle と GetProcAddress 関数を用いて対応するDLLから関数ポインタを取得し,その関数を呼び出さなければなりません.
この関数をC/C++で使用する場合は,DLLから関数ポインタを引きずり出す必要があります.
HMODULE hModule = GetModuleHandle("Connect.dll");
FARPROC pIIC = GetProcAddress(hModule, "IsInternetConnected");
if (pIIC == NULL) {
// 関数ポインタの取得に失敗
} else {
HRESULT result = pIIC();
}
アクセスするサイトが決まっているなら #
そのアプリが特定のサイトにしかアクセスしないなら,直接アクセス先のサイトにHTTPリクエストなりPingなり飛ばしたほうがより的確に判断できると思います.
例えばプロキシ環境下などで,インターネットには繋がっているものの特定サイトにはアクセスできないという場合があるかもしれません.
他の方法 #
以下は自分が調べたときに出てきた方法です.
204サイトにアクセスする #
例えば,Googleなどが提供する204ページにリクエストを送ることでインターネットに接続できるか判断することができます.
http://clients3.google.com/generate_204
ただ,この方法は IsInternetConnected 関数の判断元となるNCSIでも同様の方法が用いられているため,こちらを採用するメリットはないかもしれません.
(宗教的にMicrosoftを使いたくないのであればこの方法を採用する手もあり)
.NET Framework の機能を使用する #
.NET Framework 2.0 以降,以下の関数やイベントが用意されています.挙動は名前どおりです.
NetworkInterface.GetIsNetworkAvailable
関数NetworkChange.NetworkAvailabilityChanged
イベント
こいつらはどうやらインターネットではなく ネットワーク の接続状況を見ている様子.
Windows NLM API を使用する #
Stack Overflow で見つけました.COM経由で Windows NLM API を使用できるようです.