调用动态库时提示“尚未调用CoInitialize”?(180分)

  • 主题发起人 Lotus123
  • 开始时间
L

Lotus123

Unregistered / Unconfirmed
GUEST, unregistred user!
在动态库中通过ADOConnection控件访问SQL Server数据库,
在Libaray中创建DataModule时出现异常"尚未调用CoInitialize",
如果将ADOConnection换成DataBase控件则程序运行正常,为什么?SOS!

//*************代码如下*******************
library Demo;
uses
...;
{$R *.RES}
Begin
Try
DMDemo := TDMDemo.Create(Nil); //此处异常!!!
Except
On E:Exception Do
Begin
MessageBox(0, pChar('异常【' +E.Message + '】'), '提示信息', MB_ICONWARNING);
Exit;
End;
End;
End;


 
它提示你调用,那你就调用 CoInitialize。
动态库中通过ADOConnection控件访问SQL Server数据库,要进行初始化的。
Begin
Try
CoInitialize(Nil);
DMDemo := TDMDemo.Create(Nil); //此处异常!!!
Except
On E:Exception Do
Begin
MessageBox(0, pChar('异常【' +E.Message + '】'), '提示信息', MB_ICONWARNING);
Exit;
End;
End;
CoUninitialize;// 不要忘了这句。
End;

 
TO sunys:
试过了,编译时提示"Undecalred identirier :'CoInitialize' ",
需要引用那个单元?
另外,通过ADO访问SQL Server数据库时,需要哪些动态库?
谢谢!
 
需你在动态库里面加Initialize
 
To antic_ant: Initialize是给变量分配内存,好像无关吧?
 
sunys说得完全正确。需要引用ActiveX。
因为访问数据库需要使用Com控件,必需调用'CoInitialize' 初始化。
在编写一般的application时,Delphi会自动帮你加上,而在编写Dll时,
Delphi没有考虑到这种情况。
 
看看这个,可能对你有帮助

Delphi COM编程的一个BUG
由于工作需要,得在一个DELPHI写的普通DLL中来调用一个VC写的进程内COM组件来实现功
能。DLL很顺利就编写成功,但是在使用一个EXE程序来调试这个DLL时,DLL即总是报异常
错误。,由于DLL所调用的这个使用VC写的这个COM组件在EXE中调用调试完全通过,所以其
出错的可能性极小。我又非常的仔细检查了个用DELPHI写的DLL,也没有发现错误,却发现
这个异常使用try和except还是可以拦住的,也就是说肯定是DELPHI本向所产生的异常。
这就奇怪了,难道是DELPHI本身的问题造成的这种情况,我不敢肯定,所以只得从VCL源
码一级来对这个程序进行除错。

在DLL中是COM对象是通过调用DELPHI的RTL函数CreateComObject来建立的,于是我先从这
个函数入手开始调试。这个RTL函数很简单,只有一行代码:

OleCheck(CoCreateInstance(ClassID, nil, CLSCTX_INPROC_SERVER or

CLSCTX_LOCAL_SERVER, IUnknown, Result));

即使用Windows API函数CoCreateInstance函数来建立并返回COM组件的实例。这个API函数
外面套了一层OleCheck函数,Delphi RTL函数OleCheck的作用是如果CoCreateInstance没
有返回S_OK即COM组件建立成功,那么OleCheck将产生一个异常。我程序当中的异常会不会
是这OleCheck函数调用所报出来的呢,于是我试着将OleCheck去掉,让把
CoCreateInstance函数把其返回值显示出来。我试着运行修改过后的程序,呵呵
CoCreateInstnace函数所返回的值果然不对,是2147746288十六进制数是800401F0。在
MSDN中查得此值表示的含意是CoInitialize函数没有被调用。CoInitialize是COM组件的
初始化函数,是DELPHI封装COM时绝对应该负责调用的东西,难道这次的错误真是由于没有
调用CoInitialize函数所造成的,我半信半疑。试着将CoInitialize函数的调用加到了DLL
单元的initialization部分,将CoUninitialize函数加到了DLL单元的finalization部分。
再次使用外部EXE来调试这个DLL,果然不出错了。

错误是找到了,但是错误是怎样造成的呢。经过进一步的查找。发现错误出在Delphi的
ComObj单元initialization部分。此处有以下一段代码:

if not IsLibrary then

begin

SaveInitProc := InitProc;

InitProc := @InitComObj;

end;

这段代码判断当前程序是否是一个DLL(通过IsLibrary变量来判断)如果不是的话,则将
初始化的过程设为InitComObj函数。而DELPHI执行调用CoInitialize函数的操作正是在这
个InitComObj函数中调用的,难快会出错。最终究其原因可能是宝兰的开发人员只注意到
了ActiveX Library这类进程内COM框架的组件出始化的情况,而忘记了还可能有在普通DLL
中调用COM组件来实现功能的情况造成了上述的错误。至此问题全部解决,不过笔者还想多
说两句,就笔者认为对COM的支持是DELPHI做得比较差的地方之一,像这类错误在VC当中就
根本不会出现的,真的是很希望宝兰的开发人员能在DELPHI6中把DELPHI对COM的支持做得
更好,使DELPHI变得更加的完美。
 
TO All:
按照sunys, 远帆的思路,问题解决了,谢谢!
 
顶部