Search code examples
visual-c++comimportoffice-automation

Office Automation with #import harmful?


http://code.msdn.microsoft.com/office/CppAutomateOutlook-55251528 states:

[...] It is very powerful, but often not recommended because of reference-counting problems that typically occur when used with the Microsoft Office applications. [...]

Which reference-counting problems are specifically meant here? For example, does it apply to the particular example?

Similarly as in the example, I just want to open Outlook, create an appointment, done.

I wanted to use #import but this statements makes me feel afraid about it ...


Solution

  • A circular reference happens when you have two or more objects holding references to each other, directly or indirectly. In COM, it means that circularly linked objects have called IUnknown::AddRef on each other.

    In case with Excel automation, that could happen if you connect your event handler (sink) to Excell objects sourcing events (via IConnectionPoint::Advise). This way, you may be keeping a reference to e.g., Application object, while Application object keeps a reference to your sink.

    This problem is not specific to smart pointers generated by VC++ #import directive. It's about how you handle the shutdown of the COM objects when you no longer need them. You should explicitly break all connections you've made (i.e., do IConnectionPoint::Unadvise), and call any explicit shutdown API the object may expose (e.g., Workbook::Close or Application::Quit). Then you should explicitly release you reference (e.g, call workbookPtr.Release() on a smart pointer).

    That said, if you don't handle any COM events sourced by Excel, you shouldn't be worrying much, the chance you might create a circular reference would be low. Besides, Excel is an out-of-process COM server, and COM has some garbage collection logic in place to manage life-time of out-of-process servers. However, while your application is still open, the Excel process will be kept alive until all references to its object have been released, or Application::Quit has been called.