Link to home
Start Free TrialLog in
Avatar of ranjfoad
ranjfoad

asked on

unloading in DLL's

Hello
  I am developing a DLL using delphi, and i need to be able to do so intialization when the dll attached to an EXE and some clean up when deattched from the EXE. i have read from the help of Delphi and tried to find it in the internet, every one saying i have to use DllProc to define a new DLLEntryPoint, but the problem is this function is never executed.
  here is the code:

library HLR;


uses
  ShareMem,
  SysUtils,
  Classes,
  Types,
  dialogs,
  Oper in 'Oper.pas';  //another unit i use

const
  DLL_PROCESS_ATTACH = 1;                         // Executable attaches to DLL
  DLL_THREAD_ATTACH  = 2;                         // Thread in exe calls DLL
  DLL_THREAD_DETACH  = 3;                         // Thread leaves DLL
  DLL_PROCESS_DETACH = 0;                         // Exe detaches from DLL


procedure DLLEntryPoint(Reason: integer);
begin
  case Reason of
    Dll_Process_Attach:
        begin
         ShowMessage('in');
         HLRCon := HLRConnection.Create;
        end;
    Dll_Thread_Attach:
      sleep(1);
    Dll_Thread_Detach:
      sleep(1);
    Dll_Process_Detach:  //this never gets to execute
        begin
          ShowMessage('Out');
          FreeAndNil(HLRCon) ;
         end;
    else
      ShowMessage('Dont Know');
  end;                                          
end;

{$R *.res}
exports Connect,Disconnect,SendCommand,Logon,Logout;

begin
  if not assigned(DllProc) then
    begin
      DllProc := @DLLEntryPoint;
      DllEntryPoint(Dll_Process_Attach);
    end;
end.
Avatar of Mikho
Mikho
Flag of Sweden image

i would give same recommendation as madshi in this thread
https://www.experts-exchange.com/questions/20932760/Where-is-the-dll-destroy-event-of-an-ISAPI-dll.html


use the finalization part.
Avatar of DeerBear
DeerBear

Hi!

You can use ExitProc variable.

See Delphi help for details.

HTH,

Andrew
I think I would leave out the

if not assigned(DllProc) then

and have -

begin
 DllProc := @DLLEntryPoint;
 DllEntryPoint(Dll_Process_Attach);
end.


I have code like that, and it works for me
Avatar of ranjfoad

ASKER

I tiried ExitProc variable and it didnt work for me, and about  Slick812 suggestion i did that to, any way the existence of (if not assigned(DllProc) then) dose not make any difference on the code.
as I said before, that code works for me, if I have

DLLProc := @DllInit;
DllInit(DLL_PROCESS_ATTACH);

then the  Dll_Process_Detach  is called when the process drops the library, , , as far as I have seen this always seems to work . . .

I have no Idea why it does not seem to be called for you, All I can think of is the way you test it (just only thing I can even have as posibility), maybe your ShowMessage( ) will not be seen? I would try another way to get confirmation of the  Dll_Process_Detach  call, maybe a SendMessage( ), I know I have used a SendMessage in a   Dll_Process_Detach  before, and that worked for me. . .

procedure DLLEntryPoint(Reason: integer);
begin
  case Reason of
    Dll_Process_Attach:
        begin
         ShowMessage('in');
         HLRCon := HLRConnection.Create;
        end;
    Dll_Thread_Attach:
      sleep(1);
    Dll_Thread_Detach:
      sleep(1);
    Dll_Process_Detach:  //this never gets to execute
        begin
         // ShowMessage('Out');
        SendMessage(FHandle, WM_USER+1234, 42,543);
          FreeAndNil(HLRCon) ;
         end;
    else
      ShowMessage('Dont Know');
  end;                                          
end;
or you might try and create a text file in the   Dll_Process_Detach  and write to this file , and then see if the file exists, when you free the dll
I have even traced into the code of the DLL, and it never executed the  Dll_Process_Detach part
this is how i used the DLL

interface

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

function  Connect(IP: string;Port,TimeOut :integer;var ErrorMSG:string): boolean; stdcall;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

function  Connect; stdcall;  external 'D:\Pro\HLRDLL\hlr.dll' name 'Connect';

Its not the whole code but this should give you an idea about the way i used the DLL
try to load the dll dynamiccly

Information taken from Win32 Programmer's reference.

The LoadLibrary function maps the specified executable module into the address space of the calling process.

HINSTANCE LoadLibrary(

    LPCTSTR lpLibFileName       // address of filename of executable module
   );

i did a small project of my own with two buttons.
One to Load the dll using LoadLibrary and the other button to unload.
When unloading it did enter then Dll_Process_Detach:  part of your case scenario.

