Zwalnianie dll i zrzut głównego okna do paska

1

Przywitam się, pierwszy raz na forum. Jeśli coś zchrzanię z formatowaniem tekstu to przepraszam, to mój pierwszy raz ;)
Od wielu lat rozwijam pewne narzędzie w Delphi 7 i tak już pewnie zostanie. Nie mam mocy na migrację na nowsze środowisko.
Moja obecna konfiguracja to Windows 10 64 bit
Ostatnio pojawiła się konieczność wydzielenia pewnego fragmentu aplikacji do dll i wczytywania go oraz zwalniania na żądanie. Biblioteka ma być zwalniana po wykonaniu zadania. Powód tu nieistotny. Wszystko ok poza jednym dziwnym zachowaniem. Gdy wywołuję FreeLibrary to główne okno aplikacji jest hmm... chyba minimalizowane bo znika i po trzykrotnym kliknięciu w aplikację na pasku zadań okno wraca. Żadnych A/V nie odnotowałem. Stworzyłem testowo bibliotekę i aplikację wywołującą. Efekt ten sam. Jeśli natomiast nie dokonam przypisania Application.Handle := AHandle to efekt nie występuje ale to chyba nie tędy droga. Co robię źle?

Biblioteka:

library Proba2;

uses
  Windows,
  SysUtils,
  Classes,
  Forms;

{$R *.res}

function proba(AHandle:THandle; Napis:PChar; var Zwrot:PChar):Integer; StdCall;
begin
  Application.Handle := AHandle;    // <- bez tego wszystko jest ok
  Result := Length(String(Napis));
  Zwrot := PChar('Tekst '+Napis);
//  Application.MessageBox(PChar('Długość tekstu '+IntToStr(Result)),'--',mb_ok);
end;

exports
 proba;
 
begin
end. 

** główny unit aplikacji:**

unit Proba3Main;

interface

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

type
  Tproba_proc = function (AHandle:THandle; Napis:PChar; var Zwrot: PChar):Integer; StdCall;

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var Res:Integer;
    proba : Tproba_proc;
    DLLHandle   : THandle;
    Zwr:PChar;
    ZwS :String; {tylko do testów}
begin
  try
    DLLHandle := LoadLibrary('Proba2.dll');
    if DLLHandle = 0 then raise Exception.Create('Brak biblioteki Proba2.dll');

    @proba := GetProcAddress(DLLHandle, 'proba');

    if  @proba = nil then raise Exception.Create('Błąd wiązania proba w proba2.dll');

     Form1.Caption := IntToStr(proba(Application.Handle, PChar('Napis'), Zwr));
     ZwS := String(Zwr);
     Form1.Caption := Form1.Caption + ZwS;
   finally
    // @proba := nil;
     FreeLibrary(DLLHandle);
   end;
end;

end.
4

przed zwolnieniem biblioteki musisz przywrócić jej oryginalny handle. Możesz to zrobić dopisując dedykowaną metodę albo obsługując Dll_Process_Detach https://www.oreilly.com/library/view/delphi-in-a/1565926595/re70.html

0

@abrakadaber: Dziękuję bardzo. Działa. Nadpisałem DLLProc i reaguję na reason = DLL_PROCESS_DETACH Jeszcze tylko uściślenie. Czy "oryginalny handle" biblioteki to 0 (bo wcześniej nie istniała) czy też muszę go wcześniej gdzieś przechwycić? Próbowałem łapać handle w eksportowanej procedurze jeszcze przed nadpisaniem jej przez AHandle ale Application.Handle jest tu właśnie równe 0. Chyba, że (zgaduję) może być różne od zera gdy biblioteka jest już załadowana przez inny wątek? Bo gdyby zmieniał się przy załadowaniu przez inną aplikację to by było bez sensu.

1

powinieneś zapamiętać przed podmianą i potem przywrócić.

1 użytkowników online, w tym zalogowanych: 0, gości: 1