Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   DLL ignorieren wenn nicht im Pfad (https://www.delphipraxis.net/175591-dll-ignorieren-wenn-nicht-im-pfad.html)

EWeiss 3. Jul 2013 06:44

DLL ignorieren wenn nicht im Pfad
 
Wie man diese statisch/Dynamisch läd ist mir klar.
Mein Problem!

Ich möchte eine DLL wenn sie nicht im Pfad ist aber trotzdem als Unit bsp. BassMix
eingebunden ist ignorieren können wenn die Anwendung startet.
Geht so was?

Meine DLL soll also nicht zwingend auf die anderen DLL's angewiesen sein.

Bei Statisch eingebundenen DLL's verstehe ich das es nicht geht
Aber warum nicht bei Dynamischen.. welchen sinn hat dann LoadLibrary?

Ich verwende davon eine Function die ich theoretisch wenn das Handle 0 ist bei LoadLibrary überspringen könnte
Aber die Anwendung will immer die DLL.


gruss

lbccaleb 3. Jul 2013 07:16

AW: DLL ignorieren wenn nicht im Pfad
 
Prüfe zu erst ob die Datei existent ist (FileExists) und dann führe LoadLibary aus.

Ich hatte das auch mal gemacht:

Delphi-Quellcode:
          if FileExists(ExtractFilePath(paramstr(0)) + szOSADSDLL) then begin;
            if not OSADSPlugIn_Load then
              raise Exception.Create(szLoadPlugInErr)
            else AppendMenu(hToolSubMenu, MF_STRING, 1101, 'OSADS DB Scan PlugIn');
          end;
Delphi-Quellcode:
function OSADSPlugIn_Load: Boolean;
begin
  Result := False;
  hOSADSDll := LoadLibrary(PChar(ExtractFilePath(paramstr(0)) + szOSADSDLL));
  if hOSADSDll <> 0 then begin
    OSADSSendData := GetProcAddress(hOSADSDll, 'SendData');
    Result := Assigned(OSADSSendData);
  end
  else OSADSPlugIn_Close;
end;
Oder hab ich dich jetzt falsch verstanden ? oO

EWeiss 3. Jul 2013 07:25

AW: DLL ignorieren wenn nicht im Pfad
 
Das problem ist aber sobald der Export bzw.. die Unit eingebunden ist verlangt die Anwendung die DLL.
Die Datei ansich zu laden bzw.. zu prüfen ob sie existiert stellt nicht mein problem da trotzdem Danke.

Meine Unit als uses eingebunden Bassmixer.pas ohne das ich jetzt irgendetwas aufrufe macht die Anwendung dicht
da die DLL nicht gefunden wurde das will ich abfangen da ich ansonsten zu meiner DLL jedesmal fremde Bibliotheken mit ausliefern muss.
Das kann ich aber nicht.
Wobei ich aber die funktionen benötige da ansonsten bei verwendung von Wasapi und Mixer keine Visualisierung stattfindet.

gruss

lbccaleb 3. Jul 2013 07:33

AW: DLL ignorieren wenn nicht im Pfad
 
Kannst du dann die Unit nicht so abändern?

Die wird dann die dll auch so dynamisch laden wie oben..

(Ist zwar nicht das gelbe vom Ei in anderen Units rum zu fuschen aber ab und zu nötig :D )

EWeiss 3. Jul 2013 07:40

AW: DLL ignorieren wenn nicht im Pfad
 
Wie soll ich die abändern? (Darum geht es ja) ;)

Kleines Beispiel von einem Sample von delphi.about.com alles mal copy/paste

Delphi-Quellcode:
function CircleArea(const radius : double) : double; external 'circle.dll';
dynamisch laden..
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
type
  TCircleAreaFunc = function (const radius: double) : double; stdcall;
var
  dllHandle : cardinal;
  circleAreaFunc : TCircleAreaFunc;
begin
  dllHandle := LoadLibrary('circle.dll');
  if dllHandle <> 0 then
  begin
    @circleAreaFunc := GetProcAddress(dllHandle, 'CircleArea');
    if Assigned (circleAreaFunc) then
      ShowMessage('dynamic: ' + FormatFloat(',.00',circleAreaFunc(StrToFloat(Edit1.Text))))
    else
      ShowMessage('"CircleArea" function not found');
    FreeLibrary(dllHandle);
  end
  else
  begin
    ShowMessage('circle.dll not found / not loaded');
  end;
end;
dynamisch.. auch das teil verlangt nach der DLL
da die Function CircleArea im Header diese erwartet.

wie soll ich das umgehen das der Compiler diese ignoriert und nicht mehr nach der DLL sucht/Fragt.

gruss

lbccaleb 3. Jul 2013 07:49

AW: DLL ignorieren wenn nicht im Pfad
 
Also ich habe die Function in der Unit global als Variable angegeben:


