正 文

头脑风暴 “攒”出更稳定的软件


www.7dspace.com  更新日期:2006-3-20 19:14:36  七度空间


  六、VB 实现中的问题

  在程序员杂志2004年第10期《掌握汇编依然是技术高手的必经之路》的访谈中,在谈到汇编语言的发现bug的能力时,我曾经谈到以下的一段话:“曾经用VB编写一个程序,该程序通过创建对象与另一个程序通信,但是VB在将对象变量与原来的对象切断联系之前,不允许同一个对象变量重新创建对象,这种处理方式无所谓对错,但是我们的工作却要求如此,因此通过对VB 的msvbvm50.dll(msvbvm60.dll)的跟踪修改,使VB的工作机制符合我们的要求。”..

  这段话中所描述的问题就是实现这种结构时所遇到的。通过演示就可以发现,部件程序是由调度者创建的,而当调度者发现某个部件存在故障时,就会重新创建该部件,但是 VB5/VB6对于这种情况的处理均是无法重新创建部件,为此笔者对msvbvm50.dll/msvbvm60.dll进行跟踪修改了VB的这种处理机制,从而使自动恢复成为可能。必须说明的是,这种问题的出现是由VB的处理机制造成的,用其它环境实现未必会出现此问题。

  以下是我在1999年所写的关于修改VB5.0/6.0的DLL文件MSVBVM50.DLL/MSVBVM60.DLL的说明:

  1 为什么要修改该文件?

  VB的Set ObVar = nothing和Set ObVar = CreateObecjt(...)语句在很多情况下执行失败,并且会返回错误信息:自动化错误。经过对VB的分析发现,VB在将一个Object变量与一个新的对象建立连接之前必须与原来的对象切断联系,这样如果原来的对象因为某种原因不能工作(不响应--比如程序down),则这种语句就不能切断与原来对象的联系,从而也就不与新的对象建立联系,并返回“自动化错误”信息。VB的这种处理方法固然有其道理,但是在实际应用中,这种处理方法常常导致新对象无法创建,因此有必要修改其处理方式。

  2 修改方法

  我们知道,VB的核心文件为MSVBVMX0.DLL,其中提供了大量的函数,而与我们的问题的相关联的函数为MemSetEvent,该函数负责检查对象变量的有效性,并负责切断与原来对象的联系,其方法是:检查对象变量是否有原先发生联系的对象,如果有,则调用相应对象的清除过程。

  因此如果原来的对象已经down掉,则该过程无法实现,因此VB返回"自动化错误"信息。如果我们能够将让该函数永远认为不存在原来的对象,则该过程保证永远成功。

  3 修改过程(以VB5为例,VB6与此类似)

  在MSVBVM50.DLL中查找以下代码序列,并按照以下方法修改即可:

原始代码序列 修改为
56 push esi
8b 06 mov eax,[esi]
ff 50 04 call [eax+4]
8b 45 08 mov eax,[ebp+8]
8b 38 mov edi,[eax] 33 ff xor edi,edi
83 c0 04 add eax,4
89 45 f4 mov [ebp-0c],eax
85 ff test edi,edi
  
  保存文件即可。

  特别说明:在调试环境中,该功能是无效的,因为调试环境未使用msvbvm50.dll,而是建立了一个模拟环境!

  需要说明的是,在调试演示代码的时候,所使用的操作系统为Windows XP Professional,其msvbvm60.dll的日期为2003年1月24日。虽然没有对msvbvm60.dll进行修改,但是似乎可以进行恢复,是否是msvbvm60.dll修改了其原来的处理方式、Windows 2000的svbvm60.dll是否如此还需要验证。

  但是不论如何,对于早期的VB其问题存在,在此说明这种修改方法,如果读者在实验时遇到无法恢复的情况,可以参考进行修改。

  七、性能问题

  我们知道,进程通信会降低程序的性能。在最初设计该结构时,为了检验这种结构究竟会对系统的性能造成何种影响,曾经将一个近万行的VB程序拆分大约20 个程序进行试验。当时所采用的系统配置如下:CPU——奔腾200, 内存——64M,虽然没有采集对性能影响的具体数
据,但是经过验证系统性能是完全可以接受的。在当今,无论CPU、内存,还是硬盘的性能与当时的实验环境完全不可同日而语,因此这种结构对性能的影响几乎可以不需要考虑。当然读者如果有兴趣,可以对该结构性能的影响进行实验,如果有具体的数据结果,欢迎告诉笔者。在此先表示感谢。

  八、接口的设计、扩展

  实现调度者与部件之间的通信是该结构的基本要求,调度者与部件之间的接口方式有很多种,常见的就是属性、方法和事件、进程同步机制等。但是因为每种部件功能不一,需要设计许多不同的结构,这就给设计带来了麻烦。就好象在PC机中,各种不同的设备与系统有不同的接口,导致出现大量不同的接口,为设计带来困难。其实完全可以设计统一的接口,在PC中也出现这种趋势,比如USB的出现。请注意USB的全称为“Universal Serial Bus”,其中的Universal就是“通用的”,“一致的”的含义。在该结构中,通过实现统一的接口,既简化设计而又便以实现脚本化。但限于篇幅,在此不再赘述。

  虽然该结构一开始是为了解决触摸系统的对稳定性的要求而设计的,但是实际上这是一种通用的软件结构。一个企业可以开发大量的这种部件,然后以支持脚本的方式实现一个编辑环境,就可以随意生成各种程序。感兴趣的读者可以自行实现。

  九、关于演示程序的说明

  最后,简单对演示程序进行解释如下:

  1、执行register.exe,该程序完成两个部件、调度者的注册,因为它们是ActiveX 程序;

  2、执行monitor.exe。该程序启动调度者,然后调度者启动部件1、部件2,系统进入正常运行状态;

  3、按部件1上的Crash(腐败)按扭,会导致部件1关闭,观察会发生什么;

  4、按部件1上的“切换”按扭,切换到部件2的界面;

  5、按部件2上的Crash(腐败)按扭,会导致部件2关闭,观察会发生什么;

  6、按屏幕右上角的“Crash”按扭会导致调度者关闭,观察会发生什么;

  7、监控程序没有设置退出方式,因此要结束整个系统,必须用任务管理器之类的工具进行关闭,关闭次序如下:

  (1)杀掉monitor.exe进程

  (2)杀掉dispatcher.exe进程

  (3)杀掉comp1exe和comp2.exe进程

  请注意,必须按照此顺序进行,否则你会发现很难关闭整个系统,因为会不断地进行自动恢复。你也可以如此尝试以增加对该结构的认识。

2页,页码:[1] [2] 

上一篇:关闭Nero在刻录后弹出光盘功能
下一篇:自定义菜单栏 让你的Office彰显个性
头脑风暴 “攒”出更稳定的软件 作者:王振祥 来源:程序员杂志
收藏此页】【打印】【关闭
站 内 搜 索
 

热 点 导 读
特 别 推 荐