2014-01-30 54 views
1

http://code.msdn.microsoft.com/office/CppAutomateOutlook-55251528狀態:辦公自動化#import有害嗎?

[...]這是非常強大,但通常不建議使用,因爲 與 Microsoft Office應用程序一起使用時,經常會出現引用計數問題。 [...]

其中引用計數問題專門在這裏是什麼意思? 例如,它是否適用於特定示例?

同樣作爲例子,我只是想打開Outlook,創建約會,完成。

我想使用#import但這種聲明讓我感到害怕吧......

回答

1

一個circular reference當你拿着引用對方,直接或間接地兩個或多個對象發生。在COM中,這意味着循環鏈接的對象相互調用IUnknown::AddRef

如果使用Excel自動化,如果你的事件處理程序(匯)連接到該的Excell可能發生對象的採購活動(通過IConnectionPoint::Advise)。這樣,您可能會保留對象,例如Application對象,而Application對象會保留對接收器的引用。

此問題不是專用於由VC++ #import指令生成的智能指針。這是關於如何在不再需要COM對象時關閉COM對象。您應該明確地斷開您所做的所有連接(即,執行IConnectionPoint::Unadvise),並調用該對象可能公開的任何顯式關閉API(例如,Workbook::CloseApplication::Quit)。那麼你應該明確地釋放你的參考(例如,在智能指針上調用workbookPtr.Release())。

這就是說,如果你不處理用Excel採購任何COM事件,你不應該擔心太多,你可以創建一個循環引用的機率會很低。此外,Excel是一個進程外COM服務器,COM有一些garbage collection logic來管理進程外服務器的生命週期。但是,在應用程序仍處於打開狀態時,Excel進程將保持活動狀態,直到所有對其對象的引用都已釋放,或調用了Application::Quit

+1

太好了,謝謝!我瞭解循環引用,但我不知道這是此陳述的原因。所以我可以放心地使用#import。 – divB

+1

@divB,除非你處理事件,否則執行「正常水平的預防措施」。否則,執行「高級別的預防措施」,並在完成特定的Excel對象時顯式釋放任何智能指針。 **如果您的應用程序終止,但Excel.exe仍然掛在進程列表中的時間超過幾秒鐘,那將是一個不好的跡象。** – Noseratio

1

這很無意義。藉助#import編程Office進行互操作是樣板和推薦的方式。它自動生成的智能指針類型明確用於爲您自動完成引用計數,因此您不能忘記調用Release()。有一些尖銳的邊緣,你必須明白什麼是智能指針可以做和不做。

這是課程這是所有功能於一體代碼框架背後的團隊,否則相提並論。這些樣本是由上海的一個支持團隊創建的,最初被僱用來幫助MSDN論壇。這些人沒有你在Redmond工作的微軟程序員期望的那種憑證,他們的摘錄也沒有被審查。其中有些人是完全不適當的。如果您曾在MSDN論壇上提過問題,並看到他們發佈的答案,那麼您就明白我的意思了。

他們的Solution2.cpp示例通過IDispatch使用後期綁定。這絕對是與Office互操作的難題,當您編寫代碼時,您無論如何都得不到任何幫助。編寫方法調用時,智能感知不能提供任何有用的信息,編譯器也不能告訴您錯過了一個參數或錯誤的參數類型。您的程序在運行時會因爲不透明的錯誤代碼而失敗,如DISP_E_BADVARTYPE或DISP_E_BADPARAMCOUNT。 Release()調用必須明確地進行,當然這會使更容易錯過。您使用智能指針時沒有的問題,他們會給您自動完成和類型檢查。您可以親自看到Solution1.cpp具有多小和可讀性。

診斷到Release()的未接來電很容易,您的程序完成但您仍然會看到Outlook.exe在任務管理器中運行。無論如何你會習慣於檢查,當你調試你的程序,發現錯誤並停止程序來修正時,它也會發生。當然這也阻止了Release()被調用,所以Outlook將繼續運行。你必須自己殺死它。

不要考慮用像C#或VB.NET這樣的託管語言編寫這種代碼。如果您遇到問題,您將獲得lot更多幫助,並且您會發現很多示例代碼。垃圾收集器從不忘記發佈呼叫。這樣做有點慢。