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/)
-   -   loadlibrary unter W10 (https://www.delphipraxis.net/202846-loadlibrary-unter-w10.html)

joacim 13. Dez 2019 17:27

loadlibrary unter W10
 
Hallo,

ich muß eine Fremd-DLL unter WIN10 Pro 64Bit per loadLibrary einbinden.
Die DLL wird als 32 Bit und 64 Bit Version zur Verfügung gestellt.
Mit lastError erhalte ich entweder error = 193 (bad EXE format) oder error = 126 (not found).
Die DLL ist vorhanden, das habe ich mit FileExists vorher geprüft und ich verwende
loadLibrary(PChar( DLL-NAME )). Ich vermute die DLL benötigt andere DLLs und wird daher nicht geladen.
Per HEX-Editor sehe ich (u.a.) MSVCP100.DLL. Als Test versuche ich mit loadLibrary MSVCP100.DLL einzeln
zu laden. Das klapp aber auch nicht.

Gibt es ein spezielle Version von MSVCP100 für 64 Bit? Ich bin aus den gefundenen Infos nicht schlau geworden.
Auf meimem PC finde ich diese DLL nur unter C:\windows\system32, auch nachdem ich eine (angeblich) für 64
gedachet Version nachinstalliert habe.

Der schöne Günther 13. Dez 2019 17:33

AW: loadlibrary unter W10
 
Ich glaube das Tool das einem anzeigen konnte was beim Einladen einer DLL falsch läuft hieß "Dependency Walker". Das würde ich mal auf die 32 und 64-Bit-Version loslassen und schauen was der ausspuckt.

joacim 13. Dez 2019 17:39

AW: loadlibrary unter W10
 
.. danke, hab ich schon gemacht. Das Drama dauert schon 4 Tage und ich habe die Details erstmal weggelassen.
Im D.Walker sehe ich auch MSVCP100.DLL. ich verstehe nur nicht, warum ich diese DLL mit LoadLibrary auch nicht laden kann.

DieDolly 13. Dez 2019 17:48

AW: loadlibrary unter W10
 
Zitat:

Im D.Walker sehe ich auch MSVCP100.DLL. ich verstehe nur nicht, warum ich diese DLL mit LoadLibrary auch nicht laden kann.
Installier doch einfach das passende Microsoft Windows Redistributable Package dann musst du nix selber laden.

joacim 13. Dez 2019 17:54

AW: loadlibrary unter W10
 
hab ich gemacht, s.o. aber auf meimem PC finde ich diese DLL nur unter C:\windows\system32

Dalai 13. Dez 2019 17:57

AW: loadlibrary unter W10
 
Zitat:

Zitat von joacim (Beitrag 1453416)
[...] und ich habe die Details erstmal weggelassen.

Das solltest du ändern. Ohne konkrete Informationen kann jeder Helfer nur einen Schuss ins Blaue machen.

Für welche Plattform kompilierst du dein Programm? Win32 oder Win64 (oder beide)? Wo genau liegt die zu ladende DLL? Für den Fall, dass sie im %SystemRoot%\system32 liegt, und du ein Win32-Programm hast: Bist du dir der Filesystem Redirection bewusst, die dann zuschlägt (durch WOW64)? Und nicht zuletzt: Etwas Code kann vielleicht auch nicht schaden.

Grüße
Dalai

hoika 13. Dez 2019 18:00

AW: loadlibrary unter W10
 
Hallo,
Zitat:

Die DLL ist vorhanden, das habe ich mit FileExists vorher geprüft
Das nützt nichts. Der Vorgang des Suchens der Dll ist viel komplizierter.

Ich würde erst mal ein Testprogramm aufsetzen,
wo die fremde Dll im eigenen Verzeichnis liegt.
Dort wird zuerst gesucht.

joacim 13. Dez 2019 18:24

AW: loadlibrary unter W10
 
Liste der Anhänge anzeigen (Anzahl: 1)
ist schon klar, ich wollte erstmal "klein anfangen"
Code:
unit Load_DLL_Test;

interface

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TfrmTest = class(TForm)
    Memo1: TMemo;
    bt32: TButton;
    bt64: TButton;
    procedure FormActivate(Sender: TObject);
    procedure bt32Click(Sender: TObject);
    procedure bt64Click(Sender: TObject);
  private
  public
    { Public-Deklarationen }
  end;

var
  frmTest: TfrmTest;

implementation


{$R *.dfm}

procedure TfrmTest.FormActivate(Sender: TObject);
begin
  memo1.Lines.Clear;

  memo1.Lines.Add('loadLibrary Test; Version vom 13.12.2019 ');
  memo1.Lines.Add('ADDIPACK DLLs (32/64 bit) müssen in ');
  memo1.Lines.Add('zwei Verzeichnissen ..\DLL32  bzw. ..\DLL64 liegen');
end;

procedure TfrmTest.bt32Click(Sender: TObject);
var
  strName, strHome: string;
  err : integer;
  hndl : THandle;
begin
  memo1.Lines.Add('');
  hndl := 0;
  strHome := ExtractFilePath(Application.ExeName);
  strName := strHome + 'DLL32\ADDIDATA.DLL';
  if FileExists(strName) then
    memo1.Lines.Add('file ' + strName +'  exists')
  else
    showMessage('DLL 64 bit not found');
  hndl := loadLibrary(PCHAR(strName));
  err := GetLastError();
  memo1.Lines.Add('32 bit ' + IntToStr(hndl) + ' last error ' + intToStr(err));
end;

procedure TfrmTest.bt64Click(Sender: TObject);
var
  strName, strHome : string;
  err : integer;
  hndl : THandle;
begin
  memo1.Lines.Add('');
  hndl := 0;
  strHome := ExtractFilePath(Application.ExeName);
  strName := strHome + 'DLL64\ADDIDATA.DLL';
  if FileExists(strName) then
    memo1.Lines.Add('file ' + strName +'  exists')
  else
    showMessage('DLL 64 bit not found');
  hndl := loadLibrary(PCHAR(strName));
  err := GetLastError();
  memo1.Lines.Add('64 bit ' + IntToStr(hndl) + ' last error ' + intToStr(err));
end;

end.
Dei beiden DLLs liegen in zwei Verzeichnissen DLL32 bzw DLL64. Das komplette Projekt ist als ZIP angehängt.
Ich arbeite für WIN10 64bit mit Delphi 6, ja ich weiß das ist alt ...

DieDolly 13. Dez 2019 18:35

AW: loadlibrary unter W10
 
Zitat:

hab ich gemacht, s.o. aber auf meimem PC finde ich diese DLL nur unter C:\windows\system32
Das ist ja auch richtig so. Die DLL muss man nicht selber laden. Lass die einfach da und lade sie nicht manuell.

Wenn die DLL dann noch nicht funktioniert, ist das Problem ein anderes.

Zitat:

Ich arbeite für WIN10 64bit mit Delphi 6, ja ich weiß das ist alt ...
Das ist meiner Meinung nach schon das Problem.
DLL erzeugt mit modernem Delphi und du arbeitest mit einem alten. Das Problem hatte ich umgekehrt schon.

samso 13. Dez 2019 18:46

AW: loadlibrary unter W10
 
Mit Delphi 6 Programmen kannst Du keine 64-Bit-DLL laden.

Dalai 13. Dez 2019 20:17

AW: loadlibrary unter W10
 
Zitat:

Zitat von DieDolly (Beitrag 1453423)
Das ist meiner Meinung nach schon das Problem.
DLL erzeugt mit modernem Delphi und du arbeitest mit einem alten. Das Problem hatte ich umgekehrt schon.

Das sollte kein Problem sein, jedenfalls nicht für LoadLibrary. DLLs sind ja gerade dafür da, von einem beliebigen Programm geladen und benutzt zu werden, völlig egal, womit die beteiligten Teile kompiliert wurden. Trotzdem ist dein Einwand grundsätzlich berechtigt, wenn es um Rückgaben von Funktionen aus der DLL geht (Stichwort Strings/PChar und Unicode). Aber das kommt erst nach dem LoadLibrary.

@joacim:
Den (relevanten) Fehlercode aus dem OP beschreibt MS so:
Zitat:

ERROR_MOD_NOT_FOUND
126 (0x7E)
The specified module could not be found.
Schau dir die DLL genauer an, z.B. mit einem der schon genannten Programme (Dependency Walker, DLL Export Viewer) und prüfe, welche Funktionen deine DLL aus anderen DLLs importiert. Bevor eine DLL erfolgreich geladen werden kann, müssen alle (statischen) Import-Abhängigkeiten aufgelöst werden. Und samso sagte ja schon richtig, dass du die Win64-Variante der DLL ignorieren kannst, denn dein Programm ist in jedem Fall 32-bittig.

Grüße
Dalai

joacim 14. Dez 2019 06:40

AW: loadlibrary unter W10
 
@samso ich weiß, daß man mit D6 keine 64 bit DLL laden/verwenden kann. Das mache ich alles nur, um jede Möglichkeit auszuschöpfen.

Auf die DLL selber habe ich keinen Einfluß, die kommt vom Hersteller der Mess-Karten, die ich ansprechen soll.
Ich denke mal, die DLL ist mit C oder C++ erstellt worden. Ein Kontakt mit dem Hersteller gestaltet sich eher
schwierig.

joacim 15. Dez 2019 07:45

AW: loadlibrary unter W10
 
Liste der Anhänge anzeigen (Anzahl: 1)
@Frühlingsrolle In meinem Rechner steckt eine PCIe3021. Das ist aber nicht entscheidend.
Ich habe mit dem "normalen" Treiber schon Programme für die Karte entwickelt. Jetzt geht es
um einen neuen sog. Universaltreiber. Ich habe auch eine ausführliche Dokumentation mit
allen Aufrufen usw. Die Sache mit dem statischen Linken hatte ich inzwischen schon verwendet
und der Treiber liegt auch im Verzeichnois der EXE. Jetzt bekomme ich wenigstens Fehlermeldungem.
Erstmal fehlte MSVCR100.DLL (liegt jetzt im Verzeichnis) Dann wurde MSVCP100.DLL nicht gefunden.
Das schein ja - nach vielen Hinweisen im Netz - ein übliches Problem zu sein. Ich habe den MS-Installer
ausgeführt und sehe MSVCP100.DLL jetzt unter c:\windows\system32. Das scheint aber noch nicht ausreichend zu sein.
Beim Start des Programms bekomme ich immer noch eine Fehlermeldung (s. Anhang).

Es scheint ja auch noch Probleme mit div. Verssionen der MSVCP100.DLL zu geben ...

Dalai 15. Dez 2019 16:32

AW: loadlibrary unter W10
 
Wenn die DLL auf das Vorhandensein der msvc*100.dll angewiesen ist, muss die 32-bit (x86) Version der Visual C++ Redistributable 2010 installiert sein/werden. Deren DLLs landen dann in %SystemRoot%\SysWOW64 (\system32 bitte ignorieren für diesen Fall, weil dort 64-bit DLLs liegen).

Alle (halbwegs) aktuellen Visual C++ Redists können bei MS geladen werden: https://support.microsoft.com/en-us/...al-c-downloads (für die 2010 muss man auf das MFC Update zurückgreifen, wenn man kein MS-Konto hat).

Grüße
Dalai

DieDolly 15. Dez 2019 16:43

AW: loadlibrary unter W10
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Alle (halbwegs) aktuellen Visual C++ Redists können bei MS geladen werden: https://support.microsoft.com/en-us/...al-c-downloads (für die 2010 muss man auf das MFC Update zurückgreifen, wenn man kein MS-Konto hat).
Oder einfach vom Anhang

himitsu 15. Dez 2019 17:09

AW: loadlibrary unter W10
 
Die Fehler aus LoadLibrary (ERROR_MOD_NOT_FOUND) können sich halt auf die DLL selbst beziehen, oder auf eine andere abhängige DLL,
oder es kann aus den Startprozeduren der DLLs kommen und da dann z.B. auch von dynamischen Links.

Wie bereits genannt wurde, kannst du mit gewissen Programmen die statischen Verlinkungen auflisten und prüfen lassen.
Wenn das nichts Hilft, dann entweder mit dem Debugger, der aber nur bei dynamischen Links helfen könnte.
Oder z.B. mit einem FileExplorer/ProcessMonitor, welcher die Dateizugriffe loggt. Dort kannst du dann sehen auf welche Dateien und Verzeichnisse zugegriffen und welche davon nicht gefunden wurden.
https://docs.microsoft.com/en-us/sys...nloads/procmon


Zu den DLLs in Systemverzeichnissen (System32 usw.) brauchst und solltest du kein Verzeichnis beim LoadLibrary und für statische Links angeben.
Windows sucht beim hier zuerst in dem Verzeichnis deiner EXE und später auch im "passenden" System-Verzeichnis. (und weiteren Suchpfaden)

PS: Du kompilierst ein 32-Bit Programm, also sind für dich nur 32-Bit-DLLs interessant, wie bereits richtig erkannt. (abgesehn von OutOfProcessServern, wo die DLL woanders auch in einem 64-Bit-Host geladen sein kann).
Und Achtung, in Windows 64 ist System32 für 64-Bit-DLLs, während die 32-Bit-DLLs im SysWOW64 liegen (System for Windows 32 on Windows 64), aber keine Sorge, denn Windows leitet standardmäßig für dein 32-Bit-Programm auf WoW64 um, falls dein Programm doch einmal auf C:\Windows\System32\... zuzugreifen versucht.
Selbiges Umleitungskonzept gilt auch für einige Verzeichnisse in der Registry.
Und was das WinSxS (Side-by-Side) betrifft, können Andere es besser erklären, aber im Grunde geht es darum, dass man in seiner Anwendung die DLL-Version vorgeben kann und Windows dann im System unter all den gleichnamigen DLLs die Passende für dich raussucht.
https://en.wikipedia.org/wiki/Side-by-side_assembly
Vorallem für gewisse System-DLLs ingoniert Windows gleichnamige DLLs in deinem Verzeichnis oder anderen Suchfragen und geht dennoch auf System32. (Sicherheitsdinges, um billige Hooks zu umgehen) aber ist hier egal.

Und nun noch etwas Werbung: https://www.embarcadero.com/delphi-starter-edition

joacim 15. Dez 2019 17:53

AW: loadlibrary unter W10
 
guten abend und danke für die vielen Tips!

@dieDolly : Nachdem ich die Installation aus Deiner 7z-Datei verwendet habe, startet mein Testprogramm
schon mal ohne Fehlermeldung. Das habe ich bei diversen Versuchen mit anderen Installern für MSVCP100
nicht geschafft. Also nochmal danke!

Für die weitere Programmierung brauche ich nun das handle, welches die Treiber-DLL bei LoadLIbrary
zurückliefert. Das war ja der Ausgangspunkt. LoadLibrary läuft jetzt zwar durch und liefert (angeblich)
auch ein handle (268435456). Das kommt mir aber merkwürdig vor. Außerdem liefert ein GetLastError als Ergenis
eine 5 (access denied). Der Versuch diese Handle in einer der DLL-Funktionen zu verwenden liefert dann
auch gleich wider einen Fehler. (Externe exception E06D7363).

DieDolly 15. Dez 2019 17:54

AW: loadlibrary unter W10
 
Zitat:

Das habe ich bei diversen Versuchen mit anderen Installern für MSVCP100
nicht geschafft.
Auf Seite 1 glaube ich hatte ich bereits geschrieben, dass man dieses Redist installieren muss.

Zitat:

Zitat von DieDolly (Beitrag 1453417)
Zitat:

Im D.Walker sehe ich auch MSVCP100.DLL. ich verstehe nur nicht, warum ich diese DLL mit LoadLibrary auch nicht laden kann.
Installier doch einfach das passende Microsoft Windows Redistributable Package dann musst du nix selber laden.

Noch ein Tipp für die Zukunft: wenn man zum Beispiel MSVCP100.dll bei Google eingibt, sind die ersten Seiten oft irgendwelche sehr dubiosen DLL-Download und -Fix-Seiten.
Bei sowas niemals runterladen!

Stattdessen einfach hier nachfragen, wo diese DLL herkommt und was man braucht, damit alles funktioniert.

jaenicke 16. Dez 2019 05:50

AW: loadlibrary unter W10
 
Zitat:

Zitat von joacim (Beitrag 1453485)
LoadLibrary läuft jetzt zwar durch und liefert (angeblich)
auch ein handle (268435456). Das kommt mir aber merkwürdig vor. Außerdem liefert ein GetLastError als Ergenis
eine 5 (access denied). Der Versuch diese Handle in einer der DLL-Funktionen zu verwenden liefert dann
auch gleich wider einen Fehler. (Externe exception E06D7363).

Wie meinst du das "in einer der DLL-Funktionen zu verwenden"? Das Handle, das LoadLibrary liefert, ist das Handle der DLL und kann verwendet werden um die Funktionen der DLL dynamisch zu laden.
Das hat aber nichts mit dem Handle zu tun, das du an eine der Funktionen der DLL übergeben kannst (in den Beispielen z.B. ph_DeviceHandle genannt).

joacim 16. Dez 2019 08:26

AW: loadlibrary unter W10
 
Nach verschidenen Tests bekomme ich jetzt die ersten Ergenisse. Versuche die Funktionen des Treibers
zu verwenden, klappten aber immer noch nicht. Das Problem lag in einer fehlenden FAR Deklaration beim
Import der Funktionen.
@jaenicke
Es gibt aber immer noch Unklarheiten. Die Funktionen des Treibers verlangen im Aufruf ein Handle. Ich habe
bisher gedacht (und es bei dem Vorläuferprojekt auch so gemacht), das dort das Handle eingetragen werden
muss, dass bei LoadLibrary zurückkommt. Das funktioniert zwar, aber ich kann genauso gut Null eintragen und
bekomme z.B. sinnvolle Ergebnisse beim Lesen der digitalen Eingänge. Ich erwarte nicht, diese Eigenschaft
hier zu klären, da werde ich mal mit dem Hersteller Kontakt aufnehmen.

Nachdem nun die größten Hürden genommen sind, kann ich mit der eigentlichen Verwendung des Treibers
beschäftigen. Nochmals denke an alle und schon mal frohe Weihnachten.

jaenicke 16. Dez 2019 12:02

AW: loadlibrary unter W10
 
Zitat:

Zitat von joacim (Beitrag 1453506)
Es gibt aber immer noch Unklarheiten. Die Funktionen des Treibers verlangen im Aufruf ein Handle. Ich habe
bisher gedacht (und es bei dem Vorläuferprojekt auch so gemacht), das dort das Handle eingetragen werden
muss, dass bei LoadLibrary zurückkommt.

Wie das geht sieht man eigentlich schon in den Parametern der Funktionen. Du hast dort z.B. bei einem Board eine Funktion i_PCI3016_OpenBoardViaIndex, die den Boardindex bekommt und als var-Parameter die Variable mit dem Handle. Dementsprechend ist zu erwarten, dass die Funktion das Handle in eben diese Variable hineinschreibt (sonst müsste es ja kein var-Parameter sein).

Sicher, wenn du da vorher deinen Handle-Wert hineinpackst, wird der einfach überschrieben, deshalb merkst du das ohne es zu debuggen nicht.

joacim 16. Dez 2019 14:41

AW: loadlibrary unter W10
 
Ich habe hier - nur als Beispiel - zwei Funktionen

Delphi-Quellcode:
function b_ADDIDATA_GetNumberOfDigitalInputs(dw_DeviceHandle : DWord; var w_NumberOfChannels : word) : byte; far; stdcall; external 'ADDIDATA.DLL';
function b_ADDIDATA_Read4DigitalInputs(dw_DeviceHandle : DWord; b_port : byte; var b_portValue : byte) : byte; far; stdcall; external 'ADDIDATA.DLL';
Wie schon geschrieben, wurde im Vorläuferprojekt immer das Handle an die Funktion übergeben.
Die beiden Funktionen erwarten auch hier die Übergabe von dw_DeviceHandle, nicht als var, also nicht als Rückgabewert!

In der Dokumentation steht z.B.
<return value> = b_ADDIDATA_Read4DigitalInputs(DWORD dw_DeviceHandle,
BYTE b_port : byte,
PBYTE pb_portValue)

Ich interpretiere PBYTE als Pointer auf ein Byte, daher VAR im Delphi. dw_DeviceHandle ist aber DWORD also kein VAR,
also auch kein Rückgabewert. Warum ist es völlig gleichgültig, was ich da übergebe? Das Lesen der digitalen Eingänge funktioniert jerdenfalls, auch mit dw_DeviceHandle = 0. Die Antwort kann wahrscheinlich nur der Hersteller geben.

Luckie 16. Dez 2019 15:55

AW: loadlibrary unter W10
 
DeviceHandle! Das Handle des Geräts und nicht das Handle der DLL. Die Funktion muss ja wissen von welchem Gerät du die Infos willst.

jaenicke 16. Dez 2019 16:34

AW: loadlibrary unter W10
 
Zitat:

Zitat von joacim (Beitrag 1453542)
Wie schon geschrieben, wurde im Vorläuferprojekt immer das Handle an die Funktion übergeben.
Die beiden Funktionen erwarten auch hier die Übergabe von dw_DeviceHandle, nicht als var, also nicht als Rückgabewert!

Und wie sieht es mit i_ADDIDATA_OpenWin32Driver und i_ADDIDATA_GetCurrentDriverHandle aus? :wink:

joacim 18. Dez 2019 06:59

AW: loadlibrary unter W10
 
@jaeinicke

Der Aufruf von i_ADDIDATA_OpenWin32Driver liefert als Handle immer Null zurück.
Die Aufrufe der anderen Funktionen, die das Handle benötigen, funktionieren aber,
wenn ich dort diese Null eintrage. Ich hätte für ein Handle eigentlich einen Wert
ungleich Null erwartet

Mit Euren Hilfen und Anregungen habe ich jetzt die wichtigsten Dinge zum Laufen
gebracht, frage mich aber immer noch, warum das Handle Null ist.

joacim 18. Dez 2019 11:04

AW: loadlibrary unter W10
 
Doku zu i_ADDIDATA_OpenWin32Driver
...
-Output
PDWORD pdw_DriverHandle
Returns the driver handle. This parameter i the first to be called up for each function.

Soweit so klar, trotzdem würde ich da keine Null erwarten.

joacim 19. Dez 2019 10:39

AW: loadlibrary unter W10
 
hab ich gemacht, kommt aber nur eine große Zahl als Fehlercode, die in keiner Liste steht.
Das ist auch nicht weiter verwunderlich, weil i_ADDIDATA_OpenWin32Driver mit Null
( = kein Fehler) zurückkommt.


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

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