m_adil
asked on
Dll Problem
Hi,
I've develpoed a dll that contains a form and some edit boxes. It reads and writes some values from registry. The dll is working fine with an Delphi application, but when I try this with rundll32, it gives me an error **Invalid page fault error**
Infact Rundll32 correctly executes the dll (Correctly reads & writes values to the registry). The error comes when I close the form in the dll.
what could be the possible error.
I've develpoed a dll that contains a form and some edit boxes. It reads and writes some values from registry. The dll is working fine with an Delphi application, but when I try this with rundll32, it gives me an error **Invalid page fault error**
Infact Rundll32 correctly executes the dll (Correctly reads & writes values to the registry). The error comes when I close the form in the dll.
what could be the possible error.
Delphi had in earlier versions some problems with thread-saftey. This could be PERHAPS a reason for you problem:
1. Don't use sharemem.pas
2. Don't pass 'string'-vars in DLL-calls, use PChars instead
Try this. If it don't helps give us further information on your configuration (Delphi-Version, Windows etc...)
1. Don't use sharemem.pas
2. Don't pass 'string'-vars in DLL-calls, use PChars instead
Try this. If it don't helps give us further information on your configuration (Delphi-Version, Windows etc...)
Are you starting a specific function with RunDll? Or only the initialization of the DLL? If you start a specific function, please show us the code of the function.
Then you can try it with removing the code in the function (or in the initialization). Does it work then? If yes: Add the code again, but only half of the code. This way you should find the line which is responsible for the problem.
Regards, Madshi.
Then you can try it with removing the code in the function (or in the initialization). Does it work then? If yes: Add the code again, but only half of the code. This way you should find the line which is responsible for the problem.
Regards, Madshi.
ASKER
I'm using Delphi-3, win-95/NT-4.
>> Delphi had in earlier ...
I'm not passing any var. to dll.
Yes Madshi I'm calling a specific function with RunDll. First I wrote a starting function that returns True if user clicks ok and False if cancel but afterwards I changed the function to procedure but the problemd persists in both cases.
Here is the DLL code
========================== =======
unit Main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Registry, StdCtrls, ExtCtrls, ComCtrls;
type
TForm1 = class(TForm)
PageControl1: TPageControl;
TabSheet1: TTabSheet;
TabSheet2: TTabSheet;
Panel1: TPanel;
Button1: TButton;
Button2: TButton;
GroupBox1: TGroupBox;
Label1: TLabel;
Label5: TLabel;
fName: TEdit;
Pwd: TEdit;
GroupBox2: TGroupBox;
CheckBox1: TCheckBox;
Label6: TLabel;
proxy: TEdit;
Label7: TLabel;
port: TEdit;
procedure ReadRegistry;
procedure CheckBox1Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure WriteRegistry;
private
{ Private declarations }
public
{ Public declarations }
end;
// extern DLL function declaration
procedure loadSettings; stdcall;
//function loadSettings:Boolean; stdcall;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.ReadRegistry;
var
Reg:TRegistry;
begin
Reg:= TRegistry.Create;
Reg.RootKey:= HKEY_CLASSES_ROOT;
if Reg.OpenKey('CLSID\{BDE179 13-32E5-11 d2-8D84-00 400557ABF6 }\Settings ', FALSE) then
begin
fName.Text:= Reg.ReadString('userName') ;
proxy.Text:= Reg.ReadString('proxy');
port.Text := Reg.ReadString('port');
CheckBox1.Checked:= Reg.ReadBool('Firewall');
end;
Reg.CloseKey;
Reg.Destroy;
end;
//function loadSettings:Boolean;
procedure loadSettings;
begin
Try
try
Form1:= TForm1.Create(Application) ;
Form1.ReadRegistry;
if Form1.ShowModal = mrOK then
Form1.WriteRegistry;
finally
Form1.Free;
end;
Except
on E: Exception do
MessageDlg('An error occured '+ E.Message, mtError, [mbok], 0);
end; //except
end;
procedure TForm1.CheckBox1Click(Send er: TObject);
begin
proxy.Enabled:= CheckBox1.Checked;
port.Enabled := CheckBox1.Checked;
end;
procedure TForm1.Button1Click(Sender : TObject);
begin
//Form1.WriteRegistry;
end;
procedure TForm1.WriteRegistry;
var
Reg:TRegistry;
begin
Reg:= TRegistry.Create;
Reg.RootKey:= HKEY_CLASSES_ROOT;
if Reg.OpenKey('CLSID\{BDE179 13-32E5-11 d2-8D84-00 400557ABF6 }\Settings ', FALSE) then
begin
Reg.WriteString('userName' ,fName.Tex t);
Reg.WriteString('proxy', proxy.Text);
Reg.WriteString('port', port.Text);
Reg.WriteBool('Firewall', CheckBox1.Checked);
end;
Reg.CloseKey;
Reg.Destroy;
end;
end.
========================== ====
and here is the DPR file
library Config;
uses
Main in 'Main.pas' {Form1};
exports
loadSettings;
end.
========================== =======
>> Delphi had in earlier ...
I'm not passing any var. to dll.
Yes Madshi I'm calling a specific function with RunDll. First I wrote a starting function that returns True if user clicks ok and False if cancel but afterwards I changed the function to procedure but the problemd persists in both cases.
Here is the DLL code
==========================
unit Main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Registry, StdCtrls, ExtCtrls, ComCtrls;
type
TForm1 = class(TForm)
PageControl1: TPageControl;
TabSheet1: TTabSheet;
TabSheet2: TTabSheet;
Panel1: TPanel;
Button1: TButton;
Button2: TButton;
GroupBox1: TGroupBox;
Label1: TLabel;
Label5: TLabel;
fName: TEdit;
Pwd: TEdit;
GroupBox2: TGroupBox;
CheckBox1: TCheckBox;
Label6: TLabel;
proxy: TEdit;
Label7: TLabel;
port: TEdit;
procedure ReadRegistry;
procedure CheckBox1Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure WriteRegistry;
private
{ Private declarations }
public
{ Public declarations }
end;
// extern DLL function declaration
procedure loadSettings; stdcall;
//function loadSettings:Boolean; stdcall;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.ReadRegistry;
var
Reg:TRegistry;
begin
Reg:= TRegistry.Create;
Reg.RootKey:= HKEY_CLASSES_ROOT;
if Reg.OpenKey('CLSID\{BDE179
begin
fName.Text:= Reg.ReadString('userName')
proxy.Text:= Reg.ReadString('proxy');
port.Text := Reg.ReadString('port');
CheckBox1.Checked:= Reg.ReadBool('Firewall');
end;
Reg.CloseKey;
Reg.Destroy;
end;
//function loadSettings:Boolean;
procedure loadSettings;
begin
Try
try
Form1:= TForm1.Create(Application)
Form1.ReadRegistry;
if Form1.ShowModal = mrOK then
Form1.WriteRegistry;
finally
Form1.Free;
end;
Except
on E: Exception do
MessageDlg('An error occured '+ E.Message, mtError, [mbok], 0);
end; //except
end;
procedure TForm1.CheckBox1Click(Send
begin
proxy.Enabled:= CheckBox1.Checked;
port.Enabled := CheckBox1.Checked;
end;
procedure TForm1.Button1Click(Sender
begin
//Form1.WriteRegistry;
end;
procedure TForm1.WriteRegistry;
var
Reg:TRegistry;
begin
Reg:= TRegistry.Create;
Reg.RootKey:= HKEY_CLASSES_ROOT;
if Reg.OpenKey('CLSID\{BDE179
begin
Reg.WriteString('userName'
Reg.WriteString('proxy', proxy.Text);
Reg.WriteString('port', port.Text);
Reg.WriteBool('Firewall', CheckBox1.Checked);
end;
Reg.CloseKey;
Reg.Destroy;
end;
end.
==========================
and here is the DPR file
library Config;
uses
Main in 'Main.pas' {Form1};
exports
loadSettings;
end.
==========================
ASKER
I've found another thing in MSDN
To call 32-bit DLL with RunDll32:
void CALLBACK
EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
whats this!!
To call 32-bit DLL with RunDll32:
void CALLBACK
EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
whats this!!
Yes, you've found the right idea on MSDN. Functions that you call via RunDll32 must look like this:
procedure loadSettings(window, hInstance: dword; cmdLine: pchar; showCmd: integer); stdcall;
Regards, Madshi.
procedure loadSettings(window, hInstance: dword; cmdLine: pchar; showCmd: integer); stdcall;
Regards, Madshi.
ASKER
so what are the parameters that I've to pass to rundll32.
Currently I'm using the cmdLine
rundll32 mydll,loadSettings
Currently I'm using the cmdLine
rundll32 mydll,loadSettings
You could start it as this:
RUNDLL32.EXE mydll.dll,loadSettings 777 Teststring
But I'm quite sure that you can start it as you've done (without any additional parameters). Just change the parameters of the loadSettings function. I think it will work then.
RUNDLL32.EXE mydll.dll,loadSettings 777 Teststring
But I'm quite sure that you can start it as you've done (without any additional parameters). Just change the parameters of the loadSettings function. I think it will work then.
ASKER
Yup this works fine. but there is a little problem. How can i pass an argument to loadSettings procedure.
I've tried
procedure loadSettings(n, window, hInstance: dword; cmdLine: pchar; showCmd: integer); stdcall;
where n is the parameter of int type I've to send.
I used cmdLine
rundll32 mydll,loadSettings(1)
but it give me the error Entry point not found
Except this it is working fine!!
I've tried
procedure loadSettings(n, window, hInstance: dword; cmdLine: pchar; showCmd: integer); stdcall;
where n is the parameter of int type I've to send.
I used cmdLine
rundll32 mydll,loadSettings(1)
but it give me the error Entry point not found
Except this it is working fine!!
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks alot!!!
Motaz