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.
LVL 1
ranjfoadAsked:
Who is Participating?
 
Slick812Connect With a Mentor Commented:
OK, I will do a Demo DLL library and the code in a program to use the library and test to see if a file is written when the library is "Detatched" . . .

frist, here is the code I used for a simple library -




library DemoDll;

uses Windows;

var
Int1: Integer;

function Some_Function: Integer;
begin
// an exported function
Result := Int1;
Inc(Int1);
// I do not need stdcall so I do not use it
end;


procedure StartUp;
begin
// process attatch
Int1 := 0;
end;

procedure Finish;
var F1: TextFile;
S1: String;
begin
// process detatch
Str(Int1, S1);
// write a file to DISK to see if the DLL_PROCESS_DETACH is called
AssignFile(F1, 'E:\DllKill.txt');
Rewrite(F1);
Writeln(F1, 'this is the DLL_PROCESS_DETACH, with Int1 = '+S1);
CloseFile(F1);

//MessageBox(0,'Finish in the DLL','DLL_PROCESS_DETACH', MB_OK or MB_ICONERROR);
end;

procedure ProcDLL(Action: Integer);
begin
if Action = DLL_PROCESS_ATTACH then
  Startup
  else
  if Action = DLL_PROCESS_DETACH then
    Finish;

end;

exports
  Some_Function;

begin
DLLProc := @ProcDLL;
// standard  DLLProc setup
ProcDLL(DLL_PROCESS_DETACH);
end.


= = = = = = = = = = = = = = = = = = = = = = == = = = = = = = =

next is the code in the Program to use this DLL - -


var
  Form1: TForm1;

implementation

{$R *.DFM}

function Some_Function: Integer; external 'DemoDll.dll';



procedure TForm1.sbut_DLL_FuncClick(Sender: TObject);
begin
// this is a button click that uses the DLL Some_Function
ShowMessage(IntToStr(Some_Function));
end;


 = = = = = = = = = = = = = = = = = =  = = = = = =

and EVERY TIME, without fail for me, ,  the  file  E:\DllKill.txt  is written to disk, when this library is detatched, program is closed
0
 
MikhoCommented:
i would give same recommendation as madshi in this thread
http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_20932760.html


use the finalization part.
0
 
DeerBearCommented:
Hi!

You can use ExitProc variable.

See Delphi help for details.

HTH,

Andrew
0
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

 
Slick812Commented:
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
0
 
ranjfoadAuthor Commented:
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.
0
 
Slick812Commented:
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;
0
 
Slick812Commented:
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
0
 
ranjfoadAuthor Commented:
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
0
 
MikhoCommented:
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
0
 
Slick812Commented:
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
0
 
MadshiCommented:
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.
0
 
ranjfoadAuthor Commented:
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.
0
 
ranjfoadAuthor Commented:
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?
0
 
Slick812Commented:
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. . .
0
 
ranjfoadAuthor Commented:
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.
0
 
Slick812Commented:
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
0
 
Slick812Commented:
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.
0
 
ranjfoadAuthor Commented:
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.
0
 
MadshiCommented:
Have you installed all D6 updates? D6 without any updates makes problems with DLL_PROCESS_DETACH.
0
 
ranjfoadAuthor Commented:
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.
0
 
MikhoCommented:
check ftp.borland.com

most updates are stored there.
anonymous login
0
 
ranjfoadAuthor Commented:
i found updates for all other version of delphi except Delphi 6???
0
 
ranjfoadAuthor Commented:
in this link you have to be registered in order to able to dowanload.
0
 
ranjfoadAuthor Commented:
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)
0
 
MadshiCommented:
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.
0
All Courses

From novice to tech pro — start learning today.