Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Ping mit HostName (https://www.delphipraxis.net/217226-ping-mit-hostname.html)

Alucard 25. Mai 2025 13:10

Ping mit HostName
 
Moins.

Ich benutze die unten zitierte Unit, um Geräte im lokalen Netzwerk anzupingen. Im Wesentlichen will ich eigentlich nur wissen, ob mein Programm in meiner heimischen Umgebung ausgeführt wird bzw. ob mein heimischer ChromecastAudio erreichbar ist.

Die zitierte Unit funktioniert super, so lange ich mit IP-Adressen arbeite. Die IP des Chromecast ist daheim statisch und bekannt. Über einen Ping auf diese IP könnte es in fremden Netzwerken allerdings zu einer falsch-positiven Antwort kommen, falls durch Zufall ein Gerät mit der gleichen IP vorhanden ist. Wenn ich einen Hostnamen nutze, der im gerade verbundenen Netzwerk vorhanden ist, funktioniert die Unit auch fehlerfrei (/Cpt. Obvious). Sobald ich aber irgendwo bin, wo mein Chromecast nicht vorhanden ist und der Hostname also nicht bekannt ist, wirft Delphi beim Aufrufen von "PingHost('HostName_meines_Chromecast')" folgenden Fehler:
Code:
Im Projekt Blablub.exe ist eine Exception der Klasse EOSError mit der Meldung 'Systemfehler. Code: 11002.
Dies ist normalerweise ein zeitweiliger Fehler bei der Auflösung von Hostnamen. Grund ist, dass der lokale Server keine Rückmeldung vom autorisierenden Server erhalten hat' aufgetreten.
Vermutlich lässt sich der Fehler leicht beheben, aber da ich doof bin und die Unit nur irgendwoher geklaut habe, verstehe ich sie nicht ganz :?

Alternativ würde für mich auch reichen, die SSID des gerade verbundenen WLANs abzugleichen, aber das scheint auch nicht so wirklich trivial zu sein... :shock:

Code:
unit Ping2;

interface

function PingHost(const HostName : AnsiString; TimeoutMS : cardinal = 500) : boolean;

implementation

uses Windows, SysUtils, WinSock;

function IcmpCreateFile: THandle;
  stdcall; external 'iphlpapi.dll';
function IcmpCloseHandle(icmpHandle: THandle): boolean;
  stdcall; external 'iphlpapi.dll';
function IcmpSendEcho(icmpHandle: THandle; DestinationAddress: In_Addr;
  RequestData: Pointer; RequestSize: Smallint; RequestOptions: Pointer;
  ReplyBuffer: Pointer; ReplySize: DWORD; Timeout: DWORD): DWORD; stdcall;
  external 'iphlpapi.dll';

type
  TEchoReply = packed record
    Addr: In_Addr;
    Status: DWORD;
    RoundTripTime: DWORD;
  end;

  PEchoReply = ^TEchoReply;

var
  WSAData: TWSAData;


procedure Startup;
begin
  if WSAStartup($0101, WSAData) <> 0 then
    raise Exception.Create('WSAStartup');
end;


procedure Cleanup;
begin
  if WSACleanup <> 0 then
    raise Exception.Create('WSACleanup');
end;


function PingHost(const HostName: AnsiString; TimeoutMS: cardinal = 500): boolean;
const
  rSize = $400;
var
  e: PHostEnt;
  a: PInAddr;
  h: THandle;
  d: string;
  r: array [0 .. rSize - 1] of byte;
  i: cardinal;
begin
  Startup;
  e := gethostbyname(PAnsiChar(HostName));
  if e = nil then
    RaiseLastOSError;
  if e.h_addrtype = AF_INET then
    Pointer(a) := e.h_addr^
  else
    raise Exception.Create('Name doesn''t resolve to an IPv4 address');

  d := FormatDateTime('yyyymmddhhnnsszzz', Now);

  h := IcmpCreateFile;
  if h = INVALID_HANDLE_VALUE then
    RaiseLastOSError;
  try
    i := IcmpSendEcho(h, a^, PChar(d), Length(d), nil, @r[0], rSize, TimeoutMS);
    Result := (i <> 0) and (PEchoReply(@r[0]).Status = 0);
  finally
    IcmpCloseHandle(h);
  end;
  Cleanup;
end;


end.

Uwe Raabe 25. Mai 2025 13:28

AW: Ping mit HostName
 
Ich vermute, das
Delphi-Quellcode:
RaiseLastOSError
ist hier der Auslöser der Meldung.

Wenn du nur wissen willst, ob das Ping erfolgreich war, und dir ein nicht gefundener Host egal ist, dann kannst du das
Delphi-Quellcode:
RaiseLastOSError
auch einfach mit einem
Delphi-Quellcode:
Exit(False)
ersetzen. Ebenso würde ich das mit dem
Delphi-Quellcode:
raise Exception
ein paar Zeilen darunter machen.

himitsu 25. Mai 2025 13:35

AW: Ping mit HostName
 
Und d soll wirklich als Unicode und mit Längenangabe in Char anstatt Byte so korrekt sein?

Alucard 25. Mai 2025 13:49

AW: Ping mit HostName
 
Zitat:

Zitat von himitsu (Beitrag 1548931)
Und d soll wirklich als Unicode und mit Längenangabe in Char anstatt Byte so korrekt sein?

Wie gesagt, ich habe nur eine sehr wage Vorstellung davon, was diese Unit eigentlich macht :(

Alucard 25. Mai 2025 13:49

AW: Ping mit HostName
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1548930)
Wenn du nur wissen willst, ob das Ping erfolgreich war, und dir ein nicht gefundener Host egal ist, dann kannst du das
Delphi-Quellcode:
RaiseLastOSError
auch einfach mit einem
Delphi-Quellcode:
Exit(False)
ersetzen. Ebenso würde ich das mit dem
Delphi-Quellcode:
raise Exception
ein paar Zeilen darunter machen.

Super, danke. This did the trick for me! :thumb:


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:38 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz