In an earlier post, I explained how to host Preview Handlers in Windows Forms. You may recall that Preview Handlers are implementations of the COM interface IPreviewHandler and are initialised either by a file or a stream (depending on whether they implement IInitializeWithStream or IInitializeWithFile).

I observed recently that the MAPI Mail Preview Handler (the handler registered for Outlook .MSG files) did not implement either of the aforementioned interfaces. After some further research, I have discovered that there is a third initialisation technique – which some preview handler implementations support to the exclusion of all others.

The COM interface IInitializeWithItem is used to initialise a preview handler (or thumbnail provider, etc) with an implementation of IShellItem. The latter interface is used by the Windows Shell API and represents a file, folder or virtual item in Windows Explorer. So why insist on a shell item instead of initialising the preview handler with a file or stream? Well, you have to remember that the primary host for preview handlers is, of course, Windows Explorer – which works primarily with shell items, rather than raw files or streams. They also remove the need for preview handlers to know the location of the item on disk (if indeed it is even on disk), allowing a wider variety of content to be loaded into them.

Declaration

The declaration for the interface is as follows:

internal const string GUID_ISHELLITEM = "43826d1e-e718-42ee-bc55-a1e261c37bfe";

(Don’t worry, i’ll explain that later…)

[
    ComImport,
    InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
    Guid("7F73BE3F-FB79-493C-A6C7-7EE14E245841")
]
interface IInitializeWithItem {
    void Initialize(IShellItem psi, uint grfMode);
}

[
    ComImport,
    InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
    Guid(PreviewHandlerHost.GUID_ISHELLITEM)
]
interface IShellItem {
    void BindToHandler(
        IntPtr pbc,
        [MarshalAs(UnmanagedType.LPStruct)]Guid bhid,
        [MarshalAs(UnmanagedType.LPStruct)]Guid riid,
        out IntPtr ppv
    );
    void GetParent(out IShellItem ppsi);
    void GetDisplayName(uint sigdnName, out IntPtr ppszName);
    void GetAttributes(uint sfgaoMask, out uint psfgaoAttribs);
    void Compare(IShellItem psi, uint hint, out int piOrder);
};

Rather unsurprisingly, there is no managed API for obtaining instances of IShellItem, and they can’t be instantiated via Activator.CreateInstance(). Instead, the Shell API function SHCreateItemFromParsingName() is needed:

