010.Delphi插件之QPlugins,遍历服务接口

这个DEMO注意是用来看一个DLL所拥有的全部服务接口

演示效果如下

代码如下:

unit Frm_Main;

interface

uses
  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.Variants,
  System.Classes,
  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.Dialogs,
  Vcl.StdCtrls,
  QPlugins,
  QPlugins_base,
  QPlugins_Params,
  QPlugins_Loader_Lib;

type
  TForm_Main = class(TForm)
    edtPluginsFile: TEdit;
    Label1: TLabel;
    Button1: TButton;
    Memo1: TMemo;
    OpenDialog1: TOpenDialog;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    procedure EnumFileServices(const AFileName: String);
  public
    { Public declarations }
  end;

var
  Form_Main: TForm_Main;

implementation

{$R *.dfm}

procedure TForm_Main.Button1Click(Sender: TObject);
var
  AExt: String;
  ALoader: IQLoader;
begin
  // 打开对话框加载DLL
  if OpenDialog1.Execute then
  begin
    // 根据路径的后缀名来判断是加载DLL还是BPL
    AExt := UpperCase(ExtractFileExt(OpenDialog1.FileName));
    if AExt = '.DLL' then
    begin
      // 通过路径获取指定的服务接口实例
      ALoader := PluginsManager.ByPath('/Loaders/Loader_DLL') as IQLoader;
      // 创建一个插件加载器
      if not Assigned(ALoader) then
      begin
        ALoader := TQDLLLoader.Create('', '.dll');
        PluginsManager.Loaders.Add(ALoader);
      end;
    end
    else // BPL
    begin
      ALoader := PluginsManager.ByPath('/Loaders/Loader_BPL') as IQLoader;
      if not Assigned(ALoader) then
      begin
        ALoader := TQBPLLoader.Create('', '.bpl');
        PluginsManager.Loaders.Add(ALoader);
      end;
    end;
    // 加载指定文件名的插件提供的所有服务
    ALoader.LoadServices(PWideChar(OpenDialog1.FileName));
    // 把路径显示在编辑框中
    edtPluginsFile.Text := OpenDialog1.FileName;
    // 遍历这个文件的服务
    EnumFileServices(OpenDialog1.FileName);
  end;
end;

// 遍历这个文件拥有的所有服务接口
procedure TForm_Main.EnumFileServices(const AFileName: String);
var
  AInst: HINST;
  // 遍历服务
  procedure EnumServices(AService: IQService);
  var
    AList: IQServices;
    I: Integer;
  begin
    // IQServices: 服务列表接口
    // IQService: 普通服务接口

    // 判断是IQServices还是IQService,如果是IQServices就进去遍历
    if Supports(AService, IQServices, AList) then
    begin
      for I := 0 to AList.Count - 1 do
      begin
        EnumServices(AList.Items[I]);
      end;
    end
    else // 如果是IQService就输出
    begin
      // 获取服务提供者模块句柄
      if AService.GetOwnerInstance = AInst then
      begin
        // 输出
        Memo1.Lines.Add(ServicePath(AService));
      end;
    end;
  end;

begin
  // GetModuleHandle获取一个模块(dll)的句柄
  AInst := GetModuleHandle(PChar(AFileName));
  // 输出模块地址
  Memo1.Lines.Add(AFileName + ' 注册的服务(基址:' + IntToHex(AInst, 8) + ')');
  // 遍历所拥有的服务
  EnumServices(PluginsManager as IQService);
end;

end.

 

posted @ 2019-09-10 13:49  像一棵海草海草海草  阅读(324)  评论(0编辑  收藏  举报