Delphi XE4 : Closing Internal Package Form Causes Application Termination

382 views Asked by At

i have a test.bpl package in my application and it has a form named myPackageForm. after loading my Package when i want to close myPackageForm, Application will Terminate.

Main Project Initialization:

Application.Initialize;
Application.CreateForm(TMainForm,MainForm);
Application.Run;

MainForm FormCreate :

aPackage := LoadPackage('my bpl path'+test.bpl);
@P_ItemClick := GetProcAddress(aPackage,'ItemClickExcecute');

MainForm ButtonClick:

P_ItemClick(Sender);

testPackage CommandsUnit :

Procedure ItemClickExecute(Sender : TObject)
begin
   TmyPackageForm.ShowForm();
end;

exports
  ItemClickExecute;

end.

myPackagForm has a class procedure to show it:

Class Procedure TmyPackagForm.ShowForm;
begin
 if not Assigned(myPackagForm)
    myPackagForm := Application.CreateForm(TmyPackagForm ,myPackagForm );
 myPackagForm.Show;
end;

And in OnClose Procedure has:

Release;

As a solution i try another command:

myPackagForm := TmyPackagForm.Create(Application); 

to myPackagForm creation;

Can anybody know what happend in Delphi XE4 with CreateForm command on the packages?

2

There are 2 answers

0
David Heffernan On BEST ANSWER

Sir Rufo has got the basics covered. The first form created with a call to CreateForm becomes the main form. When the main form closes, the application closes.

Now, you have shown two calls to CreateForm. One in the host application, and one in your dynamically loaded package. And it seems clear that the first one to run is from the host application. So, how can the form in the package can bring down the application? Well, that can only happen, as Sir Rufo said, if there are two application instances in your process.

So the next question is, how can there be two application instances in your process? That should not happen. The entire point of packages is to allow Delphi units to be shared between different modules. If you have built your application correctly then you will have only one instance of TApplication that is shared between the host executable, and all of your packages.

So, the only reasonable conclusion to reach is that one of your modules is not built using runtime packages. For instance, perhaps the host application includes the RTL/VCL, linked statically inside the executable file. And your packages link to the RTL/VCL runtime packages. Or perhaps it is the dynamically loaded package that includes the RTL/VCL linked statically. Although IIRC, the compiler prevents that happening.

Whatever has gone wrong, the solution is that all your modules must be built using runtime packages. All the RTL/VCL libraries must be linked via runtime packages and must not be linked statically.

So, replacing Application.CreateForm with TMyPackageForm.Create is simply suppressing a wider problem. It is critical that you have only one instance of the RTL/VCL in your application. Achieve that by using runtime packages in all your modules.

It is certainly the case that TMyPackageForm.Create is the right way to create a form in your package. I only use Application.CreateForm for the main form. I never use it anywhere else. But don't try to fix your immediate problem solely by removing Application.CreateForm from your package. Fix the linking to the RTL/VCL.

3
Sir Rufo On

TApplication.CreateForm not only just create a form, but also make the first form created by this method the TApplication.MainForm.

And closing the MainForm results in closing the application.

UPDATE

You have 2 TApplication instances inside your application.

  1. your normal application
  2. inside the BPL

So your form inside the BPL will become the MainForm of your BPL.Application and closing this form will perform a PostQuitMessage(0) in the context of your main application process and this forces the whole application to quit.