`
tibaloga
  • 浏览: 873332 次
文章分类
社区版块
存档分类
最新评论

DELPHI 6 Update 2# 的 Bug 及其解决方法

阅读更多
DELPHI 6 Update 2# 的 Bug 及其解决方法

Borland发布了对 Delphi 6 意义重大的第二个补丁,在SOAP/Web Service开发方面有了很大的增强,详见《DELPHI 6.02 抢先研究 -- BizSnap/SOAP/WebService 之四 -- 补丁2#的意义》。不过有一个方面我在那篇文章里没有说到,那就是用 SOAP 进行多层应用开发,当时我对这部分只是大致看了一下,没发现与补丁前相比有什么太多的不同,所以也没在意,直到不久前,一位叫 liaoqian 的网友给我发来 Mail 询问有关这方面的问题时,我才注意到 Delphi 6 Update 2# 在这部分有相当大的变化(当然不是表面上的),并且存在一个小 Bug 。

首先仿照《DELPHI 6 抢先研究 -- BizSnap/SOAP/WebService 之三 -- 用 SOAP 实现三层数据库应用》 中的例子做一个 WebService 三层数据应用。当出现上图所示的自动询问是否产生一个服务端接口的对话框时选择“No”,然后新建 SOAP Server Data Module ,其它操作与《之三》相同。完成之后在IE中输入:http://localhost:1024/Demo3.wadSoapDemo3/wsdl 将可以看到如下的接口列表,相比《之三》一文,可以看出增加了一个 IAppServerSOAP 接口,并且其 IWSDLPublish 接口的 Namespace URI 也有不同。

Port Type Namespace URI Documentation WSDL
IAppServer urn:Midas-IAppServer IAppServer
IAppServerSOAP http://www.borland.com/namespaces/Types IAppServerSOAP
ISoapDemo3DM urn:SvrDMSoap-ISoapDemo3DM ISoapDemo3DM
IWSDLPublish http://www.borland.com/namespaces/Types Lists all the PortTypes published by this Service IWSDLPublish

如果注意的话还可以发现一点问题,即:输入 http://localhost:1024/Demo3.wadSoapDemo3 不会看到 Delphi 6.02 写的一般 WebService 那样的一个页面,这有点不正常。
到编写客户端程序的时候,问题就出现了:在 ClientDataSet 的 ProviderName 属性中下拉,将不会看到任何可用的 ProviderName ,但一闪而逝的服务端窗体表明服务端是运行了的。通过察看 Web App Debugger 的记录信息可以看到如下的 SOAP 错误响应:

<?xml version="1.0" encoding='UTF-8'?>
<soap-env:envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" >
 <soap-env:body>
  <soap-env:fault>
   <faultcode>SOAP-ENV:Server</faultcode>
   <faultstring>
No invokable class registered that implements interface 
SOAPMidas.IAppServerSOAP of (soap action/path) 
"http://www.borland.com/namespaces/Types-IAppServerSOAP"
   </faultstring>
  </soap-env:fault>
 </soap-env:body>
</soap-env:envelope>

注意其中 faultstring 标记中的信息,它说明了错误的原因是“没有可调用的已注册的 IAppServerSOAP 接口实现类”。如果不理睬这个问题,直接把 DataSetProvider1 写到 ClientDataSet1 的 ProviderName 属性中,再将 ClientDataSet1 的 Active 属性设置为 true 将直接出现一个异常,其内容便是上面的 faultstring 的内容。
我非常喜欢包括 Delphi 在内的 Borland 的几乎所有产品,也非常信任 Borland ,这种感情来源于我七八年来使用过的数十个不同的 Borland 的产品及其不同版本,所以我不喜欢一些人在一碰到问题时就没理由地埋怨开发工具有 Bug 。虽然有很多传闻说 Borland 的产品 Bug 如何的多,其实有软件就有 Bug ,我也不是说 Borland 就一定没有 Bug , Borland 当然也有 Bug ,在本站就曾几次提到,难道 Microsoft 就没有 Bug 吗?
但这一次,我几乎可以肯定是 Delphi 6 Update 2 所带来的 Bug ,因为在打补丁2#之前,我也是完全按照上面的做法一步步做的,没有任何问题,打了补丁2#就出现了这样的问题。即便如此,我还是要找到具体的证据来证明这是一个 Bug 并要找到解决的办法,所以我读了 Delphi 6.02 的部分 SOAP 相关源代码,并进行了调试。

附:《设置源码察看和调试》
SOAP 部分源码察看设置:在 Delphi 6 中选择 Tools|Environment Options 选中 Library 页,在 Browsing path 中加入路径:$(DELPHI)/source/Soap ,然后就可以在程序中通过 Ctrl+MouseLeftButton 快速跳到相应的 SOAP 源码文件中了。
源码调试设置:在 Delph 6 中选择 Project|Options 选中 Compiler 页,将其中 Debugging 框中的 Use Debug DCUs 一项选取后,重新编译程序,即可调试进入 VCL 的源码中了。

通过跟踪调试发现异常发生在 SOAPHTTPPasInv 单元中的 Procedure THTTPSoapPascalInvoker.DispatchSOAP 中:

      ...
      if IntfInfo = nil then
        raise Exception.CreateFmt(SInvInterfaceNotReg, [SoapAction])
      else if InvClassType = nil then
        RaiseNoIntfException(SoapAction)
      ...

因为其中 InvClassType 为 Nil ,所以导致了那个异常。这提供的信息和前面的出错信息其实是一样的:即 IAppServerSOAP 接口的实现类不存在或未注册。所以我又找到了 IAppServerSOAP 接口的定义,在 SOAPMidas 单元中:

  IAppServerSOAP = interface(IInvokable)
    ['{C99F4735-D6D2-495C-8CA2-E53E5A439E61}']
    function  SAS_ApplyUpdates(...): OleVariant; stdcall;
    function  SAS_GetRecords(...): OleVariant; stdcall;
    function  SAS_DataRequest(...): OleVariant; stdcall;
    function  SAS_GetProviderNames: TWideStringDynArray; stdcall;
    function  SAS_GetParams(...): OleVariant; stdcall;
    function  SAS_RowRequest(...): OleVariant; stdcall;
    procedure SAS_Execute(...); stdcall;
  end;

熟悉 MIDAS 技术的人看了这段代码,立即可以发现它与 IAppServer 接口极其相似,只是在 IAppServer 中,那些方法都是以 AS_ 开头,而这里是以 SAS_ 开头。那么为什么既然已经有了一个 IAppServer 接口了, Borland 还要在 Update 2 加入这么一个 IAppServerSOAP 接口呢?在打补丁2之前,我也看过 SOAP 的部分代码,那时的 SOAP Server Data Module 是从 IAppServer 派生的,虽然 IAppServer 并不是从 IInvokable 派生的(按 Delphi 6 的要求,所有 SOAP 接口都要从 IInvokable 接口派生),但其实 IInvokable 是直接从 IInterface 派生的,与 IInterface 完全相同,而 IInterface 其实就是所有 COM 接口的祖先接口--IUnknown,而 IAppServer 是从 IDispatch 接口(是 COM 的一个主要接口,用于 Automation ,其祖先当然也是 IUnknown)派生出来的,所以直接用 IAppServer 也并无不可。
在 IAppServerSOAP 接口定义前面有一段注释,大意就是说: IAppServerSOAP 用 StdCall 类型的方法调用替代了 IAppServer 中的 SafeCall 类型的方法调用,为的是在不支持 SafeCall 的环境中也可以实现 IAppServer 的功能。这就是 IAppServerSOAP 出现的原因。
了解了这些就好多了。所有的 SOAP Server Data Module 都是从 TSoapDataModule 派生的,它定义在 SOAPDm 单元中,其中有如下代码:

    { IAppServerSOAP }
    function  SAS_ApplyUpdates(...): OleVariant; virtual; stdcall;
    function  SAS_GetRecords(...): OleVariant; virtual; stdcall;
    function  SAS_DataRequest(...): OleVariant; virtual; stdcall;
    function  SAS_GetProviderNames: TWideStringDynArray; virtual; stdcall;
    function  SAS_GetParams(...): OleVariant; virtual; stdcall;
    function  SAS_RowRequest(...): OleVariant; virtual; stdcall;
    procedure SAS_Execute(...); virtual; stdcall;

这里就是 IAppServerSOAP 接口的实现,由于所有的 SOAP Server Data Module 都是从 TSoapDataModule 派生的,所以 IAppServerSOAP 接口的实现类一定是已经实现的,但有没有注册呢?在我们的 SOAP Server Data Module 单元--SvrDMSoap 中有如下代码:

procedure TSoapDemo3DMCreateInstance(out obj: TObject);
begin
 obj := TSoapDemo3DM.Create(nil);
end;

initialization
   InvRegistry.RegisterInvokableClass(TSoapDemo3DM, TSoapDemo3DMCreateInstance);

显然它也已经注册了,但为什么会出错呢?看看 ISoapDemo3DM 接口的 WSDL 吧……怎么只有 AS_XXX ?没有 SAS_XXX ?原来如此,服务端只导出了 IAppServer 接口,并没有导出 IAppServerSOAP 接口。这就是问题所在!
再来看看 SvrDMSoap 单元:

  ISoapDemo3DM = interface(IAppServer)
    ['{4F618288-9F81-4090-81EF-4ACE0BF6D0BE}']
  end;

  TSoapDemo3DM = class(TSoapDataModule, ISoapDemo3DM, IAppServer)

原来如此,原来 ISoapDemo3DM 居然还是从 IAppServer 接口派生的,显然这是 SOAP Server Data Module Wizard 的一个 Bug ,它还是按 IAppServer 接口的方法来生成 SOAP Server Data Module 的。知道问题的所在就好办了,将上面的代码中的两个 IAppServer 都改为 IAppServerSOAP ,然后重新编译。再来看看客户端程序,一切正常了, ISoapDemo3DM 的 WSDL 也正确地导出了 SAS_XXX ,特别是 hhttp://localhost:1024/Demo3.wadSoapDemo3 也可以看到标准的 Delphi 6.02 的 WebService 页面了。
至此,这个 Bug 已经完全解决。另外,要补充说明的是:在 C++ Builder 6 中不存在这个问题。

[Mental Studio]猛禽 Apr.23-02

分享到:
评论

相关推荐

    内存遍历 环境:xpsp2 + delphi 2007 update 4

    //环境:xpsp2 + delphi 2007 update 4 // //由于前段日子载了笑苍天的超级遍历,感觉的确挺好用的, // //但是就在过滤浮点型的时候有时会发生错误,苦于手上没代码无法更改, // //干脆就自己写一个,由于时间仓促...

    delphi7 update1

    一般Delphi7安装程序不集成...安装Update1的D7IDE可以有效解决部分内存管理问题,优化编译速度,解决一些自带控件Bug等问题,同时使用cnWizards(D7很牛B且实用的软件开发辅助工具)也需安装此Update,否则常出现一些错误.

    delphi2005 IDE UPDATE FIX BUG 2005-9-24

    DELPHI2005 内部更新IDE的bug , 2005-9月内部发布

    Delphi7.1 Update

    Delphi 7.1 Update Release Notes=======================================================This file contains important supplemental and late-breakinginformation that may not appear in the main ...

    delphi7.1.update package

    将您使用的dephi7.0,提升到7.1,纠正了7.0中的个别bug

    The Delphi CHM ToolKit

    Delphi HH KitThe Delphi HH Kit is a free download for Delphi 2/3/4/5/6/7/etc. It consists of 2 units & doc file. The first unit is a port of C++ header file ...

    delphi2-delphi2010 全支持 dcu 装换 pas

    delphi2-delphi2010 全支持 dcu 装换 pas -------------------------------------------------------------------------------- Project Dcu2Pas Version 1.3 Purpose Decompile a D2-D7, K1-K3's dcu(dpu) file ...

    ICS delphixe10源码版

    ICS - Internet Component Suite - V8 - Delphi 7 to RAD Studio 10 Seattle ======================================================================= (Aka FPIETTE's Components) Revised: March 3, 2016 ...

    DELPHI7托盘图标控件,230(好用).zip

    DELPHI7下好用的托盘控件,安装简单,版本进度如下:TCoolTrayIcon, ver. 2.3.0 - ver. 2.3.0: Various minor bugs fixed: 1) Calling the ShowMainForm and HideMainForm methods before the main form was ...

    Delphi2010皮肤控件AlphaControls6.21FS

    * Solved problem with opening of PNG ImageList editor in Delphi5/6 and C++ Builder6 * Solved problem of Ico32 using * Solved problem in MDI child maximizing 20.10.2008 AlphaControls 2009 (v6.00) ...

    FastReport.v4.15 for.Delphi.BCB.Full.Source企业版含ClientServer中文修正版支持D4-XE5

    FastReport.v4.15 for.Delphi.BCB.Full.Source企业版含ClientServer中文修正版支持Delphi 4-XE5 and C++Builder 6-XE5. D2010以上版本(D14_D19)安装必读 delphi2010以上版本(D14_D19)使用者安装时,请将res\frccD14_...

    谷歌地图 delphi 封装库 2013 0.1.9 全面支持google maps api

    Supported Delphi version: Delphi 6, 7, 2007, 2010, XE2, XE3 Tested Windows Versions: XP, 2003, Vista, 7 Change History january 14, 2013 - Google Maps Library v0.1.9 - Improvement: Compatible with ...

    DCPcrypt(v3b3 UNICODE修正)+2个Demo

    I haven't been able to update it for quite a long time now but it still works quite happily with Delphi 4, 5, 6, 7 and 2005 and Kylix 1 and 2 (it might work under Kylix 3, but I don't have a copy to ...

    delphi线程池单元文件uThreadPool.pas

    delphi线程池单元文件uThreadPool.pas,用法如下 type TRecvCommDataWorkItem=class(TWorkItem) public // updatetime,addtime:TDateTime; // orderid,ordertype,urljson,loadcount,savepath:string; url,...

    MyDAC7.6.11

    MyDAC是一个很好的访问MySQL的Delphi控件组,性能非常好。 2012年12月份发布的版本源码,版本历史如下: 7.6.11 12-Dec-12 Rad Studio XE3 Update 1 is now required C++Builder 64-bit for Windows is supported...

    delphi 2007 第三方补丁

    2. Select the IDE registry keys for which you want to install the bugfix 3. Press the "Install" button Uninstallation: =============== 1. Start IDEFixPackReg.exe under your user account 2. Press the...

    DevArt.UniDAC.v.3.00.0.10 for Delphi7/Delphi2010

    * Added overloaded declaration of the ApplyUpdates method to choose update kind * Fixed bug with quote that first character inside quoted string for the Filter property * Fixed bug in TCRBatchMove ...

    Sdac 2.45.2.26 08.06.04 D7

    For Delphi 7.0 需要 Update 12.45.2.26 08.06.04------------------- Fixed bug with using TrimFixedChar in dll;- Fixed StackOverflow bug with opening empty ctStatic cursors;- Fixed bug with Refresh ...

    Devart_UniDAC_6.3.13_for_XE8

    Bug with generating INSERT or UPDATE queries when UpdatingTable is specified is fixed SQLServer data provider Data type mapping from Varbinary type to Blob field is added Bug with data type mapping ...

    Devart_UniDAC_6.3.13_for_DX10.1

    Bug with generating INSERT or UPDATE queries when UpdatingTable is specified is fixed SQLServer data provider Data type mapping from Varbinary type to Blob field is added Bug with data type mapping ...

Global site tag (gtag.js) - Google Analytics