ローカルのネットワークケーブル切断検出、接続検出するために、IpHelperAPI を使ってみました。
いろいろ試行錯誤の結果、次のような手順でできることがわかったので、メモしておきます。
1.Iphlpapi.dllを読み込む
LoadLibrary( "Iphlpapi.dll" ) でおk
GetInterfaceInfo と GetIfEntry を GetProcAddress() しておきます
ここでは略しますが、あちきは IpHelperってなラッパークラスを用意しました。
2.GetInterfaceInfo でネットワークカードの情報を取得します。
NIC の数だけ取得しますから、情報のサイズが不明ですので、最初に NULL 渡してサイズを取得してから取り込みます。
こんな感じ。
DWORD size = 0;
DWORD rc = IpHelper->GetInterfaceInfo( NULL, &size );
if( rc == ERROR_INSUFFICIENT_BUFFER ){
IP_INTERFACE_INFO *IfTable = (IP_INTERFACE_INFO *)new char[ size ];
IpHelper->GetInterfaceInfo( IfTable, &size );
IfTable には、NIC の数と、IP_ADAPTER_INDEX_MAP 構造体の配列 Adapter[] が取り込まれます。カード1枚だと1個分です。
この IP_ADAPTER_INDEX_MAP 構造体メンバの Index 値が重要です。
先頭のIndexを取り出すには、
ULONG index = IfTable->Adapter[ 0 ].Index を取得します。
3.インデックス指定のネットワークデバイスの情報を取得します。
MIB_IFROW 構造体を用意し、そのメンバ dwIndex を取得した index にセットしてから GetIfEntry APIを呼び出します。
こんなかんじ。
MIB_IFROW IfRow;
::ZeroMemory( &IfRow, sizeof( IfRow ) );
IfRow.dwIndex = (DWORD)index;
DWORD rc = IpHelper->GetIfEntry( &IfRow );
ネットワークの接続状態は、MIB_IFROW 構造体メンバの dwOperStatus 値を見ます。
値が IF_OPER_STATUS_CONNECTED または IF_OPER_STATUS_OPERATIONAL であれば接続中状態です。
bool connected = ( IfRow.dwOperStatus == IF_OPER_STATUS_CONNECTED ) || ( IfRow.dwOperStatus == IF_OPER_STATUS_OPERATIONAL );
以上でネットワークケーブルの状態を検出することができました。
ホントはイベントとかメッセージでリアルタイムに渡してきてほしいけどな・・・
しかたがないので、スレッドを用意して500ミリ秒おきにネットワーク状態をスキャンして、変化があればメッセージを送出するスレッドクラスを作ってしまいました。
なかなかいい感じで検出できています。(^^)