Delphi-Quellcode:
var
  OSADSSendData: function(Addresse, Data: WideString; AjaxFunc: TAjaxEvenFunc): WideString;// overload;
und dann halt dynamisch geladen, wie oben zu sehen ist. Das gab bisher noch keine Probleme...

EWeiss 3. Jul 2013 07:51

AW: DLL ignorieren wenn nicht im Pfad
 
Zitat:

Zitat von lbccaleb (Beitrag 1220503)
Also ich habe die Function global als Variable angegeben:


Delphi-Quellcode:
var
  OSADSSendData: function(Addresse, Data: WideString; AjaxFunc: TAjaxEvenFunc): WideString;// overload;
und dann halt dynamisch geladen, wie oben zu sehen ist. Das gab bisher noch keine Probleme...

Ahhh das könnte klappen ;)
Werde das mal versuchen denke dieses External macht diese problem.

Danke dir :)

gruss

DeddyH 3. Jul 2013 08:03

AW: DLL ignorieren wenn nicht im Pfad
 
Klar, mit external ist es ja statisches Laden. Wie schon gesagt, LoadLibrary/GetProcAddress benutzen und Rückgaben auswerten, wenn Ersteres 0 ist, konnte die DLL nicht geladen werden, wenn Letzteres nil ist, konnte die Routine nicht geladen werden (wurde nicht exportiert etc.).

EWeiss 3. Jul 2013 08:19

AW: DLL ignorieren wenn nicht im Pfad
 
Zitat:

Zitat von DeddyH (Beitrag 1220505)
Klar, mit external ist es ja statisches Laden. Wie schon gesagt, LoadLibrary/GetProcAddress benutzen und Rückgaben auswerten, wenn Ersteres 0 ist, konnte die DLL nicht geladen werden, wenn Letzteres nil ist, konnte die Routine nicht geladen werden (wurde nicht exportiert etc.).

Ja.. Du hast recht irgendwie auch logisch.
Hab das vergessen das external = statisches Laden ist. :oops:

Jetzt funktioniert es wie es soll

Danke euch.

gruss

Der schöne Günther 3. Jul 2013 09:48

AW: DLL ignorieren wenn nicht im Pfad
 
Mein Geschmack ist es nicht, aber das hier ist doch eigentlich genau das, was du willst, oder?

Delayed Loading of a DLL von François Piette:

Zitat:

Just add delayed keyword in each function declaration and suddenly a static DLL is loaded the first time one of his functions is called. If you never call a DLL’s function, then the DLL is not loaded at all.
Könnte dann bsp. so aussehen:

Delphi-Quellcode:
unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm2 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

  function GetSomething: Integer; external 'somelibrary.dll' delayed;

var
  Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject);
begin
   try
      GetSomething();
   except
      on EExternalException do ShowMessage('DLL nicht gefunden');
   end;
end;

end.

EWeiss 3. Jul 2013 10:06

AW: DLL ignorieren wenn nicht im Pfad
 
Die Frage wäre dann wo liegt der Unterschied denn die von lbccaleb
vorgeschlagene funktioniert eigentlich so wie sie soll.

Muss ja nicht mit Gewalt ein Exeption erstellen wenn es vermeidbar ist.

gruss

DeddyH 3. Jul 2013 10:08

AW: DLL ignorieren wenn nicht im Pfad
 
Viel interessanter finde ich die Frage, was passiert, wenn die DLL die entsprechende Routine gar nicht exportiert. Mit GetProcAddress erhalte ich einen Nil-Pointer, aber bei Delayed Loading?

EWeiss 3. Jul 2013 10:17

AW: DLL ignorieren wenn nicht im Pfad
 
Zitat:

Zitat von DeddyH (Beitrag 1220532)
Viel interessanter finde ich die Frage, was passiert, wenn die DLL die entsprechende Routine gar nicht exportiert. Mit GetProcAddress erhalte ich einen Nil-Pointer, aber bei Delayed Loading?

Wie schon gesagt man muss nicht absichtlich exeption generieren..

Das reicht mir so für die eine function ;)

Delphi-Quellcode:
  BASS_WASAPI_GetData : function(buffer: Pointer; length: DWORD): DWORD;
