关于Delphi的Bpl包的加载问题。(300分)

  • 主题发起人 主题发起人 kkkchenA
  • 开始时间 开始时间
K

kkkchenA

Unregistered / Unconfirmed
GUEST, unregistred user!
现在有一个系统,所有的功能模块都是有Bpl以插件的形式提供,在运行的时候,主程序通过LoadPack函数加载该插件,然后在通过接口把插件的功能注册到界面的菜单、工具栏上。
在这样的程序里面,主程序必须要用Build with runtime packages方式来编译。

我的问题是这样的,用带包编译的方法在发布的时候要带上所有用到的控件的运行期包,这样的话,就造成了发布上的困难,而且也会带来版本控制上的麻烦。
我尝试在编译主程序的时候只选择VCL,RTL两个运行时库,把其他运行库都编译到程序中。但是在加载插件的时候,如果主程序中使用了某些控件,而这些控件同时也在插件中使用的话,那么就会提示某某类已经注册错误,造成加载Bpl插件失败。

请问,那位大侠有解决这类问题的办法呢?
也许,不使用BPL,使用DLL是最好的办法。
 
BPL本身就是一种分布的DLL.
 
我尝试在编译主程序的时候只选择VCL,RTL两个运行时库,把其他运行库都编译到程序中
=====================
如果这样的话做bpl就没什么意义了。


但是在加载插件的时候,如果主程序中使用了某些控件,而这些控件同时也在插件中使用的话,那么就会提示某某类已经注册错误,造成加载Bpl插件失败。
===============================
你这些插件是运行时包吗?如果是运行时包,通过registerclass自己手工注册,不会出现这些问题。如果是设计时包,搜索RegisterComponents函数,看看都注册了些什么
 
用带包编译的方法在发布的时候要带上所有用到的控件的运行期包,这样的话,就造成了发布上的困难,而且也会带来版本控制上的麻烦
===================================
对于这个问题我们是这样解决的,有一个配置文件,诸如 rtl.bpl=1.0.0.1的形式,主程序运行起来时,先到服务器加载该文件,读取所有包的版本号,然后跟客户端的bpl比较,如果服务器的bpl版本新,自动将其下载至本地覆盖老版本的bpl
 
这个分数多,哈哈,我喜欢,我知道怎么解决。
在Build with runtime packages下面的文本框填入你所使用的控件的bpl(如)名字就行了
 
to fenian
呵呵,跟你想的没错,我只是想要把我需要的部分做成插件而已,所以其他部分我想把它编译到我的Exe中。
例如我的Exe跟我的某个Bpl插件包中都使用的了某个Express控件,那么Bpl插件在编译的时候会自动引用Express控件的某个包。如果我把个Express的包编译到Exe中的话,那么,加载我的插件Bpl的时候,就会说某Express控件已经注册了.........郁闷。
 
to adden_lian
分数不是问题,只要能解决问题。
 
to fenian
确实有分发上的麻烦,现在我在维护的那个程序里面,把所有的控件的运行期包都Copy到了用户的System32目录下面,如果我一不小心,用了一个不同版本的控件,而这两个不同版本的控件又有兼容上的问题的话,那么到客户运气不好的话,就运行不起来了。

例如现在我的那些插件的BPL里面就引用了这么一堆控件。
cxLibraryVCLD7, dxThemeD7, cxEditorsVCLD7, cxDataD7, cxPageControlVCLD7, cxGridVCLD7, cxExtEditorsVCLD7, dxBarD7
dxComnD7, dxNavBarD7, dxGDIPlusD7, Rz30Ctls70。
如果我的主程序不把他们加入到Build with runtime packages 下面的输入框的话,那么在加载某一个插件Bpl的时候就说某某已经注册了。而且我要改这么多的控件包的注册函数的话,那么肯定是一个浩大的工程。
还有没有其他办法呢?
 
按我的方法不能解决吗?
 
to 蓝叶菱
我在使用DLL作为插件的时候,就没有了BPL这样的问题,呵呵,各有各的优点吧。
 
为什么不能让插件提供生成窗体的参数,实际窗体由主程序构造呢?这样只要插件和主程序享有同样的interface接口,不存在交互问题啊?这样实现的插件更加灵活。
 
to zqw0117
现在在已有的代码中,是用BPL来做插件的,在使用中用LoadPack在加载。呵呵,我也不知道我的上一任为什么要这样设计。
 
例如我的Exe跟我的某个Bpl插件包中都使用的了某个Express控件,那么Bpl插件在编译的时候会自动引用Express控件的某个包。如果我把个Express的包编译到Exe中的话,那么,加载我的插件Bpl的时候,就会说某Express控件已经注册了.........郁闷。

=====================
Express的源代码肯定有吧,应该有两个包,运行时和设计时包,你的程序加载的应该是其运行时包,如果没有的话自己做一个不难,然后通过registerclasses注册用到的类,或者注册之前判断有否注册过(应该有相关函数吧,没有研究),没有注册再registerclass,实在不好判断直接try registerclass except ; 试试看呢
 
to fenian
Express控件的运行期、设计期包是做的很好的,我在我的插件BPL所引用的控件包中没有发现存在RegisterComponents这样的函数哦。我没有查全部,只是检查了一部分。只有RegisterComponents才会抛出类已经存在的异常吗?
 
RegisterComponents一般是设计时包的,安装的时候向系统注册。
Registerclasses是运行时注册的,你插件引用的是运行时包,应该是没有RegisterComponents的。你关键是要看Registerclass或者Registerclasses,报错十有八九就是这里产生的。
 
做了个测试工程,确实如fenian同志所说的那样,问题初步得以解决,还得找台没有装控件包的电脑测试一下,看看还会不会需要除了插件Bpl以外的Bpl支持。
呵呵,Registerclasses好像是不会报异常的,无论是否已经注册都不会报异常。
 
是的,bpl本身就是dll
同意研究需要加入的控件的源码,改写注册机制
 
经测试,依然要发布这么一堆包,怎么样做才能真正把他们编译到Exe中?
只是不包括在Build with runtime packages的选项里面就可以了吗?
cxLibraryVCLD7, dxThemeD7, cxEditorsVCLD7, cxDataD7, cxPageControlVCLD7, cxGridVCLD7, cxExtEditorsVCLD7, dxBarD7
dxComnD7, dxNavBarD7, dxGDIPlusD7, Rz30Ctls70
 
为什么要把包编译倒exe中?如果真要这样,干吹将所有需要用到的单元的地址加到Exe的搜索路径里编译得了
 
你不觉得只发布那些作为插件的BPL就可以了不是可以清爽很多吗?
发布程序的时候,还要带一堆第三方控件的BPL不是很爽吧。
现在的问题是,只要我把所有的第三方控件都编译进Exe的话,那么在加载哪些BPL的时候就会报类已经注册的错误。
 
后退
顶部