我最近在用IntraWeb开发一个项目,开始是使用 EXE 方式开发调试,由于使用ADO连接 MS SQL-Server,因此参考了网上普遍认为的解决方案将 ServerController 的 ComInitialization 属性设置为 ciMultiThreaded。今天我将部分完成的程序转化为 Dll 方式,打算放在IIS中看看效果,也是参照了网上的方案,将工程文件修改为DLL 模式(由于6.0.22的结构与5.X的结构不同,我手头的资料都是介绍的5.X的转换方法),编译通过后,放在我的本机IIS的虚拟目录中(已设置允许使用ISAPI)。在IE中输入地址后,满心期待着出现已经看过很多次的界面,结果,没有,出现错误提示“服务器内部错误”。我靠,这是怎么回事,是不是我转换的问题啊,仔细查看了半天,眼珠子都快瞪到显示器里了,最后的结论是:没有任何问题。虽然认为没有道理,但我还是重新新建了一个ISAPI工程,然后将原工程中的单元全部加进来,编译后放入IIS,打开IE,输入地址,故障依旧,我靠!!!我开始怀疑可能是数据库连接的问题,开始以为是无法连接数据库,于是新建了一个新程序,做了一个简单的数据显示小程序,结果数据显示正常。我靠,数据库连接没问题啊。仔细想~~~,突然闪过一丝念头,刚才这个测试程序我好像没设置 ComInitialization 啊,怎么可以连的,立刻,改成 ciMultiThreaded 再试,哈,故障重现了,因为 ComInitialization 默认是 ciNone,这在 EXE 模式下是无法使用 ADO 的,在 DLL 模式下居然可以,又改成 ciNormal 再试,居然也没有问题。连忙把我的项目中的 ComInitialization 设置为 ciNormal,重新编译放入IIS,打开IE,输入地址,哈哈,我可爱的界面终于出来了~~~ :)至此,得出结论:
  1、EXE 模式下使用 ADO,ServerController 的 ComInitialization 属性应设置为 ciMultiThreaded 或 ciNormal。  2、DLL 模式下使用 ADO,ServerController 的 ComInitialization 属性应设置为 ciNormal 或 ciNone。  3、综合以上两点,ServerController 的 ComInitialization 属性建议设置为 ciNormal,两全其美,呵呵:)但是,对于 ComInitialization 属性的这三个值我并没有很透彻的理解,他们究竟是什么含义,有什么区别,在 EXE 和 DLL 两种模式下为什么会出现上述的现象,不知有没有高人来解释一下呢!我使用的开发环境为:Delphi 7 + IntraWeb 6.0.22 + Windows 2003 Server + IIS 6.0

解决方案 »

  1.   

    这是使用COM的常识问题(ADO也是COM)  :)
      

  2.   

    同使用EXE或者DLL根本无关:)
    只是线程中使用COM的问题,关于几种线程模式的区别,你可以在网上找到具体细致的文档.建议你先不要去改缺省的线程模式.
    而是使用该用的
    CoInitialize(nil);//或者 CoInitializeEx(...);
    ...(这儿你调用COM的代码)
    CoUnInitialize;
      

  3.   

    楼主,谢谢你,我也碰到同样的问题,我的提示是interface not supported,我的属性在
    exe状态下设的就是ciMultiThreaded,后转为dll老提示interface not supported,我试试
    ,我用的版本是intraweb7.0.9
      

  4.   

    halfdream(哈欠) 老哥,我当然知道ADO也是COM,所以才要设置 ComInitialization 属性啊。但现在问题是使用IntraWeb,所有的这些初始化都是被封装的,我就是不太理解这个属性的设置的确是和 EXE/DLL 模式有关,为什么会这样,才是我关心的。
      

  5.   

    尽管你在EXE和DLL观察到的情况不同,得出上面的结论,
    但事实上跟是不是EXE和DLL没什么关系.确切说,区别在主线程与非主线程..
    你使用EXE测试的时候,调用ADO的线程是用的主线程.
    你使用DLL的时候,DLL里面调用ADO的线程是非主线程.你可以做这两个测试验证.
    1,做一个EXE型的COM组件(自动化对象,或者远程数据模块)都行..在远程方法里面
      调用ADO.
    2,做一个DLL,实现一个调用ADO的组件, EXE程序主线程里面调用它..
      

  6.   

    我想我有点明白了,不过我有点表达不出来,应该是DLL本身就是处于一个线程中的,主线程应该是IIS,所以好像在DLL这个线程中就不能再初始化为多线程模式来调用ADO,因此 ciMultiThreaded 就会出错,而设为 ciNone,因为本来DLL就已经是在线程中了,所以也已经初始化过COM了,因此和 ciNormal 一样都可以正确调用 Com。而EXE因为本身就是主线程,所以 ciMultiThreaded 和 ciNormal 都可以使用线程调用 ADO,而 ciNone 因为主线程不会初始化COM,所以就无法调用ADO了。我这样理解对不对啊。
      

  7.   

    这样理解应该差不多了:)
    不过我这儿没有装D7,它一些具体实现的东西现在没分析.不过有几点可以补充一下,
    在IIS在处理请求的时候,你可以在进程观察器里面看看它有几个线程产生.
    IIS调用你的DLL时候,不是直接调用,而通过DLLHOST.EXE调用(这样可以做到调到者与
    你的DLL不在一个进程,你的DLL崩溃不会造成IIS进程崩溃)
      

  8.   

    多谢halfdream(哈欠)!!! :)