以前この掲示板でも質問があったようですが、
回答のURLがなくなっている為、改めて質問させていただきます。
WinInetのAPIでインターネット接続確認をしたく
現在InternetAttemptConnectを使っていますが、
ADSLのモデムを切断している際にアプリケーションが固まってしまいます。
対処方法などありましたら、是非ご教授お願いします。
ADSLはLAN接続扱いですので、
InternetGetConnectedState
を使うとよろしいかと思います。
余談ですが、この掲示板のログに無ければ、googleなどで検索すれば見つかるかもしれませんよ。googleにはキャッシュがあり、実際には消えていても、検索で引っかかればキャッシュに残っているかもしれません。
InternetGetConnectedState 使用してみましたが、接続していないのに接続していると認識されました。
googleで色々なワードで検索しましたが、InternetAttemptConnect,InternetGetConnectedState 以外に有用な情報は見つかりませんでした。もちろんキャッシュも確かめました。
検索のワードがよろしくないのでしょうか?
うちの環境では、InternetGetConnectedStateでLAN接続中/切断中が判別できます。
戻り値でなく、Flagsの値はどうなっています?
それと、ADSLのモデムを切っているときのIPアドレスはどうなっているのでしょうか。
もちろん、ルータが生きていればWANには接続できなくともInternetGetConnectedStateはTrueを返すと思います。ルータにもつながっていない状態でしょうか。
Halbow です。
ちょっと試してみました。
uses
WinInet;
const
INTERNET_RAS_INSTALLED =$10;
INTERNET_CONNECTION_OFFLINE =$20;
INTERNET_CONNECTION_CONFIGURED =$40;
procedure TForm1.Button1Click(Sender: TObject);
var
Flag:DWORD;
begin
Memo1.Clear;
if InternetGetConnectedState(@Flag,0) then begin
if (Flag and INTERNET_CONNECTION_MODEM) <> 0 then
Memo1.Lines.Add('CONNECTION_MODEM');
if (Flag and INTERNET_CONNECTION_LAN) <> 0 then
Memo1.Lines.Add('CONNECTION_LAN');
if (Flag and INTERNET_CONNECTION_PROXY) <> 0 then
Memo1.Lines.Add('CONNECTION_PROXY');
if (Flag and INTERNET_RAS_INSTALLED) <> 0 then
Memo1.Lines.Add('RAS_INSTALLED');
if (Flag and INTERNET_CONNECTION_OFFLINE) <> 0 then
Memo1.Lines.Add('CONNECTION_OFFLINE');
if (Flag and INTERNET_CONNECTION_CONFIGURED) <> 0 then
Memo1.Lines.Add('CONNECTION_CONFIGURED');
end else
Memo1.Lines.Add('No Connection');
end;
わたしの自宅では ADSL ですが、正常につながっているときも、無線 LAN カード
を引っこ抜いたとき(従ってルータにもつながっていない)も同じように Memo1 には
CONNECTION_LAN
RAS_INSTALLED
と表示されて、接続の有無は確認できませんでした。D5 sp1 in Win2k sp4 です。
Halbow です。
> 接続の有無は確認できませんでした。
これですが、取り外した直後はやはり確認できないのですが、そのまま放っておいて
5,6分後にまたボタンを押したら、
No Connection
と表示されました。再び 無線LANカードを押し込むと、10秒後でも
CONNECTION_LAN
RAS_INSTALLED
と表示されました。ですから、接続は素早く検出できますが、切断を検出するのには
少し時間がかかるようです。
Halbow です。
なんどもすみません。特定サイトにアクセスしてピングする感じで
uses
WinInet;
function CheckInternetConnect:Boolean;
var
hOpen,hURL:HINTERNET;
begin
result := false;
hOpen := InternetOpen('CIAAgent',INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);
if not Assigned(hOpen) then exit;
hURL := InternetOpenURL(hOpen,'http://www.google.com/intl/ja/',nil,0,0,0);
if not Assigned(hURL) then begin
InternetCloseHandle(hOpen);
exit;
end;
InternetCloseHandle(hURL);
InternetCloseHandle(hOpen);
result := true;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if CheckInternetConnect then
Label1.Caption := 'Connected'
else
Label1.Caption := 'Disconnected';
end;
こんなふうにしたら、接続・切断ともに数秒のうちに確認できました。
InternetOpenって、キャッシュを拾ったりしませんか?
前にそんなのがあったような気がします。
Halbow です。
> InternetOpenって、キャッシュを拾ったりしませんか?
さぁ、今回がはじめての WEB プログラミングでしたのでしりませんが、
InternetOpenURL() はこちらではキャッシュを拾いませんねぇ。
IE の設定にもよるのかも知れません。切断時に、IE を立ち上げると
自動的にオフライン表示するようになっている場合はキャッシュを
拾う可能性があるかもしれませんね。わたしの環境では
InternetGetConnectedState() よりは迅速な確認ができているようです。
InternetOpenURLでキャッシュを取得するかどうかはちょっとテストしてみます。
結果は後ほど。
別の案を。
GetIfTableを使用すれば、LANの状態は見れそうです。
ダイアルアップの環境がないので、そちらのテストはできていませんが。
うちでは、接続されている場合は、dwOperStatusが5(MIB_IF_OPER_STATUS_OPERATIONAL)が返り、切断されている場合は、dwOperStatusが0(MIB_IF_OPER_STATUS_NON_OPERATIONAL)が返ってきました。
サンプルソースです。
//----------------------------------------------------
//関数の定義Unit
unit IPHLPAPI;
interface
uses
Windows, Messages, SysUtils, Variants, Classes;
Const
MAX_INTERFACE_NAME_LEN = $100;
ERROR_SUCCESS = 0;
MAXLEN_IFDESCR = $100;
MAXLEN_PHYSADDR = 8;
MIB_IF_OPER_STATUS_NON_OPERATIONAL = 0 ;
MIB_IF_OPER_STATUS_UNREACHABLE = 1;
MIB_IF_OPER_STATUS_DISCONNECTED = 2;
MIB_IF_OPER_STATUS_CONNECTING = 3;
MIB_IF_OPER_STATUS_CONNECTED = 4;
MIB_IF_OPER_STATUS_OPERATIONAL = 5;
MIB_IF_TYPE_OTHER = 1;
MIB_IF_TYPE_ETHERNET = 6;
MIB_IF_TYPE_TOKENRING = 9;
MIB_IF_TYPE_FDDI = 15;
MIB_IF_TYPE_PPP = 23;
MIB_IF_TYPE_LOOPBACK = 24;
MIB_IF_TYPE_SLIP = 28;
MIB_IF_ADMIN_STATUS_UP = 1;
MIB_IF_ADMIN_STATUS_DOWN = 2;
MIB_IF_ADMIN_STATUS_TESTING = 3;
TYPE
MIB_IFROW = Record
wszName : Array[0 .. (MAX_INTERFACE_NAME_LEN*2-1)] of char;
dwIndex : LongInt;
dwType : LongInt;
dwMtu : LongInt;
dwSpeed : LongInt;
dwPhysAddrLen : LongInt;
bPhysAddr : Array[0 .. (MAXLEN_PHYSADDR-1)] of Byte;
dwAdminStatus : LongInt;
dwOperStatus : LongInt;
dwLastChange : LongInt;
dwInOctets : LongInt;
dwInUcastPkts : LongInt;
dwInNUcastPkts : LongInt;
dwInDiscards : LongInt;
dwInErrors : LongInt;
dwInUnknownProtos : LongInt;
dwOutOctets : LongInt;
dwOutUcastPkts : LongInt;
dwOutNUcastPkts : LongInt;
dwOutDiscards : LongInt;
dwOutErrors : LongInt;
dwOutQLen : LongInt;
dwDescrLen : LongInt;
bDescr : Array[0 .. (MAXLEN_IFDESCR - 1)] of Char;
end;
MIB_IFTABLE=record
dwNumEntries: DWORD;
table: Array[0 .. (MAXLEN_PHYSADDR-1)] of MIB_IFROW;
end;
PMIB_IFTABLE=^MIB_IFTABLE;
Function GetIfTable(
pIfTable : Pointer;
VAR pdwSize : LongInt;
bOrder : LongInt
): LongInt; StdCall;
implementation
Function GetIfTable; stdcall; external 'IPHLPAPI.DLL';
end.
//-----------------------------------------------------------
//こちらが使用例
uses
IPHLPAPI;
procedure TForm1.Button1Click(Sender: TObject);
var
Buf: array[0..1023] of char;
d: Integer;
IfTable: PMIB_IFTABLE;
i: integer;
begin
d := 0;
GetIfTable(nil, d, 0);
IfTable := SysGetMem(d);
if Assigned(IfTable) then
begin
if GetIfTable(IfTable, d,0) = NO_ERROR then
begin
for i := 0 to IfTable.dwNumEntries - 1 do
begin
Memo1.Lines.Add('');
Memo1.Lines.Add('dwIndex 0x' + IntToHex(IfTable.table[i].dwIndex, 8));
case IfTable.table[i].dwType of
MIB_IF_TYPE_OTHER:
Memo1.Lines.Add('dwType MIB_IF_TYPE_OTHER');
MIB_IF_TYPE_ETHERNET:
Memo1.Lines.Add('dwType MIB_IF_TYPE_ETHERNET');
MIB_IF_TYPE_TOKENRING:
Memo1.Lines.Add('dwType MIB_IF_TYPE_TOKENRING');
MIB_IF_TYPE_FDDI:
Memo1.Lines.Add('dwType MIB_IF_TYPE_FDDI');
MIB_IF_TYPE_PPP:
Memo1.Lines.Add('dwType MIB_IF_TYPE_PPP');
MIB_IF_TYPE_LOOPBACK:
Memo1.Lines.Add('dwType MIB_IF_TYPE_LOOPBACK');
MIB_IF_TYPE_SLIP:
Memo1.Lines.Add('dwType MIB_IF_TYPE_SLIP');
end;
Memo1.Lines.Add('dwMtu ' + IntToStr(IfTable.table[i].dwMtu));
Memo1.Lines.Add('dwSpeed ' + IntToStr(IfTable.table[i].dwSpeed));
Memo1.Lines.Add('dwPhysAddrLen ' + IntToStr(IfTable.table[i].dwPhysAddrLen));
Memo1.Lines.Add('bPhysAddr ' +
IntToHex(Integer(IfTable.table[i].bPhysAddr[0]), 2) +
IntToHex(Integer(IfTable.table[i].bPhysAddr[1]), 2) +
IntToHex(Integer(IfTable.table[i].bPhysAddr[2]), 2) +
IntToHex(Integer(IfTable.table[i].bPhysAddr[3]), 2) +
IntToHex(Integer(IfTable.table[i].bPhysAddr[4]), 2) +
IntToHex(Integer(IfTable.table[i].bPhysAddr[5]), 2)
);
Memo1.Lines.Add('dwAdminStatus ' + IntToStr(IfTable.table[i].dwAdminStatus));
Memo1.Lines.Add('dwOperStatus ' + IntToStr(IfTable.table[i].dwOperStatus));
Memo1.Lines.Add('dwLastChange ' + IntToStr(IfTable.table[i].dwLastChange));
Memo1.Lines.Add('dwInOctets ' + IntToStr(IfTable.table[i].dwInOctets));
Memo1.Lines.Add('dwInUcastPkts ' + IntToStr(IfTable.table[i].dwInUcastPkts));
Memo1.Lines.Add('dwInNUcastPkts ' + IntToStr(IfTable.table[i].dwInNUcastPkts));
Memo1.Lines.Add('dwInDiscards ' + IntToStr(IfTable.table[i].dwInDiscards));
Memo1.Lines.Add('dwInErrors ' + IntToStr(IfTable.table[i].dwInErrors));
Memo1.Lines.Add('dwInUnknownProtos ' + IntToStr(IfTable.table[i].dwInUnknownProtos));
Memo1.Lines.Add('dwOutOctets ' + IntToStr(IfTable.table[i].dwOutOctets));
Memo1.Lines.Add('dwOutUcastPkts ' + IntToStr(IfTable.table[i].dwOutUcastPkts));
Memo1.Lines.Add('dwOutNUcastPkts ' + IntToStr(IfTable.table[i].dwOutNUcastPkts));
Memo1.Lines.Add('dwOutDiscards ' + IntToStr(IfTable.table[i].dwOutDiscards));
Memo1.Lines.Add('dwOutErrors ' + IntToStr(IfTable.table[i].dwOutErrors));
Memo1.Lines.Add('dwOutQLen ' + IntToStr(IfTable.table[i].dwOutQLen));
Memo1.Lines.Add('dwDescrLen ' + IntToStr(IfTable.table[i].dwDescrLen));
IfTable.table[i].bDescr[IfTable.table[i].dwDescrLen]:=#0;
Memo1.Lines.Add('bDescr ' + IfTable.table[i].bDescr);
end;
end;
SysFreeMem(IfTable);
end;
InternetOpenURLのテストをしてみました。
オフラインで使用するにしてあっても問題なさそうです。
# WindowsXP Pro, IE6.0.2800.1106, Delphi7 Pro
ありがとう
ツイート | ![]() |