Delphi XE5 で PING を使ってみる
Indy の IdIcmpClient.Ping() を使う場合は、exe を管理者権限で実行する必要があるようです。
ネット上に、Winsock を使ったサンプルがあったので、試してみました。
unit xpingUnit; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Winsock, Vcl.StdCtrls; type TForm1 = class(TForm) Memo1: TMemo; Button1: TButton; Edit1: TEdit; Edit2: TEdit; Button2: TButton; Label1: TLabel; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private 宣言 } public { Public 宣言 } runFlag : boolean; end; var Form1: TForm1; // icmp.dll function IcmpCreateFile : THandle; stdcall; external 'icmp.dll'; function IcmpCloseHandle (icmpHandle : THandle) : boolean; stdcall; external 'icmp.dll'; function IcmpSendEcho ( IcmpHandle : THandle; DestinationAddress : TInAddr; RequestData : Pointer; RequestSize : Smallint; RequestOptions : Pointer; ReplyBuffer : Pointer; ReplySize : DWORD; Timeout : DWORD) : DWORD; stdcall; external 'icmp.dll'; implementation {$R *.dfm} // ----------------------------------------------- // uses Winsock // http://homepage1.nifty.com/MADIA/delphi/delphi_bbs/200607/200607_06070018.html // 「同一LAN内のIPAdressやMacAdressを取得するには?」 // ほぼ、そのままのコードです。 // ----------------------------------------------- // IP アドレスからホスト名を得る function GetHostName(Ip : AnsiString) : AnsiString; var PH : PHostEnt; InAddr: TInAddr; WSADATA : TWSADATA; begin Result := ''; if Ip = '' then Exit; InAddr.S_addr := inet_addr(PAnsiChar(Ip)); WSAStartup(MakeWord(1, 1) , WSADATA); //MakeWord(1,1)=$0101 PH := GetHostByAddr(@InAddr, 4, PF_INET); if PH = nil then Exit; Result := AnsiString(PH^.h_name); WSACleanup; end; // ホスト名から IP アドレスを得る function GetIpAddress(HostName : AnsiString) : AnsiString; var PH : PHostEnt; InAddr: TInAddr; WSADATA : TWSADATA; begin Result := ''; if HostName = '' then Exit; WSAStartup(MakeWord(1, 1), WSADATA); PH := GetHostByName(PAnsiChar(HostName)); if PH = nil then Exit; InAddr := PInAddr(PH^.h_addr_list^)^; Result := inet_ntoa(InAddr); WSACleanup; end; // PING function PingIP(Ip : Ansistring) : boolean; var Hnd : THandle; InAddr : TInAddr; DW : DWORD; rep : array [1..128] of byte; begin result := false; Hnd := IcmpCreateFile; if Hnd = INVALID_HANDLE_VALUE then Exit; InAddr.S_addr := inet_addr(PAnsiChar(Ip)); DW := IcmpSendEcho(Hnd, InAddr, nil, 0, nil, @rep, 128, 500{Timeout}); Result := DW <> 0; IcmpCloseHandle(Hnd); end; // 自PCのIPアドレスとPC名を取得 function LocalIP(var PcName: AnsiString): Ansistring; type TaPInAddr = array [0..10] of PInAddr; PaPInAddr = ^TaPInAddr; var PH : PHostEnt; pPtr: PaPInAddr; buffer: array [0..127] of AnsiChar; i: Integer; GInitData: TWSAData; begin WSAStartup(MakeWord(1, 1), GInitData); Result := ''; PcName := ''; GetHostName(buffer); PH := GetHostByName(buffer); if PH = nil then Exit; PcName := AnsiString(PH^.h_name); pPtr := PaPInAddr(PH^.h_addr_list); i := 0; while pPtr^[i] <> nil do begin Result := inet_ntoa(pPtr^[i]^); Inc(i); end; WSACleanup; end; // 自PCのIPアドレスとPC名を得る procedure TForm1.Button1Click(Sender: TObject); var Ip : AnsiString; PcName : AnsiString; begin Edit1.Text := ''; Edit2.Text := ''; Ip := LocalIP(PcName); if Ip <> '' then begin Edit1.Text := string(Ip); Edit2.Text := string(PcName); end; end; procedure TForm1.Button2Click(Sender: TObject); var i : integer; n : integer; IpHead : Ansistring; Ip : Ansistring; begin if Button2.Caption = 'PING' then begin runFlag := True; Button2.Caption := 'Break'; Memo1.Lines.Clear; IpHead := '192.168.0.'; n := LastDelimiter('.', Edit1.Text); if n > 0 then IpHead := AnsiString(Copy(String(Edit1.Text), 1, n)); for i := 0 to 255 do begin if runFlag then begin Application.ProcessMessages; IP := IpHead + AnsiString(IntToStr(i)); Label1.Caption := String(IP); Label1.Refresh; if PingIp(Ip) then Memo1.Lines.Add(String(Ip + AnsiString(StringOfChar(' ', 16 - Length(ip))) + GetHostName(Ip))); end else Break; end; if runFlag then Memo1.Lines.Add('---- term ----') else Memo1.Lines.Add('---- break ----'); end else begin runFlag := False; Button2.Caption := 'PING'; Application.ProcessMessages; end; end; procedure TForm1.FormCreate(Sender: TObject); begin Button1.Caption := 'LocalIP'; Button2.Caption := 'PING'; Edit1.Text := ''; Edit2.Text := ''; Label1.Caption := ''; Memo1.Lines.Clear; end; end.