zoukankan      html  css  js  c++  java
  • 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.
  • 相关阅读:
    一文搞懂字符集
    机器视觉之eVision
    PID调节
    激光切割质量主要影响因素
    155. 最小栈
    111.二叉树最小深度
    110. 平衡二叉树
    108.将有序数组转换为二叉搜索树
    107. 二叉树的层次遍历 II
    104. 二叉树的最大深度
  • 原文地址:https://www.cnblogs.com/tianpan2019/p/11497087.html
Copyright © 2011-2022 走看看