Archive for the ‘Interop’ Category

Hosting Office in a WPF Application

Friday, August 24th, 2007

note 

Updated on December 17, 2009

The approach described in this article for hosting office documents in WPF is no longer supported.  Microsoft has recently pulled the DSO Framer control from its knowledge base.  🙁

Please contact Microsoft Developer Support directly if you have questions regarding this decision.

 If a new supported solution for hosting Microsoft Office applications within WPF becomes available, I will try to post a sample.

Cheers,
Dr. WPF


Dear Dr. WPF,

Is it possible to host Microsoft Excel inside of a WPF application? Do you have any sample code?

Sincerely,
Rob
 


Hi Rob,

It’s certainly possible to host a Microsoft Office application inside of a WPF application. And just to prove it, I’m writing this entire post inside of Microsoft Word while it’s being hosted inside my WPF application.

WPF Hosting WordFeel free to download the code for this sample. This sample will work for hosting Word, Excel, PowerPoint, or Visio documents. It should host Project documents also, but I don’t have Project, so I couldn’t verify this. And I should note that hosting Visio 2007 documents proved to be very flaky. The Visio host crashed more often than not. The other hosts seemed pretty stable.

You will need to install the DSO Framer control prior to running the sample. More on that below…

So yes, it’s possible to host an Office application, but that doesn’t necessarily mean it’s easy! There are definitely a lot of caveats, disclaimers, qualifiers, stipulations, and limitations (yep, even the thesaurus works in the hosted scenario!) when hosting any Win32-based window (a.k.a., an HWND) within a WPF app. Most of these are documented in the SDK in topics like WPF Interoperation: ”Airspace” and Window Regions Overview and Hosting a Microsoft Win32 Window in WPF. In the latter article, special attention should be given to the sections entitled “Notable differences in output behavior” and “Notable differences in input behavior”.

Hosted Office applications come with a whole set of their own challenges (keeping the document focused, keeping application menus in sync with document menus, etc). If you go down the path of hosting an Office app, you should expect some technical challenges and a potential steep learning curve, especially if you’re considering office automation.

There are code samples in the SDK that demonstrate how to host an ActiveX control inside your WPF application. So if you can find a simple ActiveX wrapper for your Office application, then you’re all set, right?

Well, unfortunately it’s not that easy when it comes to hosting Office. An Office application, like Excel, has much larger requirements for its host container. The host must be an Active Document Container. This container implements a number of COM interfaces above and beyond those found in a simple ActiveX host.

There are a couple of Active Document Containers readily available on most Windows machines: 

1. Internet Explorer

2. the Windows Forms WebBrowser control

The simplest approach to hosting an Office application inside a managed application involves hosting the Windows Forms WebBrowser control and pointing it at an Office document. If all you care about is simple hosting, this approach might work for you.

SIDEBAR: For the record, I should point out that there is also an unmanaged WebBrowser control (shdocvw.dll) that ships as part of Internet Explorer. This control can be hosted in an unmanaged app (or even in a managed app using the instructions in this article, but why would you do that when there’s already a managed control?). Indeed, the Windows Forms WebBrowser control is just a managed wrapper around the Internet Explorer WebBrowser control. As such, Internet Explorer must be installed for any solution that involves either WebBrowser control.

Usually, however, if you are hosting something like Excel, you need to automate the document (to load, save, or print it, invoke automation commands, etc). The WebBrowser control does not give you much access to the document-related automation classes. (For information on the Office automation classes, check out the vast Office Development documentation in the SDK.) For this level of control, you need a better Active Document Container. Unfortunately, Microsoft has not released any such “supported” container. It would be great if they could put out a managed control that could serve as an Active Document Container. But so far, the only thing they offer is an “unsupported” container in the form of an ActiveX control called DSO Framer control.

The DSO Framer control was produced a few years back by the good folks in Microsoft Developer Support. Although their name says it (“Support”, that is), they don’t do it (“Support”, that is) for this control. The DSO Framer control (along with its source code… yes, you get the full source) is provided “as is”. Microsoft doesn’t support it and Dr. WPF doesn’t support it either… However, we both use it!

My sample of WPF hosting Word (illustrated above and available for download) is indeed built using the DSO Framer control. It is an extremely simple implementation of a WPF application hosting an ActiveX control. In this case, that ActiveX control just happens to be an Active Document Container.

NOTE: I could not get the most recent version of the DSO Framer control (compiled as a 32-bit control) to run on my 64-bit Vista box. It runs well on my 32-bit Vista installation. On my x64 machine, the application complains that the control is not registered, even though I can verify and instantiate an instance just fine in OleView. Not sure if this is a problem with the control or a configuration problem on my machine. If others encounter the same problem, I’d love to hear about it. Maybe someone in Microsoft Developer Support could try to reproduce this failure and look into a fix (hint, hint)… Oh yeah… it’s not a supported control. Maybe if I say “pretty please”.

FIX: Several people have advised that compiling the WPF application to specifically target the x86 platform (rather than “Any CPU”) fixes the above load issue on x64.  Thanks to all for this fix!  😀

Anyway, I hope you find this information and sample helpful!

Best regards,
Dr. WPF