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,SendCom mand,Logon ,Logout;
begin
if not assigned(DllProc) then
begin
DllProc := @DLLEntryPoint;
DllEntryPoint(Dll_Process_ Attach);
end;
end.
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,SendCom
begin
if not assigned(DllProc) then
begin
DllProc := @DLLEntryPoint;
DllEntryPoint(Dll_Process_
end;
end.
Hi!
You can use ExitProc variable.
See Delphi help for details.
HTH,
Andrew
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
if not assigned(DllProc) then
and have -
begin
DllProc := @DLLEntryPoint;
DllEntryPoint(Dll_Process_
end.
I have code like that, and it works for me
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;
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
ASKER
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
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
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.
ASKER
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
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?
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. . .
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. . .
ASKER
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.
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
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].Disconec t;
// 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.
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].Disconec
// 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.
ASKER
I have changed your code the way you said (ProcDLL(DLL_PROCESS_ATTAC H);) 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.
ASKER
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.
ASKER
i found updates for all other version of delphi except Delphi 6???
ASKER
in this link you have to be registered in order to able to dowanload.
ASKER
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.
https://www.experts-exchange.com/questions/20932760/Where-is-the-dll-destroy-event-of-an-ISAPI-dll.html
use the finalization part.