如何仅部署 .EXE 和自定义 .BPL 文件?

Posted

技术标签:

【中文标题】如何仅部署 .EXE 和自定义 .BPL 文件?【英文标题】:How to deploy ONLY .EXE and custom .BPL files? 【发布时间】:2016-05-05 07:02:58 【问题描述】:

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

在用户端,我想部署主要的.EXE,Plugin-Core 库,以及针对不同模型的许多插件库。我可以向用户发布新的或修改现有的插件库,以便为新设备显示新的表单,而无需修改主 .EXE 和 Plugin-Core 库。

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

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

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

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

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

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

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

【问题讨论】:

【参考方案1】:

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

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

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

更多详情请参见 MSDN:Application User Model IDs (AppUserModelIDs)

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

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

    在所有 .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。

【讨论】:

嗨@Remy。非常感谢,再次。 1.“将EXE的Application.Handle传递给BPL并将其分配给BPL自己的Application.Handle”==>这似乎不适用于BPL的VCL表单。但这适用于 DLL。我的第一个版本开发就是这样做的。 2. 我的 BPL 项目的“使用 rumtime 包构建”复选框被禁用,并且未被选中。我猜这意味着 rtl.bpl 和 vcl.bpl 静态链接到我的 BPL 中。因此,唯一的解决方案是在 .EXE 项目中启用“使用 rumtime 包构建”,以防止出现 VCL/BPL 单元的多个副本,对吗?

以上是关于如何仅部署 .EXE 和自定义 .BPL 文件?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Gradle 的“仅工件表示法”和自定义工件名称

在Windows Server 2022中使用Microsoft Deployment Toolkit(MDT)时,可使用Rules(规则)文件来配置和自定义部署过程。以下是常见的Rules参数及其描

如何使 AzureAD 和自定义 JWT 令牌在 Web API 中并行工作?

OpenCSV:如何使用自定义列标题和自定义列位置从 POJO 创建 CSV 文件?

在应用程序启动时预加载 Ext JS 和自定义 JavaScript 文件

如何将对象类和自定义属性添加到 LDIF 文件?