good luck
I agree with Mikho , I do not think thick that  stactically loaded dll functions will have a call for Dll_Process_Detach, because there is no FreeLibrary call for it
ShowMessage will not show up during process finalization. Probably your code *is* executed and you just think it's not. Create a test file instead of using ShowMessage to check sure whether you're code is executed or not.
I tired to load the DLL dynamically; but nothing changed, the Dll_Process_Detach is never passed and i get an error know when I call FreeLibrary after executing a function in the DLL.
ASKER CERTIFIED SOLUTION
Avatar of Member_2_248744
Member_2_248744
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
dear Slick812
  yes your code works fine, but for some reason this dose not work in my DLL, i think it may be because i have Sharemem in the uses section?
OK, It is my way when I set up a DLL, that I NEVER use the Sharemem in the library  .DPR program file or any Units in that Library, I feel that it is burden on the DLL and the calling program to try and share memory allocation information, , , You may not know, but from my understanding, a Library will have a compleatly separate memory manager than the calling program (and this assumes the calling program is a Delphi program), and the Sharemem will try and let the Two different memory managers share some mem allocation information about strings and other non-fixed arrays, but this share info will require extra methods, that I think is UN nessary, at least most of the time,. . . . In Delphi DLLs I Always use a  PChar  instead of a String  in any exproted functions or procedures, so I do NOT need the Sharemem, , You can use Strings inside the DLL all you like, just do not export them, use a PChar instead , , Delphi makes it relativly easy to go from Srting to PChar and back. . .

Also in a DLL I think that the   Application  variable is much different than the  Application  variable in a regular program, certanly it is NOT the same  Application that is in the calling program, so I do not use the   -  ShowMessage(  )  - in a DLL for message box show, I use the API  - MessageBox(  )  - function. . .

For me coding in a Library is a different way (methods, units) than coding in a regular Delphi program. . .

I really can not tell if your problem is with the Sharemem or not, I can not see any code that uses that in your Library code above. . .
After rechecking your code i noticed your code actually dose not work, i did not read it carefully first
the problem in your code is you call the deattach when you should call attach

ProcDLL(DLL_PROCESS_DETACH);

so the deattach is executed on startup not when unloading the dll, and you can check that from the text file, i always get

this is the DLL_PROCESS_DETACH, with Int1 = 0

no matter how many times i click on the button.
sorry about that, I should check my code more for misteaks, but I have very little time these days, thanks for pointing that out to me

sorry about it not helping your problem,

I recompiled the code above with the -

ProcDLL(DLL_PROCESS_DETACH);

changed to -

ProcDLL(DLL_PROCESS_ATTACH);

and I seem to get a file written with -

this is the DLL_PROCESS_DETACH, with Int1 = 5


 - - - - -  - - - - - -

so I am clueless,  don't know . . . . .
the documentations seem to indicate that this DLL_PROCESS_DETACH should be executed when ever the library is unloaded
A thing that I thought of, might help, , I see that you have a Unit in your uses clause for the library, and I guess that the HLRCon is a class in this Unit, , SO, as a way to NOT  use the DLLProc and DLL_PROCESS_DETACH in the library, I might try and use a  finalization  section in the .pas  unit. . .

also, , in some things I have used that did a connection, it is required to "Disconect"  all of the conections made before you Free the Object that does the connections (some even require that you Log  Off  all users thet you log On, before you Disconnect, but the connection you use may not require this). .

you might leave out all of the library  DLLProc code and have something like this in the finalization section of your unit -


finalization
for i := 0 to HLRCon.User.Count-1 do
  HLRCon.User[i].LogOff;

for i := 0 to HLRCon.Connect.Count-1 do
  HLRCon.Connect[i].Disconect;
// the lines above will not work in your case, but you might try your Log Off code,
//you may not need to Log Off and Disconnect for the HLRCon ? ?
// just here for a sugestion, I know nothing about the  HLRCon

FreeAndNil(HLRCon); // move the Release of the  HLRCon to here

end.
I have changed your code the way you said (ProcDLL(DLL_PROCESS_ATTACH);) but know it didn't write anything to the file , the process didnt execute at all, so i think it may by something to do with my Delphi(i have delphi 6). and i have tested it on win XP and win 2000.
Have you installed all D6 updates? D6 without any updates makes problems with DLL_PROCESS_DETACH.
no, i havent installed those updates. where i can get them? please if you can send me direct link because i am not registered at Borland.com and i have no support from them.
check ftp.borland.com

most updates are stored there.
anonymous login
i found updates for all other version of delphi except Delphi 6???
in this link you have to be registered in order to able to dowanload.
i found the updates in one of my CD's but when i install them the problem of the  DLL_PROCESS_DETACH is fixed but i get a new problem with ADO, when i debug my programs it gives me an error (access violation      in BOrdb61.dll)
That's a new question. At least you know now why DLL_PROCESS_DETACH didn't work - it was a bug in the non-patched D6.