Delphi-Quellcode:
  if FileExists(ExtractFilePath(paramstr(0)) + basswasapi) then
  begin
    WasabiHandle := LoadLibrary(basswasapi);
    if WasabiHandle <> 0 then
    begin
      @BASS_WASAPI_GetData := GetProcAddress(WasabiHandle, 'BASS_WASAPI_GetData');
      if not Assigned (BASS_WASAPI_GetData) then
      begin
        ShowMessage('"Dynamic load"' + #13#10 + 'loading.. function BASS_WASAPI_GetData fail');
        Halt;
      end;
    end;
  end;
gruss

DeddyH 3. Jul 2013 10:19

AW: DLL ignorieren wenn nicht im Pfad
 
Ja eben, so hast Du wenigstens die Kontrolle, wenn auch etwas mehr Tipparbeit.

EWeiss 3. Jul 2013 10:26

AW: DLL ignorieren wenn nicht im Pfad
 
Und der Rest macht auch keine Problem..

Delphi-Quellcode:
         if WasabiHandle and MixerHandle <> 0 then
         begin
           if UseWASAPI then
             Data := BASS_WASAPI_GetData(@SpectrumData, BASS_DATA_FFT2048)
           else
           Data := BASS_Mixer_ChannelGetData(FChannelId, @SpectrumData, BASS_DATA_FFT2048);

           if Data = -1 then
             BASS_ChannelGetData(FChannelId, @SpectrumData, BASS_DATA_FFT2048);
         end else
         BASS_ChannelGetData(FChannelId, @SpectrumData, BASS_DATA_FFT2048);
damit bin ich hiermit fertig :)

gruss

Der schöne Günther 3. Jul 2013 10:27

AW: DLL ignorieren wenn nicht im Pfad
 
Ich sehe den Unterschied nicht. Das
Delphi-Quellcode:
delayed
-Schlüsselwort verursacht beim Aufruf genauso eine
Delphi-Quellcode:
EExternalException
wenn die Datei nicht existiert, als wenn der Einsprungspunkt nicht existiert.

Aber wie gesagt, mein Geschmack ist es trotzdem auch nicht, ich suche mir den Kram auch lieber mit
Delphi-Quellcode:
GetProcAddress
selbst zusammen :-)

EWeiss 3. Jul 2013 10:29

AW: DLL ignorieren wenn nicht im Pfad
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1220547)
Ich sehe den Unterschied nicht. Das
Delphi-Quellcode:
delayed
-Schlüsselwort verursacht beim Aufruf genauso eine
Delphi-Quellcode:
EExternalException
wenn die Datei nicht existiert, als wenn der Einsprungspunkt nicht existiert.

Aber wie gesagt, mein Geschmack ist es trotzdem auch nicht, ich suche mir den Kram auch lieber mit
Delphi-Quellcode:
GetProcAddress
selbst zusammen :-)

Allemal schon interessant was anderes zu sehen aber manchmal ist mehr einfach Mehr ;)

gruss

lbccaleb 3. Jul 2013 13:28

AW: DLL ignorieren wenn nicht im Pfad
 
Zitat:

Zitat von EWeiss (Beitrag 1220536)
...
Delphi-Quellcode:
  if FileExists(ExtractFilePath(paramstr(0)) + basswasapi) then
  begin
    WasabiHandle := LoadLibrary(basswasapi);
    if WasabiHandle <> 0 then
    begin
      @BASS_WASAPI_GetData := GetProcAddress(WasabiHandle, 'BASS_WASAPI_GetData');
      if not Assigned (BASS_WASAPI_GetData) then
      begin
        ShowMessage('"Dynamic load"' + #13#10 + 'loading.. function BASS_WASAPI_GetData fail');
        Halt;
      end;
    end;
  end;
gruss

Noch nen Tipp am Rand: Ich würde es noch vermeiden bei einem erkannten Fehler die Anwendung einfach mit Halt zu beenden. Du könntest in dem Fall nen bereits geladenen Teil im Speicher behalten.
Beende also die Anwendung normal und stell sicher das alles entladen wurde.

Sherlock 3. Jul 2013 15:50

AW: DLL ignorieren wenn nicht im Pfad
 
Delphi-Quellcode:
delayed
bedeutet doch nur, daß die DLL überhaupt erst dann geladen wird, wenn sie auch verwendet wird (Arbeitsspeicherentlastung), die Direktive entbindet nicht von der Verantwortung zu prüfen, ob die DLL da ist und funktioniert.

Sherlock

EWeiss 3. Jul 2013 17:14

AW: DLL ignorieren wenn nicht im Pfad
 
Zitat:

Ich würde es noch vermeiden bei einem erkannten Fehler die Anwendung einfach mit Halt zu beenden.
In Anwendungen mache ich das auch nicht.
Aber bei dieser Bibliothek welche nur als wrapper funktioniert dürfte das egal sein.

Die Plugins beenden sich von allein.

Aber wenn ud meinst es wäre besser kann ich es ohne probleme noch ändern.

Delphi-Quellcode:
      if not Assigned (BASS_Mixer_ChannelGetData) then
      begin
        ShowMessage('"Dynamic load"' + #13#10 + 'loading.. function BASS_Mixer_ChannelGetData fail');
        FreeLibrary(MixerHandle);
        BassVis1.QuitVisPlugin;
      end;

gruss


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:26 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 by Thomas Breitkreuz