在运行时从包加载表单

时间:2014-12-10 13:00:45

标签: delphi dll plugins package bpl

我目前正在研究一些插件概念,并且在我使用dll或BPls的研究过程中遇到过,我现在决定使用bpls。

我想知道何时必须使用UnloadPackage(包模块);最好的观点,因为加载后立即给我什么都没有,因为形状然后立即消失

当前的计划结构

Hostapplication(PackageLoader.exe)
                |_Plugin.bpl
                 |_TPluginForm

enter image description here

PackageLoader.exe

var
  PackageModule : hModule;
  createProc: Procedure;
begin
  // Package laden
  try
  PackageModule := LoadPackage('plugin.bpl');
  If PackageModule <> 0 then
  begin
    @createProc := GetProcAddress( PackageModule, 'CreatePluginForm' ); // Funktion aus den Exports aufrufen
    if Assigned(CreateProc) then
      CreateProc
    else
      ShowMessage('GetProcAddress failed');
  end;
  finally
    //UnloadPackage(PackageModule);
  end;
end;

enter image description here

plugin.bpl - uPlugin.pas

unit uPlugin;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TPluginForm = class(TForm)
    Memo1: TMemo;
    Panel1: TPanel;
    Button1: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  PluginForm: TPluginForm;
  Status: Boolean;

implementation


uses
  uRandomString;

{$R *.dfm}

procedure TPluginForm.Button1Click(Sender: TObject);
var
  User, pwd, mail: String;
  ul, pl, ml: Integer;
begin
  Status := True;
  ul := StrToInt(Edit1.Text);
  pl := StrToInt(Edit2.Text);
 // ml := StrToInt(Edit3.Text);
  while Status do
  begin
    Application.ProcessMessages;
    User := RandomString(ul);
    pwd := RandomString(pl);
    //mail := RandomString(ml) + '@' + RandomString(5)+'.de';

    Memo1.Lines.Add(User+':'+pwd); //+':'+mail);
  end;
end;

procedure TPluginForm.Button2Click(Sender: TObject);
begin
  Status := False;
end;

function CreatePluginForm(ApplicationHandle, ParentHandle: THandle): boolean;
begin
  Result := False;
  PluginForm := TPluginForm.Create(nil);
  try
    PluginForm.Show;
    //PluginForm.ShowModal;
  finally

  end;
end;


exports
  CreatePluginForm;

initialization
  RegisterClass(TPluginForm);

finalization
  UnRegisterClass(TPluginForm);

end.

1 个答案:

答案 0 :(得分:2)

何时卸载软件包取决于应用程序的设计。鉴于我们对此并不了解,很难给出具体的建议。一种选择是您不要卸载包裹。为什么你觉得你需要这样做?如果需要卸载,则必须确保程序包中的代码仍未运行。您显示包中的表单。当您卸载包装时,该表格必须已被销毁。

我能看到的一个大问题是导入该功能的方式。它在包中声明如下:

function CreatePluginForm(ApplicationHandle, ParentHandle: THandle): Boolean;
begin
  ....
end;

exports
  CreatePluginForm;

然后你像这样导入它:

var
  createProc: Procedure;
....
@createProc := GetProcAddress(PackageModule, 'CreatePluginForm');
if Assigned(CreateProc) then
  CreateProc

您需要使用匹配的签名声明createProc

var
  createProc: function(ApplicationHandle, ParentHandle: THandle): Boolean;

然后当你调用它时,你需要传递两个句柄,并使用返回值做一些事情。

您的代码也泄漏PluginForm

最后,THandle似乎是错误的类型。我认为你打算使用HWND。虽然我不明白为什么你不能通过VCL对象。毕竟,您选择使用包,这意味着您可以直接传递父控件。而且您当然不需要传递与应用程序相关的任何内容,因为该插件已经可以看到该应用程序。