1

我想用插件开发 GUI 应用程序。插件包含从 Plugin-Core 库中的 Base Forms 继承的 VCL Forms。主应用程序可以选择动态加载哪个插件,然后显示哪些 Form 子类。

在用户方面,我想部署 main .EXE、插件核心库和许多针对不同模型的插件库。我可以向用户发布新的或修改现有的插件库,以在不修改主.EXE和 Plugin-Core 库的情况下为新设备显示新表单。

我开发的第一个版本使用 DLL 方法,即 Plugin-Core 库和插件都是 DLL 形式。在用户方面一切都很好。但是,在开发人员方面,如果没有在 Plugin-Core DLL 项目中定义的 Base Forms,则无法链接插件 DLL 项目。这意味着Base Forms实际上是静态链接在每个插件DLL项目中的,如果有一天我修改了Base Forms并重新构建Plugin-Core DLL项目,我必须重新构建所有插件DLL项目并重新发布插件.DLL用户,也是。

在StackOverflow中搜索和询问后,我意识到VCL Forms不能跨DLL边界继承的限制是由于RTTI冲突(?)。建议的解决方案是将库从 DLL 修改为 BPL 形式,这是我开发的第二个版本。除了以下两个之外,一切都很好:

  1. 从插件 BPL 动态加载的表单与Windows 任务栏中的主.EXE是分开的。这不是我想要的。解决方案是我在.EXE项目中启用了“使用运行时包构建” 。

  2. .EXE项目中启用“使用运行时包构建”后,我必须向用户发布其他 .BPL,例如vcl.bplrtl.bpl。这不是我想要的。

我想知道以上两个问题可以同时解决吗?在我看来,如果我可以解决这两个问题:

  1. 在.EXE项目中禁用“使用运行时包构建” 。
  2. 在所有.BPL项目中启用“使用运行时包构建” 。

这样,.EXE可以在没有捆绑vcl.bplrtl.bpl的情况下运行,并且插件.BPL可以成功加载,因为依赖单元已经是主.EXE的一部分?我对么?但是,所有.BPL项目选项中都禁用了“使用运行时包构建”复选框。结果,我没有机会检查解决方案是否有效。对于冗长的描述,我很抱歉,由于公司的互联网安全政策,我无法附上图片。

4

1 回答 1

1

从插件 BPL 动态加载的表单与 Windows 任务栏中的主 .EXE 是分开的。这不是我想要的。解决方案是我在 .EXE 项目中启用了“使用运行时包构建”。

加载 BPL 后,将 EXE 传递Application.Handle给 BPL 并将其分配给 BPL 自己的Application.Handle,然后再创建任何 Form 实例。

或者,在 Windows 7+ 上,您可以通过 EXE 调用SetCurrentProcessExplicitAppUserModelID()为其任务栏按钮建立 App ID。然后 BPL 中的每个表单都可以使用SHGetPropertyStoreForWindow()IPropertyStore.SetValue(PKEY_AppUserModel_ID)为其窗口设置相同的 App ID。具有相同 App ID 的多个窗口被组合在一个任务栏按钮下。

有关详细信息,请参阅 MSDN:应用程序用户模型 ID (AppUserModelIDs)

我想知道以上两个问题可以同时解决吗?在我看来,如果我可以解决这两个问题:

  1. 在 .EXE 项目中禁用“使用运行时包构建”。

  2. 在所有 .BPL 项目中启用“使用运行时包构建”。

这样,.EXE 可以在没有捆绑 vcl.bpl 和 rtl.bpl 的情况下运行,并且插件 .BPL 可以成功加载,因为依赖单元已经是主 .EXE 的一部分?我对么?

不能。BPL 不能像那样使用 EXE 的内置单元。

如果禁用“使用运行时包构建”,RTL/VCL 单元将静态链接到可执行文件中。这样做的问题是给定单元的多个副本不能同时加载到内存中,因此如果相同的 RTL/VCL 单元是静态链接的,您将无法一起(甚至根本)加载多个 BPL到多个 BPL,甚至是 EXE 本身。

如果启用“使用运行时包构建”,则可执行文件将依赖于 RTL/VCL BPL,然后必须对其进行部署。

因此,如果您的 EXE 和 BPL 共享公共单元,则必须通过共享 BPL 加载这些单元,以便在内存中仅存在这些单元的一份副本。在编写自定义 BPL 时无法避免这种情况。这意味着如果您使用基本的 RTL 功能,您通常至少必须部署 RTL.BPL,而对于 UI,您通常必须部署 VCL.BPL。

于 2016-05-05T19:51:43.993 回答