Проблемы с работой формы в DLL в Delphi 12: почему компоненты не работают через rundll32.exe и как это исправить?
Разработка DLL-библиотек с графическим интерфейсом в Delphi всегда была сопряжена с особенностями, а в версии 12 Athens многие разработчики столкнулись с новыми проблемами при использовании форм через rundll32.exe. В этой статье разберем типичные ошибки и предоставим рабочие решения.
Проблема: компоненты формы не работают через rundll32.exe
Пользователь Anna Blanca столкнулась с ситуацией, где её DLL с формой корректно работала в Delphi 11, но перестала функционировать в Delphi 12 при запуске через rundll32.exe. Код выглядел так:
После перехода на Delphi 12 компоненты формы перестали реагировать на события, хотя при запуске через основное приложение всё работало.
Причина: нарушение соглашения вызова для rundll32
Remy Lebeau правильно указал на ключевую ошибку: функция, экспортируемая в DLL для rundll32, должна строго соответствовать сигнатуре, ожидаемой Windows:
В Delphi 11 код мог работать "случайно" благодаря особенностям управления памятью, но в версии 12 Athens Embarcadero ужесточила требования к совместимости.
Важно! Тип HINST объявлен в модуле System. Если IDE подчеркивает его красным, добавьте Winapi.Windows в uses.
Дополнительная проблема: создание COM-объектов в DLL
Anna также столкнулась с проблемой создания ярлыков (.lnk) через IShellLink. Код работал в EXE, но не в DLL при запуске через rundll32.
Причина: COM не был инициализирован. В отличие от VCL-приложения, где CoInitialize вызывается автоматически, в DLL это нужно делать вручную.
Исправленный код с инициализацией COM:
procedure Start(...); stdcall;
begin
// Инициализация COM для текущего потока
if Failed(CoInitializeEx(nil, COINIT_MULTITHREADED)) then
Exit;
try
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.ShowMainForm := False;
Application.Run;
finally
CoUninitialize; // Важно для очистки COM
end;
end;
Совет: Всегда используйте OleCheck для обработки ошибок COM.
Почему в EXE работало, а в DLL — нет?
Управление памятью: В EXE VCL автоматически инициализирует COM и создает контекст для форм.
Контекст выполнения: rundll32.exe не предназначен для запуска GUI через DLL. Это "хак", который требует ручной настройки.
Версии Delphi: Начиная с Delphi 12, RTL стал строже относиться к соглашениям вызова и инициализации модулей.
Альтернативное решение: используйте отдельный EXE-загрузчик
Если вам критично нужно стабильное GUI в библиотеке, рассмотрите архитектуру с двумя модулями:
1. DLL — содержит бизнес-логику.
2. EXE-загрузчик — вызывает DLL и создает формы.
// В DLL
procedure ShowForm; stdcall;
begin
Form1 := TForm1.Create(nil);
try
Form1.ShowModal;
finally
Form1.Free;
end;
end;
// В EXE
procedure TLoaderForm.Button1Click(Sender: TObject);
var
LibHandle: HMODULE;
ShowFormProc: procedure; stdcall;
begin
LibHandle := LoadLibrary('MyGuiLib.dll');
if LibHandle <> 0 then
begin
@ShowFormProc := GetProcAddress(LibHandle, 'ShowForm');
if Assigned(ShowFormProc) then
ShowFormProc();
FreeLibrary(LibHandle);
end;
end;
Отладка DLL в Delphi IDE
Чтобы отладить DLL, запускаемую через rundll32:
1. В меню выберите Run > Parameters.
2. В поле Host Application укажите путь к rundll32.exe (обычно C:\Windows\System32\rundll32.exe).
3. В Parameters укажите вашу DLL и функцию: MyLib.dll,Start.
4. Установите точки останова и запустите проект (F9).
Заключение
Проблемы с формами в DLL в Delphi 12 возникают из-за ужесточения требований к совместимости и инициализации.
Ключевые моменты для исправления:
1. Соблюдайте точную сигнатуру функций для rundll32.
2. Всегда инициализируйте COM вручную в DLL.
3. Используйте CoInitializeEx/CoUninitialize в паре.
4. Рассмотрите альтернативные архитектуры с EXE-загрузчиком.
Примеры кода из статьи можно адаптировать под ваши задачи. Помните, что использование rundll32 для GUI — нестандартный сценарий, поэтому всегда тестируйте поведение в целевых версиях Windows.
Проблемы с работой форм в DLL в Delphi 12 из-за неправильной сигнатуры функций и отсутствия инициализации COM, и способы их решения.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS