Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Aus DLL auf Prgramm zugreifen (https://www.delphipraxis.net/28662-aus-dll-auf-prgramm-zugreifen.html)

F.W. 27. Aug 2004 15:55


Aus DLL auf Prgramm zugreifen
 
Ich brauche eure Hilfe! Ich habe schon die ganze DP durchsucht, aber nie die konkrete Antwort auf mein Problem:

Aus meiner Anwendung heraus wird eine procedure aufgerufen (aus einer DLL), die ein Formular erzeugt und es anzeigt, aber nicht ShowModal!
Die DLL wird dynamisch erzeugt und nach erfolgreichem Ausführen der "Startprocedure" in der DLL die Caption eines in der Anwendung vorkommenden Labels auf 'Gestartet' gesetzt.
Wenn das DLL-Formular geschlossen wird, soll es das irgendwie der Anwendung mitteilen oder direkt die Caption des Labels auf 'Geschlossen' setzen.

Ich hab's selbst schon mit der Übergabe von Pointer, dem label selbst... versucht, aber es hat nie geklappt!

Könnt ihr mir sagen, wie ich das machen kann?

nailor 27. Aug 2004 16:37

Re: Aus DLL auf Prgramm zugreifen
 
das sollte eigentlich so gehen... an sonsten mach es über eine windows-message, die zu abschluss gefeuert wird.

SleepyMaster 27. Aug 2004 16:45

Re: Aus DLL auf Prgramm zugreifen
 
Oder du machst einen Callback rein.

F.W. 28. Aug 2004 13:42

Re: Aus DLL auf Prgramm zugreifen
 
Könnt ihr mal n Beispiel geben? :shock:

nailor 28. Aug 2004 13:56

Re: Aus DLL auf Prgramm zugreifen
 
[delphi]//dll: ganz am ende:
SendMessage(Form2.Handle, succ(WM_USER), myDATA, myDATA);

// hauptprogramm: interface:
procedure myProc(var msg: TMessage); message succ(WM_USER);

// hauptprogramm: code:
procedure TForm2.myProc(var msg: TMessage);
begin
ShowMessage(inttostr(msg.LParam));
end;

Luckie 28. Aug 2004 14:03

Re: Aus DLL auf Prgramm zugreifen
 
Das funktioniert aber nur, wenn die DLL nur von einem Prozess benutzt wird. Ich würde mir mal das DLL Tutorial von Assarbad ankucken: http://www.luckie-online.de/Downloads/Importe/Assarbad/

nailor 28. Aug 2004 14:10

Re: Aus DLL auf Prgramm zugreifen
 
@luckie: meinst du, weil die dll es nicht auf die Reihe bekäme, sich zwei verschiedene Form.Handles merken könnte, oder was ganz anderes?

Luckie 28. Aug 2004 14:14

Re: Aus DLL auf Prgramm zugreifen
 
Die DLL wird nur entladen, wenn kein Prozess sie mehr benutzt. Führts du den Code nur beim Entladen aus, dann trifft meine Aussage zu. Man muss den Code dann ausführen, wenn sie von einem Prozess entladen wird. dazu muss man seine eigene DLLProc einsetzten und auf DLL_UNDETACHE oder wie das heißt reagieren.

nailor 28. Aug 2004 14:17

Re: Aus DLL auf Prgramm zugreifen
 
mann muss es ja nicht beim entladen machen. reicht ja vollkommen, wenn man es immer dann aufruft, wenn der codeabschnitt, der durchgeführt werden soll, damit sich was ändert (siehe allererste post des fragestellers) durchgelaufen ist.

Prof. emerit. Dr. Newbie 28. Aug 2004 14:49

Re: Aus DLL auf Prgramm zugreifen
 
Zitat:

Zitat von F.W.
Ich brauche eure Hilfe! Ich habe schon die ganze DP durchsucht, aber nie die konkrete Antwort auf mein Problem:

Aus meiner Anwendung heraus wird eine procedure aufgerufen (aus einer DLL), die ein Formular erzeugt und es anzeigt, aber nicht ShowModal!
Die DLL wird dynamisch erzeugt und nach erfolgreichem Ausführen der "Startprocedure" in der DLL die Caption eines in der Anwendung vorkommenden Labels auf 'Gestartet' gesetzt.
Wenn das DLL-Formular geschlossen wird, soll es das irgendwie der Anwendung mitteilen oder direkt die Caption des Labels auf 'Geschlossen' setzen.

Ich hab's selbst schon mit der Übergabe von Pointer, dem label selbst... versucht, aber es hat nie geklappt!

Könnt ihr mir sagen, wie ich das machen kann?

Also, du hast die DllMain() (== Startprocedure) und du hast eine Anwendung. Nun lädst du die DLL entweder über dynamisches Laden (oder weil sie statisch gelinkt ist) in den Adreßraum der Anwendung. Diese Anwendung hat ein Form TFormX? Oder die DLL hat ein From TFormY? Oder beide? Was soll passieren?

Du mußt hier sehr deutlich zwischen DLL und Anwendung unterscheiden. Das bitte ich dich mal zu tun um hier dein Problem herauszustellen. Ich kann jedenfalls noch immer dein Problem nicht verstehen.

Ich denke dies ließe sich einfach lösen, aber ich will hier nicht Rätselraten. Es ist nun an dir.

F.W. 28. Aug 2004 18:50

Re: Aus DLL auf Prgramm zugreifen
 
Ok, sorry!

Meine Anwendung und meine DLL haben 1 Form. Die Anwendung besteht aus einer Liste, in die alle DLLs gelesen werden, die sich im Ordner befinden.
Alle DLLs haben mindest. 2 Proceduren, GetInhalt und StartDLL.
Mit GetInhalt fragt die Anwendung beim Verzeichnischeck nach dem Inhalt der DLLs, quasi wie ein About, das die jeweilige DLL als String (PChar) zurückgibt.
Später kann man dann aus der Liste in der Anwendung eine DLL auswählen und sie wird mit StartDLL gestartet und läuft dann selbstständig (weil nicht Modal), bis sie oder die Andwendung beendet wird.

Das Prob: In der Liste wird ihr Handle gespeichert, dadurch kann sie von der Anwendung beendet werden. Wenn man jetzt aber am Formular der DLL Beenden anklickt, soll in der Liste das Handle zurückgesetzt werden (standartmäßig 0) und ein SubItem (Liste ist TListView) wird statt mit 'gestartet' mit 'nicht gestartet' o.ä. beschriftet.

:angel2:

Assarbad 28. Aug 2004 19:35

Re: Aus DLL auf Prgramm zugreifen
 
Aha, so langsam steige ich dahinter was du willst. Dann solltest du IMO folgendes machen.

StartDLL erzeugt ein Event/Mutex/... im Kontext der Anwendung und gibt das Handle zurück (StartDLL gibt also 1 Handle zurück). Dieses Event wird beim Entladen der DLL gepulst (PulseEvent()) und ein Thread (vorzugsweise der, der die DLl geladen hat) in der Hauptanwendung Wartet mit WaitForSingleObject() auf eben diesen Puls. Schon wissen beide Instanzen bescheid. Der wartende Thread kann dann dem Hauptform bescheidgeben, daß die DLL entladen ist und dieses kann den Status updaten.

Warum benutzt du aber eine eigene Func StartDLL() und nich direkt den Einsprungspunkt der DLL?

F.W. 28. Aug 2004 20:04

Re: Aus DLL auf Prgramm zugreifen
 
Ich habe mir über nichts gedanken gemacht, die Sachen, die du aufgezählt hast, sagen mir alle nicht viel.

Die Procedure StartDLL erzeugt nur die Form und zeigt sie an, danach kümmert sie sich. Es sollte quasi ein Starter werden, mit dem man die Sachen verwalten kann. Die DLLs waren zwar wie Plugins, liefen aber nach dem Start selbst ständig, ich könnte die StartDLL auch anders nennen...

Gibts da nicht noch was einfacheres?

Assarbad 28. Aug 2004 20:54

Re: Aus DLL auf Prgramm zugreifen
 
Es geht IMO nicht einfacher. Im Endeffekt müssen beide miteinander kommunizieren. Bei WMs hätte ich nur Bedenken, daß die nicht mehr abgesetzt werden, weil die DLL sich entlädt (ist aber nur eine Befürchtung). Versuch es halt mit WMs - wenn's nicht geht nimmste Mutexe o.ä.

F.W. 28. Aug 2004 23:34

Re: Aus DLL auf Prgramm zugreifen
 
Na gut, ic werd' mal sehen, tüfteln und ausprobieren! :coder2:

Assarbad 28. Aug 2004 23:59

Re: Aus DLL auf Prgramm zugreifen
 
Alternativ kannst du eine vereinfachte Version der Sourcen der DLL und der EXE hier reinstellen. Irgendjemand wird sich vermutlich erbarmen. Ab Montag auch ich wieder :-D

F.W. 29. Aug 2004 12:05

Re: Aus DLL auf Prgramm zugreifen
 
Nehmen wir mal ein vergleichbares einfacheres (aber sinnloses) Szenario: Die Anwendung hat ein TRichEdit und ein Editfeld.
Um den String aus dem Editfeld in das Richedit formatiert einzufügen ruft die Anwendung eine Procedure der DLL auf und übergibt ihr den String und irgendwas, (KEINE AHNUNG WAS!) damit die DLL Zuhriff auf das RichEdit der Anwendung hat.
Dann formatiert die DLL den String über das RichEdit und fügt ihn ein:
Delphi-Quellcode:
 TheRichEdit.SelAttributes.Color := clred;
 TheRichEdit.SelAttributes.Name := 'Courier New';
 TheRichEdit.SelAttributes.Size := 10;
 TheRichEdit.SelAttributes.Style := [fsBold];
 TheRichEdit.Lines.Add(S);
Wie das realisieren?

Danke!

Assarbad 29. Aug 2004 12:29

Re: Aus DLL auf Prgramm zugreifen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Siehe Anhang

Delphi-Quellcode:
// DLL-Code
function GetRichEditSetEdit(Rich:TRichEdit; Edit:TEdit):Boolean;
var
  s : String;
begin

  s := Edit.Text;

  Rich.SelAttributes.Color := clred;
  Rich.SelAttributes.Name := 'Courier New';
  Rich.SelAttributes.Size := 10;
  Rich.SelAttributes.Style := [fsBold];
  Rich.Lines.Add(S);

  Rich.Lines.Text := s;
end;
Delphi-Quellcode:
// EXE-Code
function GetRichEditSetEdit(Rich:TRichEdit; Edit:TEdit):Boolean;external 'Dingens.dll';

// TEdit == Pointer
// TRichEdit == Pointer
// Beide sind schließlich nur Instanzenpointer ... also kann man sie übergeben.
// Die aufgerufene Funktion muß nur über das Objekt bescheidwissen. Also immer
// DLL und EXE mit gleicher Delphi-Version kompilieren!!!

procedure TForm1.Button2Click(Sender: TObject);
begin
  GetRichEditSetEdit(RichEdit1, Edit1);
end;
Aber dieses Problem ist um einiges einfacher zu lösen als o.g. - oder???

Theoretisch kann man die Objektinstanzen auch typecasten - dazu verwendest du den AS-Operator

F.W. 29. Aug 2004 14:28

Re: Aus DLL auf Prgramm zugreifen
 
Endlich es funktioniert!!! :cheers: :witch: :dancer2: :hello:

Das reicht, damit sich die DLL selbst kümmert. Sie sucht jetzt im Listview nach ihrem Handle eintrag und setzt den Eintrag auf Gestoppt!
Den darum ging es mir ja! :warn:

F.W. 1. Okt 2004 21:20

Re: Aus DLL auf Prgramm zugreifen
 
Hallo nochmal!

:arrow: Ich überarbeite gerade ein Programm komplett. Und wollte die Variante mit der DLL benutzen, da dieser Teil oft in Updates drinstecken wird und da macht sich das mit DLLs einfach praktischer.

Dieses Mal ist es wie im Beispiel, ein RichEdit in den Text eingefügt werden soll. Aber der Text steht nicht in einem String, sondern in einem Stream.
Es wird also das RichEdit und der Stream übergeben (und das Hauptformular, weil geprüft wird, ob es sichtbar ist). Die DLL soll den String aus dem Stream lesen und ihn in das RichEdit einfügen, ans Formatieren denke ich momentan noch nicht.

Das Problem liegt jetzt darin, dass er nach der 1. zeile einfach aufhört die Anweisungen der Procedure abzuarbeiten:
Delphi-Quellcode:
(***************Ausschnitt aus der DLL***************)
  procedure GetMsg(RE: TRichEdit; MainForm: TForm; St: TStream); export; stdcall;

procedure GetMsg(RE: TRichEdit; MainForm: TForm; St: TStream);
var
 I: Integer;
 I64: Int64;
 Kennung: Char;
 S: String;
begin
 St.Seek(0, soFromBeginning); //<- Die Zeile macht er immer ohne Probleme
 St.ReadBuffer(Kennung, 1); //<- Diese Zeile macht er nicht mehr, aber er zeigt keinen Fehler an!
 if Kennung = 'T' then begin
    St.ReadBuffer(I, SizeOf(I));
    St.ReadBuffer(S[1], I);
    RE.Lines.Add(S);
    Melden(MainForm);

 end else if Kennung = 'C' then begin
    St.ReadBuffer(I, SizeOf(I));
  { ... }
 end else if Kennung = 'B' then begin
    St.ReadBuffer(I64, SizeOf(I64));
  { ... }
 end;
end;

//Und so wird alles aufgerufen:
(***************Ausschnitt aus dem programm***************)
  TGetMsg = procedure(RE: TRichEdit; MainForm: TForm; St: TStream);

  procedure GetMsg(RE: TRichEdit; MainForm: TForm; St: TStream); stdcall;

procedure GetMsg(RE: TRichEdit; MainForm: TForm; St: TStream);
var
 GM: TGetMsg;
 H: Cardinal;
begin
 if not FileExists(Main.Pfad+'DLL_Messaging.dll') then begin
    Beep;
    Exit;
 end;

 H := LoadLibrary(PChar(Main.Pfad+'DLL_Messaging.dll'));
 if H <> 0 then begin
    @GM := GetProcAddress(H, 'GetMsg');
    if @GM <> NIL then begin
       GM(RE, MainForm, St);
    end;
    FreeLibrary(H);
 end;
end;

procedure TMain.ServerExecute(AThread: TIdPeerThread);
var
 I: integer;
 St: TStream;
begin
 I := AThread.Connection.ReadInteger;
 if I > 0 then begin
    St := TMemoryStream.Create;
    try
      AThread.Connection.ReadStream(St, I);
      GetMsg(Main.RE, Main, St);
    finally
      St.Free;
    end;
 end;
end;
:warn: IMHO ist das wieder so ein Problem, wo man alles machen kann was man will, aber es nicht zum laufen bekommt, den ganzen Quelltext in ein neues Projekt kopieren... Würde nicht funktionieren. Nur wenn man sich eine Stunde hinsetzen würde und alles nochmal abtippen würde, dann würde wahrscheinlich alles gehn! :kotz:

Bitte helft mir, ich bin ratlos!

F.W. 2. Okt 2004 20:38

Re: Aus DLL auf Prgramm zugreifen
 
Einen weiteren Fehler habe ich inzwischen gefunden:

Delphi-Quellcode:
procedure GetMsg(RE: TRichEdit; MainForm: TForm; St: TStream);
 { ... }
if Kennung = 'T' then begin
    St.ReadBuffer(I, SizeOf(I));
[color=#ff0000]   SetLength(S, I);[/color]
    St.ReadBuffer(S[1], I);
    RE.Lines.Add(S);
    Melden(MainForm);

 { ... }
Allerdings, weil ich die hier ausgeführten Zeilen ins Programm geschrieben habe. Dort funktioniert es zwar, nütz mir aber nichts!

Armageddon 31. Dez 2004 10:41

Re: Aus DLL auf Prgramm zugreifen
 
Hallo,

ich habe heute mal das Beispiel von Assarbad genommen weil ich genau so einen Fall habe. Nur leider bringt er mir bei compilieren der Dll den Fehler das TEdit ein undefinierter Bezeichner ist. BeimRichEdite genau dasselbe. Hab ich was in der Uses vergessen oder an was könnt das liegen?

Gruß Arma

F.W. 31. Dez 2004 12:49

Re: Aus DLL auf Prgramm zugreifen
 
Jepp, du hast bestimmt in der Uses-Liste die Units der beiden Compos vergessen!

TEdit >> StdCtrls
TRichEdit >> ComCtrls

Armageddon 31. Dez 2004 16:17

Re: Aus DLL auf Prgramm zugreifen
 
Danke F.W.

genau das war's hab es vorhin selbst bemerkt. Trotzdem Danke. :-)

F.W. 22. Okt 2006 02:28

Re: Aus DLL auf Prgramm zugreifen
 
Guten morgen alle Früh-aufsteher :D oder Spät-ins-Bett-geher :D

Ich hätte nicht geglaubt, dass ich zu meinem heutigen Problem was in der Suche finde (ich tu mich irgendwie mit der Bezeichnung meiner Probleme schwer, oder mit den Schlagworten in der Suche). Aber ich hab was gefunden, und nicht irgendeinen Beitrag, sondern gerade auch noch einen von mir selbst :D

Problem: In diesem Posting bin ich speziell über folgende Zeilen gestolpert:
Delphi-Quellcode:
procedure GetMsg(RE: TRichEdit; MainForm: TForm; St: TStream);
 { ... }
 St.Seek(0, soFromBeginning); //<- Die Zeile macht er immer ohne Probleme
 St.ReadBuffer(Kennung, 1); //<- Diese Zeile macht er nicht mehr, aber er zeigt keinen Fehler an!
Das ist die Stelle mit der ich mein jetziges Problem mit diesem Thread verbinde! Bloß dass der Dll jetzt mal keine Beachtung geschenkt werden soll.

Ich arbeite in einer Procedure mit einem TFileStream. Zwischendurch soll ein Position in ihm gesucht werden, da das auch an anderen Stellen des Programms geschieht, ist der Teil in einer Funktion ausgelagert, dem der Stream als Parameter übergeben wird.
Nach dem Aufruf der Funktion ist mein Stream aber weg oder was auch immer ??

Mal Stückchen Quellcode:
Delphi-Quellcode:
//soviel zum Aufruf:
var
 FS: TFileStream;
begin
   if GetStartDataPosition(FS) = -1 then begin

//...


//das ist die aufgerufene Funktion:
function TMainForm.GetStartDataPosition(S: TFileStream): Integer;
var
 Buffer: String;
begin
 Result := -1;

//schauen ob [ENDE] als letztes im Stream steht
 S.Seek(-Length(EndString), soFromEnd);
 SetLength(Buffer, Length(EndString));
 S.ReadBuffer(Buffer, Length(EndString));// << böse Stelle <<

 // ...
end;
Ich habe mal etwas probiert:
Wenn in der Funktion nur S.Seek drinsteht, geht nachher noch alles.
Sobald ich aber S.ReadBuffer ausführe kann ich mit FS (von oben, in der aufrufenden Procedure) nicht mehr weiterarbeiten. Das lustige dabei ist aber, innerhalb von GetStartDataPosition kann ich nach S.ReadBuffer noch arbeiten

Kann mir das jemand erklären warum das so ist und was man dagegen machen kann?


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