[DllImport("shell32.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
    static extern void SHCreateItemFromParsingName(
    [In][MarshalAs(UnmanagedType.LPWStr)] string pszPath,
    [In] IntPtr pbc, [In][MarshalAs(UnmanagedType.LPStruct)] Guid riid,
    [Out][MarshalAs(UnmanagedType.Interface, IidParameterIndex = 2)] out IShellItem ppv
);

(There are other functions that return IShellItem instances, but this one is the most appropriate for obtaining them for file system objects.)

Usage

Recalling the implementation of PreviewHandlerHost (my Windows Forms control), we can add a third condition to the section which initialises the preview handler:

if (mCurrentPreviewHandler is IInitializeWithFile) {
    ((IInitializeWithFile)mCurrentPreviewHandler).Initialize(filename, 0);
}
else if (mCurrentPreviewHandler is IInitializeWithStream) {
    mCurrentPreviewHandlerStream = File.Open(filename, FileMode.Open);
    StreamWrapper stream = new StreamWrapper(mCurrentPreviewHandlerStream);
    ((IInitializeWithStream)mCurrentPreviewHandler).Initialize(stream, 0);
}
else if (mCurrentPreviewHandler is IInitializeWithItem) {
    IShellItem shellItem;
    SHCreateItemFromParsingName(
        filename,
        IntPtr.Zero,
        new Guid(GUID_ISHELLITEM),
        out shellItem
    );
    ((IInitializeWithItem)mCurrentPreviewHandler).Initialize(shellItem, 0);
}

The reason for defining a constant for the GUID of the IShellItem interface is that it must be passed to the SHCreateItemFromParsingName() function. (There are two versions of the interface, one for compatibility with Windows XP SP1 and the other for Vista and onwards, the parameter determines which one to create.)

Final words

So, what does this enable us to do? Well, to date i’ve only come across one preview handler that insists on being initialised in this manner; the MAPI Mail Preview Handler {435fdba0-964c-43a7-8aff-cc94e21b2249}. However, in the business software I write, being able to preview Outlook messages is a significant requirement unto itself. Since Windows 7 ships with several more preview handlers than Vista did, it follows that the likelihood of encountering more which are initialised from shell items will increase.

Download

If you find my code useful, please consider making a donation.

PreviewHandlers3.zip – Visual Studio 2012 solution (includes test app) – .NET Framework 4.0 (updated 2013/10/14)

Regarding MSG Files

Several people have reported problems with the preview handler for Outlook mail messages (.msg files). To ensure that e-mail previews are displayed correctly, you will need to:

  • Ensure that the solution platform matches the architecture of the preview handler; i.e. x64 on 64-bit OS with 64-bit Office, or x86 on 32-bit OS with 32-bit Office. If you get this wrong, you will get an E_FAIL or CO_E_SERVER_EXEC_FAILURE error.
  • Use the included app.manifest file when building the project. This manifest instructs the runtime to load version 6 of the Windows Common Controls library (instead of the default version 5).
  • Run the project without attaching the debugger. In my build environment, this was the only way I could get it to work.

81 thoughts on “Preview Handlers Revisited

  1. vote

    Brad,

    Thank you for exposing this additional interface for initializing Preview Handlers. In developing a similar control to the one in your previous post, I had come across this issue but could not understand what the problem was until I came across your blog article.

    But I wanted to highlight some additional issues I came across and am continuing to have that you may have resolved.

    • Compiling for AnyCPU or x64 and running on an x64 platform, an exception occurs when trying to create the IPreviewHandler object via Activator.CreateInstance(). This occurs with the both the MAPI Mail Preview Handler {435fdba0-964c-43a7-8aff-cc94e21b2249} and the Microsoft Windows MAPI Preview Handler {53BEDF0B-4E5B-4183-8DC9-B844344FA104} (pre-Office 2010). Resorting to an x86 compilation resolves this when running on an x64 platform.
    • Finding the associated preview handler for a extension requires an additional search of the HKEY_CLASSES_ROOT\SystemFileAssociations as well. I have found on some systems this is the only way to locate certain preview handlers. It may be the difference between Office 2007 and Office 2010 in where these entries are installed. Have you encountered this?
    • Once I display an .msg file via the preview handler, the body of the message is not displayed and an exception occurs preventing any further use of the application. As you don’t mention any issue with it in your blog, I assume you have not encountered this problem or have gotten around this issue. It had been documented by a few others in posts (see http://social.msdn.microsoft.com/Forums/en/outlookdev/thread/040d8f15-56d9-4707-a652-48f4e07e8db3 and http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/91e4ee2d-344d-4bb9-9798-5a8194b523a1 but with no solutions. Any thoughts? Maybe there is something you are doing different from others? Since you did not supply any source for this solutions and some of the source of the snippets look different form your earlier post where you did supply source, I was wondering if you could share your source and see if there is some solution that I (and others) are not seeing.

    I too am in need of this for a business software solution where Outlook previews would be a huge feature. Any assistance would be greatly appreciated.

    Thanks for blogging about this and taking any time to reply.

    Bill Boland

    Reply
    • +1
      vote

      Thanks for your comment, Bill. I’m on vacation interstate right now, so I will try to address the points you raised when I get back home (in about a week). Certainly have not encountered the issue where the message body is not displayed, so I will try and look into that too.

      Reply
    • vote

      Thanks for your patience, Bill.

      I have edited the article to include a link to the updated source code. This is the version that supports preview handlers that use IInitializeWithItem.

      I have tried compiling under x86 and x64; neither produce any exceptions when loading an .MSG file, however I am running on a system with Office 2010 (64-bit) installed. I did notice a visual glitch when running under x64, however, so it may not be completely supported. Nevertheless, I am not getting any exceptions and the message body is being displayed correctly.

      I did not find it necessary to search in the SystemFileAssociations registry key in order to get the appropriate preview handler, however I see no harm in adding a check at this location. I think the precise location of the key may differ according to Windows version, Office version and various other factors.

      I hope this helps. Try my source code out and see if your problems persist.

      Reply
  2. vote

    Hi Brad,
    i noticed some exceptions in your latest code, and i tried to fix them:
    In “OnResize” I changed
    “((IPreviewHandler)mCurrentPreviewHandler).SetWindow(Handle, ref r);”
    to
    “((IPreviewHandler)mCurrentPreviewHandler).SetRect(ref r);”
    That helped for the resize exception, but i still have an exception, when closing my app in “UnloadPreviewHandler”.
    I also recognized some resizing bugs (unreadable screen) when resizeing a MSG preview, is this a sideeffect of my “bugfix”?
    Best Regards
    Thorsten

    Reply
    • +1
      vote

      Hi Thorsten,
      Thanks for pointing out the problem in OnResize – this was not raising any exceptions for me, but the call to SetWindow is definitely unnecessary when SetRect will suffice. SetWindow only needs to be called once during initialisation. I have noticed some visual glitches with certain preview handlers – in particular, the Windows Media Player one – but I can’t fault what my code is doing. If you can give me some specific examples of when you encounter exceptions in UnloadPreviewHandler, that would be very helpful to me – I have tested several different file formats and have not been able to trigger any exceptions in that method.

      Reply
      • vote

        I found two problems with the way resources are released.
        The main problem seems to be that mCurrentPreviewHandler).Unload() does not work if it’s host window has been invalidated. To avoid this, call UnloadPreviewHandler for your instance of the preview user control from the form closing event.

        Second, less important (it seems to cause no problems if not done but prevents several un-necessary repeat attempts to unload the handler), it should set the preview handler to null in UnloadPreviewHandler after unloading it:

        public void UnloadPreviewHandler() {
        if (mCurrentPreviewHandler is IPreviewHandler) {
        // explicitly unload the content
        ((IPreviewHandler)mCurrentPreviewHandler).Unload();
        mCurrentPreviewHandler = null;
        }
        if (mCurrentPreviewHandlerStream != null) {
        mCurrentPreviewHandlerStream.Close();
        mCurrentPreviewHandlerStream = null;
        }
        }

        Reply
  3. vote

    Hello,

    I have the same problem with .msg files. Only the header is being displayed!

    Brad mentions the MAPI Mail Preview Handler {435fdba0-964c-43a7-8aff-cc94e21b2249}, but on my system I can’t find this GUID in the registry.
    Under SystemFileAssociations\.msg I have the handler {53BEDF0B-4E5B-4183-8DC9-B844344FA104} which points to MAPI Mail Previewer, mssvp.dll

    The problem seems to be discussed here too: http://int.social.msdn.microsoft.com/Forums/en/outlookdev/thread/c38a53f5-36d0-4261-9186-e276ad12ac0d
    They say it is related to commctrl.dll version being used.

    When calling DoPreview() I receive Error HRESULT E_FAIL has been returned from a call to a COM component.

    I’m using Office 2007.

    Best regards,
    Cantemir

    Reply
  4. vote

    Let me know that I found a solution to my problem. It really was a comctl32.dll version problem. Since explorer.exe and outlook.exe used version 6.10 and my app loaded 5.82, I forced my app to load the 6.10 version too, using an app.manifest with:

    Hope it helps other too!

    Reply
    • vote

      Thanks, Cantemir – I never would have guessed the cause of this problem without your insight. I’m going to have to look into reasons why apps would be using an earlier version of the Common Controls DLL… perhaps the version of the .NET Framework determines this? I see the potential for mismatches depending on the version of Windows and Office as well…

      Reply
  5. vote

    I am playing with a C++ equivalent host. Most document types seem to work ok, EXCEPT for HTML. DoPreview() returns E_FAIL. Somewhere in the middle my site is queried for IHlinkFrame which I don’t implement.

    Funnily enough the same host shows HTML previews ok in vista (!) so it is only win7 that has the problem

    does your host work for HTML files in windows 7? (sorry I don’t know enough C# to build your CS sample code)

    thanks

    Reply
    • vote

      I am going to presume that the preview handler for HTML files would be provided by Internet Explorer. Your problem may not reside with the version of Windows, but rather the version of IE installed. If the preview handler is querying your code, then I would imagine the handler is designed to be hosted by Windows Explorer only, with no third-party application support. You could always use a COM WebBrowser control to preview HTML content instead, I can’t imagine any difference in performance.

      Reply
  6. vote

    according to HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\PreviewHandlers the html previewer is supplied by windows live mail (!)

    at any rate, can you see HTML previews with your C# host on windows 7?

    Reply
    • vote

      Okay, this is an interesting one… Firstly, I had to enhance my registry key search as per Bill’s comment, otherwise the GUID of the preview handler wouldn’t be found. Having acquired it, I discovered that one of two behaviours will happen on my install of Win 7 x64 – if compiled as 32-bit, I get an AccessViolationException during the initialisation of the preview handler – if compiled as 64-bit, it works fine and the HTML document is previewed.

      I checked, and you’re right, it does seem to be the Windows Live Mail program supplying the handler. I have a feeling that the DLL containing the preview handler will match the architecture of the Windows version installed (64-bit in my case) – and will not provide an alternative if the handler is being loaded from a host targeting a different architecture (e.g. 32-bit).

      I hope this sheds some light on your problem.

      Reply
  7. vote

    i am on 32 bit windows 7. Now that you mention it, my vista virtual machine is 64 bit, so that’s why perhaps it “works on vista” (?)

    your windows form container, it wouldn’t be automatically supplying any IHlinkFrame interface, would it?

    Reply
    • +1
      vote

      Unless the Windows Forms base class, Control, implements IHlinkFrame (which I do not think it does… at least I cannot see any reason why it would), then my host does not implement it. Perhaps the preview handler only queries the interface and extends its behaviour if the host implements it, but is robust enough to function if it is not implemented by the host?

      Reply
  8. vote

    I found another C# sample and it works on my win7 so there must be a thing with winforms hosting… http://c4fdevkit.codeplex.com/

    how are com objects created in C# by default? e.g.
    _comInstance = Activator.CreateInstance(comType);
    is that going to be in proc or a separate server? Is the form environment appartment threaded or multithreaded?

    Reply
  9. vote

    Hello,
    It seems that the .msg file extension,.ong, .htm do not have the ShellEx under root.
    Is there a way I can map the extensions .e .msg , .htm etc to the GUIDs under HKEY_LOCAL_Machine\Software\Microsoft\CurrentVersion\PreviewHandlers?
    for instance I have “53BEDF0B-4E5B-4183-8DC9-B844344FA104” coressponsding to “Microsoft Windows MAPI Preview Handler” so How would the programa ssociate .msg to that value?

    Thank you

    Reply
    • vote

      Although the MAPI Preview Handler is capable of displaying those file formats, they are not registered with the handler by default, so there is no way of automatically determining which handler to use for them. You can either create the necessary registry entries (which would then allow Windows Explorer and other host programs to use the handler for these formats), or maintain a manual list of exceptions in your own application (a simple name/value pair list relating the file extensions to the GUIDs of the handlers would be sufficient).

      Reply
  10. vote

    thanks for your previous reply,
    I am trying to preview a pdf that is on a server (http)
    so I pass the URL as the filename, this seems to crash so I though I would read the pdf into a stream using the webResponse object and use the open(stream,guid) method in the previewhandler; however this is throwing an exception too “”Error HRESULT E_FAIL has been returned from a call to a COM component.””
    Any idea how I would be able to preview a remote pdf without downloading it to local harddrve?
    Thank you

    Reply
    • vote

      Hi John. My wrapper for the IStream interface is a very basic one. You may find that you need to provide a more complete implementation in order to wrap an HTTP stream. For example, that kind of stream may not have a fixed length, or may not support seeking. First verify that you can preview a PDF by passing a FileStream (from a local file) to the preview handler – if this works, the type of stream is likely to be the cause of the problem. It may also be the case that the PDF preview handler simply doesn’t support initialisation from this type of stream; unfortunately, there is no documentation available for these components.

      Reply
  11. vote

    Hello,
    Sometimes when a preview is to be loaded for an excel document
    the code hangs at
    Activator.CreateInstance(comType), that takes over 5 mintes to come back, in the meantime the whole applicaion hangs, is there a way I can cancel the creation of the comObject?
    Any other ideas to prevent the app from hanging?

    Thank you

    Reply
  12. vote

    @john Creating an instance from a COM type involves a number of processes, one of which being a registry lookup. If the registry is corrupted or extremely fragmented, that could explain the long delays. Alternatively, there may be excessive load on the system in some other area which is taking priority over the operation. In my own tests, the Excel preview handler seems to load relatively quickly each time.

    Reply
  13. vote

    Hello Bradley,
    does the MAPI Mail Preview Handler allow for attachment preview?
    or just the text in the msg
    Thank you

    Reply
  14. vote

    Hello Bradley

    Thank you for such a great code, it saved me a lot of time.

    I just want to signal that I had to change your StreamWrapper and modify the Read & Write methods to use WriteInt32 instead of WriteInt64.
    Otherwise opening pdf/word/etc was working fine (I suppose they don’t use stream ?) but opening a .mht (and other html like extensions) file was throwing an “Attempting to read or write protected memory”

    For info: I’ve a win7 pro 64bit, project is compiled using “Any CPU” but as it’s an Outlook 32bit plugin, the environment is 32bit.

    Hope it helps

    Reply
    • vote

      Thanks for the advice; I was getting that error intermittently and was never quite sure what was causing it – seems so obvious now that I look at it.

      Reply
  15. vote

    Forgot:
    Opening .msg file doesn’t work. It display the header but not the body content. It throw an E_FAIL error when calling DoPreview(). This is when the preview control is hosted in Outlook itself (Outlook addin). When the preview is hosted in a standard winform app, it show a popup that Outlook is not the default client blablabla..
    Anyway, I convert the .msg file to .mht and then the preview works.

    Reply
    • vote

      Curiously, .msg previews work fine for me using my original code (as posted). Not getting an errors or prompts. Outlook 2010 on Windows 7 here.

      Reply
  16. vote

    You’re welcome
    I also replaced the SetWindow by SetRect in the OnResize as stated above in an old comment. It was very strange: resizing was working fine for a few hours, then it started to throw E_FAIL until I replaced SetWindow by SetRect. Did you made any other bug fix ?

    Anyway, I learned a lot by looking your code, thanks.

    Reply
  17. vote

    Do you have any idea why the .txt preview is not available ? It just show “No preview available”, but windows can show a preview of .txt file in the explorer.
    I’ll have to search, but I first ask here if you have any tips/ideas. Thank you.

    Reply
    • vote

      If your pc is of type x86 then the Read method in StreamWrapper should be using Marshal.WriteInt32 instead of Marshal.WriteInt64. Then .txt files could be previewed with no issues.

      Reply
  18. vote

    Using comment from Simon Mourier in the previous article, I’ve replace the GetPreviewHandlerGUID by this method and now it also works for .txt.
    I post the code here for readers that need it.
    AssocF & AssocStr enum can be found on the web or on microsoft web site.
    It’s *NOT* deeply tested.

    private Guid getPreviewHandlerGUID(string filename)
    {
    var extension = Path.GetExtension(filename);
    if (!string.IsNullOrEmpty(extension))
    {
    uint pcchOut = 0; // size of output buffer
    var extra = “{8895B1C6-B41F-4C1C-A562-0D564250836F}”;

    // First call is to get the required size of output buffer
    COMHelper.AssocQueryString(AssocF.Verify, AssocStr.ShellExtension, extension, extra, null, ref pcchOut);

    // Allocate the output buffer
    StringBuilder pszOut = new StringBuilder((int)pcchOut);

    // Retrieve the guid
    COMHelper.AssocQueryString(AssocF.Verify, AssocStr.ShellExtension, extension, extra, pszOut, ref pcchOut);

    string id = pszOut.ToString();
    Guid guid;
    if (!string.IsNullOrEmpty(id) && id.Length == 38) // GUID = 36 characters + 2 brackets around
    {
    // Remove brackets around GUID
    id = id.Substring(1, id.Length – 2);
    if (GuidHelper.TryParse(id, out guid))
    return guid;
    }
    }
    return Guid.Empty;
    }

    Reply
  19. vote

    When trying to load .doc files with Word 2007 installed I’m getting various errors. Sometimes I get an interface not found error and other times I get the server threw an exception (0x80010105 (RPC_E_SERVERFAULT).

    Any suggestions on how I could resolve this? Opening the file in question works fine.

    Reply
  20. vote

    I was able to figure out the answer to my problem. I had created a hybrid Open that took a Stream and a filename (to get the Guid). The Word previewer implements IInitializeWithFile so that was the problem.

    Reply
  21. vote

    The line

    mCurrentPreviewHandlerStream = File.Open(filename, FileMode.Open);

    should be

    mCurrentPreviewHandlerStream = File.Open(filename, FileMode.Open, FileAccess.Read);

    Reply
  22. vote

    I was having the same .msg issue as some of you – i.e. it would only show header and throw exception. I tried most suggestions including the common controls/Application.EnableVisualStyles but with noi success. However, I had this in my app manifest:

    –><!–

    (Need to understand more about this section’s use) – when I commented it out, I could preview .msg files. My environment: Window 7 64bit, MS Office 2010 32bit, .Net 2.0 app compiled for x86 using VS2010. Hope this helps.
    Sharad

    Reply
  23. vote

    I pasted the compatibility section from the app manifest in my last post but it may have parsed as xml and therefore not shown – it was the compatibility section that I commented out.

    Reply
  24. vote

    I am having the issue where an Office 2010 msg email does not get the body shown. When I use Sharad’s solution in a .net form this works. However, I need to embed this into a legacy VB6 system – does anyone know a different way to solve this without changing the manifest as the manifest seems to be ignored when I create a com control.

    Reply
  25. vote

    You should do “mCurrentPreviewHandlerStream = File.Open(filename, FileMode.Open, FileAccess.Read);” OR copy the stream. Otherwise the file is locked:


    else if (mCurrentPreviewHandler is IInitializeWithStream)
    {
    if (File.Exists(filename))
    {
    // other handlers want an IStream (in this case, a file stream)
    mCurrentPreviewHandlerStream = File.Open(filename, FileMode.Open);
    Stream copyStream = new MemoryStream();
    mCurrentPreviewHandlerStream.CopyTo(copyStream);
    StreamWrapper stream = new StreamWrapper(copyStream);
    ((IInitializeWithStream)mCurrentPreviewHandler).Initialize(stream, 0);
    mCurrentPreviewHandlerStream.Close();
    }
    else
    {
    ErrorMessage = “File not found.”;
    }
    }

    Reply
  26. vote

    Brad / Others,

    Everything is working great on Windows 7 / Office 2010 – however just trying it on Windows 2008 / Office 2010 (Terminal Server / Citrix) and the preview handlers do not seem to be there – neither the registry settings nor the DLL that does the preview on Windows 7 (mapishell.dll). Indeed it looks like Windows Explorer preview of msg files is also not working.

    Anyone have any ideas – presumably something is missing from the Office 2010 install?

    Reply
    • vote

      This is a bit of a long shot, but have you tried installing the Desktop Experience feature on Windows Server 2008? It may include the functionality needed to make preview handlers work under a server OS.

      Reply
    • vote

      Forgot to say – found the solution on Windows 2008 terminal Server – enable the Windows Search Service (which is part of the File Server service so enable that first), then when you fire up Outlook it installs the necessary components and you can view msg files.

      Reply
  27. Pingback: Hosting Preview Handlers in Windows Forms Applications | Brad Smith's Coding Blog

  28. vote

    Hi Bradley

    We are using the preview handlers since a very long time.

    Currently we are facing problems when using the preview handler of Adobe Reader XI.

    It seems as if the pdf preview handle of this version has problems while being unloaded.
    The application seems to hang for about 5 to 10 seconds when closing the application or when explicitly calling FinalReleaseComObject.

    I just built a simple winforms application based on your PreviewHandler.cs class to reproduce the behavior. The application just shows a pdf in your control.
    When stopping the application you might recognize the delay which in some circumstances leads to an application crash warning of the operating system.

    If your are interested in going deeper into this problem, I could send you my sample application. You could just give me an email address to send it to.

    Do you have any idea about what could be wrong with this version of the pdf preview handler?

    Any help would greatly be appreciated.

    Best regards,
    Alex

    Reply
    • vote

      I have found that Excel.exe sometimes hangs when calling Unload() via the IPreviewHandler interface from the user control’s Dispose method. This could also be true for Adobe Reader.

      Subscribing to the parent form’s Closing event seems to be a valid workaround. Simply call SubscribeParentFormClosing() in the following code before loading a preview handler.

      bool m_isSubscribedToParentFormClosing = false;

      private void SubscribeParentFormClosing()
      {
      if (m_isSubscribedToParentFormClosing)
      return;

      if (ParentForm == null)
      return;

      ParentForm.FormClosing += OnParentFormClosing;

      m_isSubscribedToParentFormClosing = true;
      }

      private void OnParentFormClosing(object sender, FormClosingEventArgs e)
      {
      UnloadPreviewHandler();
      }

      protected override void Dispose(bool disposing)
      {
      if (ParentForm != null)
      ParentForm.FormClosing -= OnParentFormClosing;

      base.Dispose(disposing);
      }

      Reply
    • vote

      Preview Handlers were first introduced in Windows Vista, so they are not available in XP and earlier versions of Windows.

      Reply
        • vote

          At the time when I wrote this article, preview handlers would not work on Windows XP with Office 2007. I have since read some articles which suggest there is support for preview handlers if you install Windows Search 4.0 – however, I have not tested this myself and I cannot confirm whether it will work or not.

          Reply
  29. vote

    Hi,

    I´d like to know if is there a way to manage an underlying app through wpffilepreviewer.
    I need to do it with Power Point. I know there is Office.Interop but I didn´t find a way to embed power point in wpf apps with it… So is it possible to manage some power point functions through wpffilepreviewer ?

    thanks

    Reply
    • vote

      This article is about hosting Windows Preview Handlers in WinForms applications, nothing to do with WPF. You might be able to host the control in a WPF app using the WindowsFormsHost class, but I have not tried this myself.

      Reply
  30. vote

    thanks a lot bradley !
    but even in WinForms ( hosting Windows Preview Handlers) is it possible to interop with an office app like Power Point ?

    Best Regards

    Reply
    • vote

      Preview Handlers only give you the ability to load and display previews of documents; they don’t provide any other sort of interoperability. For that, you will need to use VSTO or COM interop instead.

      Reply
  31. vote

    I have noticed that if a load a preview of an Excel file then there is a crash if I have Excel open in the background (with any other file loaded) and then the preview code calls Unload().

    Reply
  32. Pingback: How To Fix 0x80010105 Server 2008 Excel Errors - Windows Vista, Windows 7 & 8

  33. vote

    >> john said on August 11, 2011 at 9:47 pm:
    >>Hello,
    >>Sometimes when a preview is to be loaded for an excel document
    >>the code hangs at
    >>Activator.CreateInstance(comType), that takes over 5 mintes to come back, in the >>meantime the whole applicaion hangs, is there a way I can cancel the creation of the >>comObject?

    Hi, I have the same problem. Is there any solution for this?

    Thank you

    Reply
  34. vote

    I solved the problem. The form must be loaded before use it. So use the Previewer only after the event “Form.Load”

    Reply
  35. vote

    Thx a lot for this code sample. It is very helpful. I was wondering if anybody figured out a solution for the Outlook 32/64bit problem. It works well with a 32bit application and a 32bit Outlook installation and according to some posts it seems to work with 64bit Outlook installations regardless what platform the application uses. But I can’t get it to work with a 64bit application and a 32bit installation. Since it’s working inWindows Explorer there has to be a way. I can see there is a 32bit “Preview Handler Surrogate Host” process running. Is there a way to consume the preview handler through this process?

    Best Regards,
    Wolfgang

    Reply
  36. vote

    Hi brad,

    I use your solution and it works great. One thing I keep bumping in is the Visio previewer. It does preview the file without a problem but when ‘((IPreviewHandler)mCurrentPreviewHandler).Unload();’ is called the actual process ‘Microsoft Offie Visio Previewer’ is not cleaned up. Every time I preview a new Visio file it creates a new instance of ‘Offie Visio Previewer’ where the old one remains. Eventualy this causes freezing screens in my application and the application only continues when i kill the processes manualy. If I use the same technique on Word or Excel files the processes are cleaned up automaticaly and everything keeps working. I wonder if you encountered this before and maybe know a solution to it.

    Thanks in advance!

    Kind regards,
    Roel Winkels

    Reply
  37. vote

    Hi Bradley,

    Many thanks for your fantastic code!! It works brilliantly.

    I wondered if you knew if it is possible to highlight text in the preview pane from a search?

    For example, open/preview a file in your application, type text to find in a textbox, click ‘search’ button and have the search matches highlighted in the preview pane?

    Many thanks,
    GoodJuJu

    Reply
    • vote

      There is no way to interact with preview handlers other than through the public methods exposed by the IPreviewHandler interface. Things like the presentation and interaction with text are implementation details that are specific to each preview handler and, thus, there is no standard way to access that functionality.

      You could, theoretically, use a tool like Spy++ to figure out some of those implementation details for specific preview handlers (control classes, parent/child relationships, etc) and use Win32 API calls to interact with them. However, you would have to develop different routines for each preview handler and there would be no way to safeguard your code against different installed software or changes caused by updates. From a design point of view, this would also undermine the abstraction offered by preview handlers in the first place, so I would advise against it.

      Reply
  38. vote

    IDE : Vs 2015
    Issue : For viewing the preview of my own format files in windows explorer , custom preview handler library is built using 4.0 framework and registered using regasm.exe. Everything works well.

    The problem is with app.vshost.exe[when a console app or windows app is opened in visual studio framework 4.0 and later],previewhost.exe is not firing.if visual studio is closed or framework change to 3.5 or lesser, prevhost.exe is working.

    Reply
    • +1
      vote

      This sounds like a problem with the debugger (or the Visual Studio hosting process) rather than the preview handler host, since everything works when the debugger isn’t attached. Do you get the same problem if you change the build configuration from Debug to Release?

      Also note that preview handler implementations should not be written in .NET – see this article for more info: Now that version 4 of the .NET Framework supports in-process side-by-side runtimes, is it now okay to write shell extensions in managed code? This may well explain the problem you are experiencing.

      Reply
      • vote

        Hi Bradley Smith,
        Thanks for the reply.

        There is no issue when build configuration is changed from Debug to Release.
        Yes the problem with the debugger,

        Error : This file cannot be previewed because of an error with [previewhandlername]

        Isssue Scenario :
        1) If the client opens any project using Visual studio with build configuration Debug(console,forms,wpf application) and enable hosting process checked.
        2)Now if the clients wants to see the preview of .xyz files(preview supported by my preview handler)
        Is there any workaround to overcome this issue, because we can’t force the client to disable the Hosting Process of his personal projects.

        Reply
  39. vote

    Hi Bradley,

    Thanks for your work. But I can’t get the PDF preview working. I am on Windows 10.

    Exception from HRESULT: 0x8008005 (CO_E_SERVER_EXEC_FAILURE)

    It can retrieve the GUID {f8b8412b-dea3-4130-b36c-5e8be73106ac} successfully, so I don’t think it’s 32bit or 64bit issues.

    The preview is working fine in Windows Explorer. Any idea?

    Reply
    • vote

      Not sure what that GUID corresponds to. The preview handler included with Adobe Reader is {dc6efb56-9cfa-464d-8880-44885d7dc193} and the one included with Foxit Reader is {1b96fad8-1c10-416e-8027-6eff94045f6f}. Those are the only two implementations I am aware of.

      Speaking more generally, processor architecture can still matter; the GUID is stored under HKEY_CLASSES_ROOT (which is architecture-neutral), so it’s possible to retrieve the GUID successfully but then fail to initialise the preview handler due to an architecture mismatch. There are also other factors that can affect preview handler hosting, such as conflicting versions of COM components being loaded into memory.

      If you don’t have any luck with preview handlers, the Adobe browser plug-in for Internet Explorer can be used with a WebBrowser control to provide previews for PDFs in any WinForms application. It offers exactly the same user experience as the preview handler.

      Reply

Leave a reply

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> 

required