Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Windows API Übersetzung - Welche Variante ist besser ? (https://www.delphipraxis.net/142911-windows-api-uebersetzung-welche-variante-ist-besser.html)

RWarnecke 5. Nov 2009 22:14


Windows API Übersetzung - Welche Variante ist besser ?
 
Hallo zusammen,

ich habe da mal eine vielleicht einfache Frage. Ich kann ja die API-Befehle von Windows in zwei Varianten nutzen. Welche der beiden Varianten ist besser geeignet, um Fehler vorzubeugen ?

Variante 1 :
Delphi-Quellcode:
  TGetAdapterAdresses = function (Family: ULONG; Flags: cardinal; Reserved: PVOID;
     pAdapterAddresses: PIP_ADAPTER_ADDRESSES; pOutBufLen: PULONG): dword; stdcall;
Variante 2 :
Delphi-Quellcode:
  function GetAdapterAdresses(Family: ULONG; Flags: cardinal; Reserved: PVOID;
     pAdapterAddresses: PIP_ADAPTER_ADDRESSES; pOutBufLen: PULONG) : DWORD; stdcall;
     external 'IPHLPAPI.DLL' name 'GetAdapterAdresses';
Diese Funktion ist lediglich nur ein Beispiel. Welche Variante ist einfacher zu benutzen, um zum Beispiel den Fehler vorzubeugen, dass die IPHLPAPI.DLL nicht gefunden wird, wie in diesem Beispiel. Oder anderst gefragt, wo und wie ist es besser abzufragen, ob die dazugehörige DLL für die API-funktion vorhanden ist ?

Aphton 5. Nov 2009 22:23

Re: Windows API Übersetzung - Welche Variante ist besser ?
 
Bei der ersten Variante definierst du nur einen Typ. Später im Programmfluss musst du dir eine Variable eben dieses Typs definieren und die Funktion selbst aus der DLL (LoadLibraryA()/GetModuleHandleA() & GetProcAddress()) laden.

Bei der zweiten Variante wird es in die Importier-Liste beim Kompilieren hineinverlinkt. Dh. der PE-Loader von Windows ist zuständig, dass er beim Initialisieren der Echse - falls diese ausgeführt wird - alle Module (DLLs) & Funktionen der Importier-Liste ladet (und weitere Aufgaben durchführt...).

MfG

mirage228 5. Nov 2009 22:25

Re: Windows API Übersetzung - Welche Variante ist besser ?
 
Also am einfachsten ist es im Vorfeld abzuklären, ab welcher Windows/IE Version diese Datei enthalten ist, um dann zu schauen, ob du ältere Versionen unterstützen willst.

Lädst du statisch (zweite Variante) haut dir Windows beim Start direkt eine Meldung um die Ohren, falls die DLL fehlt, diese Variante ist aber recht komfortabel. Wenn Du den ersten Punkt von mir beachtet, könntest Du ohne Bedenken diese Variante nutzen.

Für Variante 1 würde sich der "initialization" Abschnitt anbieten. Kannst Dir ja anschauen, wie Borland das macht in der VCL (Ich glaube "GetLayeredWindowAttributes" ist so ein Kandidat). Hier kannst Du natürlich ein eigenes Fehlerhandling ansetzen, hast aber mehr Aufwand.

Viele Grüße

RWarnecke 5. Nov 2009 22:28

Re: Windows API Übersetzung - Welche Variante ist besser ?
 
Ok, soweit verstanden. Für Variante 1 kenne ich die vorgehensweise mit LoadLibary/GetProcAddress u.s.w. Verstehe ich das dann richtig, dass ichbei Variante 2 nur über die Windows Version gehen kann ? Oder gibt es da auch noch eine andere Möglichkeit ?

mirage228 5. Nov 2009 22:31

Re: Windows API Übersetzung - Welche Variante ist besser ?
 
Zitat:

Zitat von RWarnecke
Ok, soweit verstanden. Für Variante 1 kenne ich die vorgehensweise mit LoadLibary/GetProcAddress u.s.w. Verstehe ich das dann richtig, dass ichbei Variante 2 nur über die Windows Version gehen kann ? Oder gibt es da auch noch eine andere Möglichkeit ?

Bei Variante 2 ist mit der Windows Version dachte ich eher an eine informelle Regelung. Du legst einfach als Systemanforderung Windows XY fest, ggf. ein Installationsprogramm könnte diese Prüfung dann vornehmen. Afaik gibt es dann keine weitere Kontrollmöglichkeit seitens deines Programmes aus (bei Variante 2), da das Prorgamm gar nicht erst gestartet wird.
Edit: Für Variante 1: Genau LoadLibrary / GetProcAddres ... für ältere Versionen von Windows wäre zu überlegen, ob Du das Programm mit einer eigenen Fehlermeldung wieder schließt, eine Dummy-Funktion schreibst, die immer "FALSE" (oder ein vergleichbares Ergebnis, das für den Fehlschlag der API Funktion steht) zurückgibt oder die Funktion selber für ältere Versionen implementierst, usw. ...

RWarnecke 5. Nov 2009 22:33

Re: Windows API Übersetzung - Welche Variante ist besser ?
 
Ok, danke für die Infos. Damit kann ich was anfangen. Dann werde ich meine Unit nach Variante 1 umschreiben, da ich doch viele Funktionen habe, die über verschiedene Windows Versionen verteilt sind.

Edit: Ich unterstütze eh nur noch ab Windows 2000 oder höher. Auf ältere Versionen gehe ich schon garnicht mehr ein. Aber trotzdem habe ich ja noch unterschiede bei den API-Befehlen von Windows 2000 bis Windows 7.

Edit 2: Dabei stellt sich mir die Frage, ob ich das ganze LoadLibray/GetProcAddress nicht über eine Funktion laufen lasse. Was haltet Ihr davon ?

uoeb7gp 6. Nov 2009 00:34

Re: Windows API Übersetzung - Welche Variante ist besser ?
 
RWarnecke hat folgendes geschrieben:
Dann werde ich meine Unit nach Variante 1 umschreiben, da ich doch viele Funktionen habe,
die über verschiedene Windows Versionen verteilt sind.

Variante1 ist statisch, da bekommst wenn was nichgt gefunden wird, böse Fehlermeldungen.

Versuchs mal mit folgendem (Types must aus der IPHLPAPI ziehen).

type
TGetAdapterAdresses = function(Family: ULONG; Flags: cardinal;
Reserved: PVOID; pAdapterAddresses: PIP_ADAPTER_ADDRESSES;
pOutBufLen: PULONG) : DWORD; stdcall;

function SafeLoadLibrary(const Filename: String; ErrorMode: UINT): HMODULE;
var
SaveErrorMode: UINT;
SaveFPUControlWord: Word;
begin
SaveErrorMode := SetErrorMode(ErrorMode);
try
asm FNSTCW SaveFPUControlWord end;
try
Result := LoadLibrary(PChar(Filename));
finally
asm
FNCLEX
FLDCW SaveFPUControlWord
end;
end;
finally
SetErrorMode(SaveErrorMode);
end;
end;


function GetAdapterAdresses(Family: ULONG; Flags: cardinal; Reserved: PVOID;
pAdapterAddresses: PIP_ADAPTER_ADDRESSES; pOutBufLen: PULONG) : DWORD;
var
DLLProc: TGetAdapterAdresses;
DLLHandle: THandle;
begin
result := 0;
try
DLLHandle := SafeLoadLibrary('IPHLPAPI.DLL', SEM_NOOPENFILEERRORBOX);
if DLLHandle <> 0 then begin
try
@DLLProc := GetProcAddress(DLLHandle, 'GetAdapterAdresses');
if @DLLProc <> nil
result := DLLProc(Family, Flags, Reserved, pAdapterAddresses, pOutBufLen);
finally
FreeLibrary(DLLHandle);
end;
end;
except
result := DWORD(-1);
end;
end;

RWarnecke 6. Nov 2009 04:44

Re: Windows API Übersetzung - Welche Variante ist besser ?
 
Zitat:

Zitat von uoeb7gp
... Variante1 ist statisch, da bekommst wenn was nichgt gefunden wird, böse Fehlermeldungen. ...

Wenn ich bei Variante 1 mit LoadLibrary und GetProcAddress es vorher Abfrage, kann ich doch die ganzen bösen Fehlrmeldungen abfangen. Oder sehe ich das falsch ?

Zitat:

Zitat von uoeb7gp
Versuchs mal mit folgendem (Types must aus der IPHLPAPI ziehen).

Delphi-Quellcode:
type
  TGetAdapterAdresses = function(Family: ULONG; Flags: cardinal;
    Reserved: PVOID; pAdapterAddresses: PIP_ADAPTER_ADDRESSES;
    pOutBufLen: PULONG) : DWORD; stdcall;

function SafeLoadLibrary(const Filename: String; ErrorMode: UINT): HMODULE;
var
  SaveErrorMode: UINT;
  SaveFPUControlWord: Word;
begin
  SaveErrorMode := SetErrorMode(ErrorMode);
  try
    asm FNSTCW SaveFPUControlWord end;
    try
      Result := LoadLibrary(PChar(Filename));
    finally
      asm
        FNCLEX
        FLDCW SaveFPUControlWord
      end;
    end;
  finally
    SetErrorMode(SaveErrorMode);
  end;
end;


function GetAdapterAdresses(Family: ULONG; Flags: cardinal; Reserved: PVOID;
  pAdapterAddresses: PIP_ADAPTER_ADDRESSES; pOutBufLen: PULONG) : DWORD;
var
  DLLProc: TGetAdapterAdresses;
  DLLHandle: THandle;
begin
  result := 0;
  try
    DLLHandle := SafeLoadLibrary('IPHLPAPI.DLL', SEM_NOOPENFILEERRORBOX);
    if DLLHandle <> 0 then begin
      try
        @DLLProc := GetProcAddress(DLLHandle, 'GetAdapterAdresses');
        if @DLLProc <> nil
          result := DLLProc(Family, Flags, Reserved, pAdapterAddresses, pOutBufLen);
      finally
        FreeLibrary(DLLHandle);
      end;
    end;
  except
    result := DWORD(-1);
  end;
end;

Danke für das Beispiel. Nur verstehe ich noch nicht, warum muss ich jetzt nochmal selber eine Funktion für die API-Funktion schreiben ? Ich wollte ja nur lediglich den Teil mit LoadLibrary und GetProcAddress in eine Funktion setzen.

Bernhard Geyer 6. Nov 2009 07:39

Re: Windows API Übersetzung - Welche Variante ist besser ?
 
Schau dir mal an wie es im Jedi Win32API-Projekt gemacht ist.

Solltest du D2010 oder neuer haben so wäre auch Delay Load etwas was mit dem neuen Schlüsselwort delayed ermöglicht wird.

RWarnecke 6. Nov 2009 07:57

Re: Windows API Übersetzung - Welche Variante ist besser ?
 
Zitat:

Zitat von Bernhard Geyer
Schau dir mal an wie es im Jedi Win32API-Projekt gemacht ist.

Welches der Projekte meinst Du da genau ? JCL/JVCL oder welches ?
Zitat:

Zitat von Bernhard Geyer
Solltest du D2010 oder neuer haben so wäre auch Delay Load etwas was mit dem neuen Schlüsselwort delayed ermöglicht wird.

Ich benutze Delphi 2006, eventuell noch 2007.
Ich verstehe nur noch nicht das Beispiel was mir uoeb7gp hier gepostet hat. Im Moment würde ich folgendermaßen vorgehen :
Delphi-Quellcode:
type
  TGetAdapterAdresses = function(Family: ULONG; Flags: cardinal;
    Reserved: PVOID; pAdapterAddresses: PIP_ADAPTER_ADDRESSES;
    pOutBufLen: PULONG) : DWORD; stdcall;

{...}

function xy(Test:string):string;
var
  AdaptersAddresses : TGetAdapaterAddresses;
  hdll : THandle;
begin
  hdll := LoadLibrary('IPHLPAPI.DLL');
  if hdll <> 0 then
  begin
    @AdapaterAddresses := GetProcAddress(hdll, 'GetAdaptersAddresses');
    if @AdaptersAddresses <> nil then
    begin
      { hier der Aufruf der Funktion und Verarbeiten der ausgelesenen Daten }
    end;
  end;
end;
Jetzt stellt sich mir die Frage, wo ist der Unterschied zwischen meinem Beispiel und dem von user]uoeb7gp[/user] ?


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:44 Uhr.
Seite 1 von 2  1 2      

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