繁体   English   中英

动态加载BPL在LoadLibrary中失败

[英]Dynamically loading BPL fails in LoadLibrary

我想在Delphi 10 Seattle(更新1)或Delphi 10.1 Berlin项目(企业版)中动态加载BPL模块。 但是LoadPackage函数失败并显示消息(在32位和64位目标平台上):


Project LoadPackageTest.exe引发异常类EPackageError,并显示消息“无法在此处加载程序包的真实路径” \\ TestBplPackage.bpl。 指定的模块无法找到'。


我的开发平台是Windows 10 Pro 64位。

我确定传递的文件名正确(包含完整路径)。 我到目前为止所做的:

  • 如果在同一台Win 10 PC上使用Delphi 2007 Enterprise进行编译,则相同的项目组可以正常工作(我必须从头开始重新创建它)

  • 如果我加载标准.DLL-它将正确加载,并且可以在D2007,D10和D10.1中调用函数(适用于D10和D10.1上的32位和64位目标)。

实际上,LoadPackage调用了SafeLoadLibrary,后者调用了LoadLibrary(所有这些过程都在System.SysUtils中。

我编译了带有和不带有运行时软件包的测试可执行文件,其中包含代码:

DLL项目(TestDLL.dpr),在所有情况下均有效

library TestDLL;
uses SysUtils, Classes;
{$R *.res}
function GetMyTime: TDateTime; stdcall; 
begin 
  Result:= Now; 
end;
exports GetMyTime;
end.

BPL项目(TestBplPackage.dpr)

package TestBplPackage;
{ standard compiler directives - the project was created with New->Package}
requires
  rtl,
  vcl; 
contains
  TestBPLUnit in 'TestBPLUnit.pas';
end.

unit TestBPLUnit;
interface
function GetMyTime: TDateTime; stdcall;

implementation 
uses  classes, sysutils;  

function GetMyTime: TDateTime;
begin  
  Result:= Now;
end;
exports  GetMyTime;
end.

测试应用程序-LoadPackageTest.dpr

Form1:TForm包含dOpen:TOpenDialog和一个Button1:TButton

type
  TMyDateTimeFunction = function: TDateTime; stdcall;
procedure TForm1.Button1Click(Sender: TObject);
var
  ext: string;
  h: HModule;
  func: TMyDateTimeFunction;
begin
  if dOpen.Execute then begin
    ext:= ExtractFileExt(dOpen.FileName);
    if SameText(ext, '.bpl') then begin
      h:= LoadPackage(PChar(dOpen.FileName));
      if h > 0 then begin
        func:= GetProcAddress(h, 'GetMyTime');
        if Assigned(func) then
          ShowMessage(FormatDatetime('yyyy-mm-dd hh:nn:ss', func));
        UnloadPackage(h);
      end;
    end else if SameText(ext, '.dll') then begin
      h:= LoadLibrary(PChar(dOpen.FileName));
      if h > 0 then begin
        func:= GetProcAddress(h, 'GetMyTime');
        if Assigned(func) then
          ShowMessage(FormatDatetime('yyyy-mm-dd hh:nn:ss', func));
        FreeLibrary(h);
      end;
    end;
  end; //dOpen.execute
end;

有人尝试过类似的东西吗?

避免从项目管理器树的“包含”节点中删除单元-Delphi 10和10.1都崩溃...


编辑1:它在某些条件下工作

感谢大卫的回答,我设法取得了一些进展:
当相关的内容

or subfolders is either in the folder where the application and the test BPL are or in relevant or folder. 子文件夹位于应用程序和测试BPL所在的文件夹中,或者位于相关的文件夹中。

如果没有上述条件,尽管我俩都无法
and
were in the %PATH% Environment variable. 位于%PATH%环境变量中。 它没有找到RTL软件包。


如果应用程序依赖于%PATH%变量来查找必要的BPL,则有一个容易解释的副作用。 因为我有C:\\ Windows \\ SysWOW64; C:\\ WINDOWS \\ system32; C:\\ WINDOWS
在%PATH%变量中,如果我使用运行时程序包为Win32平台编译,则会收到以下错误消息:
应用程序无法正确启动(0xc000007b)
这是因为32位应用程序尝试加载64位BPL。

我可以轻松地交换System32和SysWOW64的位置,但这是全局变量,而不是用户路径变量,并且需要重新启动才能使更改生效。
" BPLs into the platform output folder. 我将继续进行试验,但是到目前为止,唯一可行的解​​决方案是将使用过的“ ” BPL保留在平台输出文件夹中。

异常文本指示对LoadLibrary的调用失败,并且GetLastError返回ERROR_MOD_NOT_FOUND 对此有两种常见的解释:

  1. DLL搜索找不到包文件。 可能是名称错误,或者程序包不在DLL搜索算法搜索的位置。
  2. 可以找到该软件包文件,但是找不到其依赖项之一。 例如,也许找不到rtl包。

使用Dependency Walker调试问题。 在配置文件模式下使用它,它将告诉您找不到哪个模块。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM