2011-09-07 31 views
5

如何強制Excel(2007)VBA釋放對COM服務器對象的引用?如何從Excel VBA中釋放進程內COM服務器對象

我已經在我的開發機器上從Excel 2007 VBA代碼實例化了Visual Foxpro 9 SP2中編寫了一個inprocess(單實例DLL)COM服務器。即使我將它設置爲= Nothing,Excel似乎仍持有對COM對象/ dll的引用。這可以防止我由於「文件訪問被拒絕TestCOM.dll」消息而重建DLL,直到我退出Excel,每次我想進行更改和測試時都很痛苦。

我煮完代碼到一個非常簡單的測試設置: 的VFP9項目(TestCOM)具有下列內容

DEFINE CLASS TestClass As Session OLEPUBLIC 

ENDDEFINE 

VBA代碼如下所示只是一個.prg文件:

Sub Test() 

    Set objTest = CreateObject("TestCOM.TestClass") 
    Set objTest = Nothing 

End Sub 

我已經嘗試刪除在VBA項目中的COM服務器庫的引用,但這並沒有任何區別。 我已經試過,沒有DIMing對象變量,它沒有區別。 我曾嘗試創建一個新的VFP DLL項目,但問題依然存在。

如果我將VFP application/dll構建爲INPROCESS/DLL並運行VBA代碼,則會出現此問題,但如果將其構建爲OUTOFPROCESS/EXE並運行VBA代碼,則不會出現此問題。

我在COM Object Cleanup中發現了一個非常類似的問題,只是我的COM服務器是用Visual Foxpro 9 SP2編寫的,而這涉及到C#,OP沒有詳細解釋他們如何解決問題,所以我不知道如何繞過它;如果這甚至是可能的。

+0

對於任何人閱讀此線程我後來意識到,如果該項目建成爲一個進程外(EXE)COM服務器,那麼你只能重建項目如果您沒有在VBA/Excel中引用類型庫,則不退出Excel。 – Caltor

回答

6

用於從DLL中的代碼實例化COM類的過程是,Excel使用ProgID或ClassID調用COM庫層來查找您的實現。當你有一個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實例可能允許主機進程退出。

您可以將DLL作爲本地服務器(out-of-process)使用,讓它由DllHost託管。如果您使用OleView實用程序並找到您的類ProgId,那麼您可以在代理過程(dllhost)中啓用託管。自從我這樣做以來已經有一段時間了,但網絡上應該有關於使用代理託管的信息。很顯然,將進程外的COM對象託管會使得所有事情變得更慢,並引發各種編組問題的可能性。如果你保持oleautomation兼容接口,它應該沒問題。

+0

感謝您提供優秀的詳細技術回覆。所以簡而言之,你基本上是說用COM接口,我受到客戶端的支配,在這種情況下是Excel,並且我無法強制釋放DLL?我應該在我的問題中提到,當從另一個VFP副本調用COM服務器時,不會發生此問題,因此該故障似乎與客戶端而不是服務器有關。我認爲作爲一種解決方法,我將在開發過程中將此項目構建爲Out of Process服務器(EXE),然後將其切換爲In Process(DLL)以進行最終測試和發佈。 – Caltor

+2

需要一種額外的成分。 COM服務器必須從它的DllCanUnloadNow()入口點返回S_OK。在VBA + Foxpro環境中測試並不簡單。 –

1

添加一個較短的答案....

鬆開DLL是棘手的問題,並在過程中的一個熟悉的開發商COM組件用於Excel

有跡象表明,需要滿足

1)不要使用早期綁定庫引用(工具 - >參考)兩個條件,使用後期綁定來代替。早期的綁定工具參考將鎖定一個鎖。

2)致電CoFreeUnusedLibraries卸載COM不再有客戶端的服務器。

從你的示例代碼你已經晚了綁定,但請檢查您的參考。雖然點2)在payyhoyts answer中被提及,但沒有給出代碼。

這裏有一個副本和pasteable聲明

Private Declare Sub CoFreeUnusedLibraries Lib "ole32.dll"()