Cal*_*tor 5 com excel vba visual-foxpro
如何强制Excel(2007)VBA发布对COM服务器对象的引用?
我在Visual Foxpro 9 SP2中编写了一个inprocess(单实例DLL)COM服务器,它是从我的开发机器上的Excel 2007 VBA代码实例化的.Excel似乎持有对COM对象/ dll的引用,即使我设置它= Nothing.这阻止我重建DLL由于"文件访问被拒绝TestCOM.dll"消息,直到我退出Excel这是每次我想要进行更改并测试它时很痛苦.
我已将代码简化为一个非常简单的测试设置:VFP9项目(TestCOM)只有一个.prg文件,其中包含以下内容
DEFINE CLASS TestClass As Session OLEPUBLIC
ENDDEFINE
Run Code Online (Sandbox Code Playgroud)
VBA代码如下:
Sub Test()
Set objTest = CreateObject("TestCOM.TestClass")
Set objTest = Nothing
End Sub
Run Code Online (Sandbox Code Playgroud)
我已经尝试删除VBA项目中对COM服务器库的引用,但这没有任何区别.我已尝试使用和不使用DIMing对象变量,它没有任何区别.我试过创建一个新的VFP DLL项目,但问题仍然存在.
如果我将VFP应用程序/ DLL作为INPROCESS/DLL构建并运行VBA代码我遇到了这个问题但是如果我将它构建为OUTOFPROCESS/EXE并运行VBA代码我就不会遇到这个问题.
我在COM对象清理中发现了一个非常类似的问题,除了我的COM服务器是用Visual Foxpro 9 SP2编写的,而这与C#有关,OP没有详细解释他们是如何解决这个问题所以我不知道如何解决它; 如果这是可能的.
用于从DLL中的代码实例化COM类的过程是Excel调用COM库层以使用ProgID或ClassID查找实现.当你有一个inproc服务器时,这意味着它找到了你的DLL的路径,并使用LoadLibrary将它加载到你的客户端进程,然后创建类工厂并调用DLL中的方法.因此最终结果是Excel在您的DLL上调用LoadLibrary并锁定该文件,直到Excel在句柄上调用FreeLibrary.
使用COM接口,您无法控制它.您调用CoCreateInstance()(或者从VBA创建对象,使用New或CreateObject调用此Win32 API).这个的实现处理LoadLibrary和其他所有内容,直到你得到一个可以使用的接口指针.某些应用程序会定期调用CoFreeUnusedLibraries()来尝试释放当前未使用的已加载的COM dll.默认的类工厂实现维护一个创建的对象的计数器,可用于确定DLL是否正在使用 - 但这并不总是可靠的,因为COM类编写器可能不遵守规则.退出Excel显然会释放文件锁定.
当您将COM类创建为进程外服务器时 - 它位于单独的可执行文件或DLL中,其生命周期管理方式不同.Excel不再对DLL进行锁定,并且释放COM实例可能会允许托管进程退出.
您可以通过安排让DllHost托管它来将DLL转换为本地服务器(进程外).如果您使用OleView实用程序并找到您的类ProgId,那么您可以在代理进程(dllhost)中启用托管.我做了一段时间已经有一段时间了,但网上应该有关于使用代理托管的信息.显然,在进程外托管COM对象会使一切变慢,并引入各种编组问题的可能性.如果你保持oleautomation兼容接口,它应该没问题.