Delphi XE4: закрытие внутренней формы пакета приводит к прекращению работы приложения

У меня есть пакет test.bpl в моем приложении, и он имеет форму с именем myPackageForm. после загрузки моего пакета, когда я хочу закрыть myPackageForm, приложение завершает работу.

Инициализация основного проекта:

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 имеет процедуру класса, чтобы показать это:

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

А в OnClose Процедура имеет:

Release;

В качестве решения я пробую другую команду:

myPackagForm := TmyPackagForm.Create(Application); 

для создания myPackagForm;

Кто-нибудь может знать, что произошло в Delphi XE4 с командой CreateForm для пакетов?

2 ответа

Решение

Сэр Руфо получил основы. Первая форма, созданная с помощью вызова CreateForm становится основной формой. Когда основная форма закрывается, приложение закрывается.

Теперь вы показали два звонка CreateForm, Один в хост-приложении и один в вашем динамически загруженном пакете. И кажется очевидным, что первым запустится приложение хоста. Итак, как форма в пакете может сбить приложение? Что ж, это может произойти, как сказал сэр Руфо, только если в вашем процессе есть два экземпляра приложения.

Итак, следующий вопрос: как в вашем процессе может быть два экземпляра приложения? Этого не должно быть. Весь смысл пакетов состоит в том, чтобы позволить модулям Delphi быть разделенными между различными модулями. Если вы правильно создали приложение, то у вас будет только один экземпляр TApplication это разделяется между исполняемым файлом хоста и всеми вашими пакетами.

Итак, единственный разумный вывод, который нужно сделать, - это то, что один из ваших модулей не построен с использованием пакетов времени выполнения. Например, возможно, хост-приложение включает RTL/VCL, статически связанный внутри исполняемого файла. А ваши пакеты ссылаются на пакеты времени выполнения RTL/VCL. Или, возможно, это динамически загруженный пакет, который включает статически связанный RTL/VCL. Хотя IIRC, компилятор предотвращает это.

Что бы ни пошло не так, решение состоит в том, что все ваши модули должны быть собраны с использованием пакетов времени выполнения. Все библиотеки RTL / VCL должны быть связаны через пакеты времени выполнения и не должны быть связаны статически.

Итак, замена Application.CreateForm с TMyPackageForm.Create просто подавляет более широкую проблему. Очень важно, чтобы в вашем приложении был только один экземпляр RTL/VCL. Добейтесь этого, используя пакеты времени выполнения во всех ваших модулях.

Это, безусловно, тот случай, когда TMyPackageForm.Create это правильный способ создать форму в вашем пакете. Я использую только Application.CreateForm для основной формы. Я никогда не использую это где-нибудь еще. Но не пытайтесь решить вашу непосредственную проблему исключительно, удалив Application.CreateForm из вашей посылки. Исправьте ссылку на RTL/VCL.

TApplication.CreateForm не только создать форму, но и сделать первую форму, созданную этим методом, TApplication.MainForm,

А закрытие MainForm приводит к закрытию приложения.

ОБНОВИТЬ

У вас 2 TApplication экземпляры внутри вашего приложения.

  1. ваше нормальное приложение
  2. внутри BPL

Таким образом, ваша форма внутри BPL станет главной формой вашего BPL. Application и закрытие этой формы будет выполнять PostQuitMessage(0) в контексте вашего основного процесса приложения, и это заставляет все приложение выйти.

Другие вопросы по тегам