当没有对象引用时,COM是否会自动卸载DLL?

4
例如,在X语言中:
let x = CreateOject( "MyProgID" )
x.LateBoundCall()
x.Release()  // (or setting x to Nothing in VB-like language, etc)

MyProgID所在的DLL会发生什么?COM是否会自动卸载DLLs?

编辑

假设上述代码位于不公开任何COM的可执行文件中。

2个回答

10

是的,但不是以确定性的方式。 Windows定期询问每个已加载的DLL“现在卸载你是否安全?” 任何回答“是”的DLL都会被卸载。

注意MSDN的备注

如果通过调用CoGetClassObject加载的DLL未能导出DllCanUnloadNow,则该DLL将一直保持加载状态,直到应用程序调用CoUninitialize函数来释放OLE库。

请参阅此Old New Thing文章。


1
DLLs不会调用CoUninitialize - wqw
@wqw:错误。根据MSDN的说法:“为了在线程上优雅地关闭COM库,每个成功调用CoInitialize或CoInitializeEx(包括任何返回S_FALSE的调用)都必须通过相应的调用CoUninitialize来平衡。” http://msdn.microsoft.com/en-us/library/ms695279(VS.85).aspx - John Dibling
COM库 = 支持COM运行时的Win32 API库,与COM DLL不同。 --- COM服务器DLL通常不会在它们自己创建和管理的线程上调用CoInitialize(也不会调用CoUninitialize)。此外,“DllCanUnloadNow”的典型实现只取决于现有实例的数量。 - peterchen
@peterchen:是的,COM服务器DLL确实会调用CoInitialize()。至少应该这样做。如果使用COM的应用程序不使用COM本身,并且在加载DLL的同一线程中没有其他代码使用COM,则COM将不会被初始化。 - John Dibling
约翰,我不认为典型情况是“卖弄学问的”。COM服务器DLL通常通过CoCreateInstance --> CoGetClassObject --> ...加载,这需要先初始化COM库。如果DLL只消耗而不公开COM对象,则它不是COM服务器DLL(好吧,最后一个*接近吹毛求疵)。 - peterchen
@Peter:抱歉,我的上下文切换器出了问题,我一直在以消费者的角度思考,而不是提供者的角度来编写。你(和wqw)是对的,提供者通常不需要CoUninit()。我会更新我的回答。 - John Dibling

2

您需要手动释放COM对象使用的资源。它们在内部使用引用计数器来保持对组件的引用数量。如果组件仍然具有引用计数器>0,则dll将无法卸载,资源也将无法释放。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接