none
IPreviewHandler interface - excel 2016 high cpu RRS feed

  • Question

  • hi all,

    my company is developing an application which have the ability to preview excel files using: IPreviewHandler interface.

    when it is used with office 2010, we didn't have any problems but when we used it with office 2016, especially excel, we started to see cpu high usage and the only way to solve it is to kill excel.

    my developer said that the following exception is issued before excel.exe*32 hangs and uses 50% cpu:

    System.Runtime.InteropServices.COMException (0x800706BE): The remote procedure call failed. (Exception from HRESULT: 0x800706BE) at IPreviewHandler.Unload()

    i found links that says there is a bug with some KB but i do not see them installed.

    does anyone has an idea ?

    Udi

    Thursday, November 2, 2017 1:55 PM

Answers

  • Hi Udi Mo,

    Thank you for feedback and sorry for late reply.

    I spend some time to test the code you provided. Some variables are defined by yourself, I try to make it and reproduce your scenario. But it does not work.

    The field of clsLogger and enmLogType, I do not know how to declare. I do not know how you add reference of PRJ.Common.

    Dear, it properly hundreds lines of codes. It would be better to provide a project for me to test. You could upload OneDrive and show the link in the reply. If you do not want to show the whole project for security, you could upload the part which could reproduce the error. The code could be test without any variables which is not declared.

    Best Regards,

    Wendy



    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.



    Thursday, November 16, 2017 3:23 PM
    Moderator
  • Hi Wendy,

    thank you for all that time and effort.

    unfortunately, this is all the code I can give you.

    again, thank you very much.

    Udi

    • Marked as answer by Udi Mo Sunday, November 19, 2017 8:28 AM
    Sunday, November 19, 2017 8:28 AM

All replies

  • Hi Udi Mo,

    Thank you for posting here.

    According to your description, I am not sure what cause the error with high CPU. Could your provide some information?

    What is the type of your project? What is the language for your project?

    Could you provide the code sample which produce the error with high CPU?

    Best Regards.,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, November 3, 2017 9:09 AM
    Moderator
  • Hi Wendy,

    thank you for replying.

    here is the code given to me:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices.ComTypes;
    using System.IO;
    using System.Runtime.InteropServices;
    using Microsoft.Win32;
    using PRJ.Common.Logger;
    using PRJ.Common.Utils;
    using PRJ.Common.Declarations;

    namespace PRJ.UIFramework
    {
        [StructLayout(LayoutKind.Sequential)]
        internal struct RECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
            public Rectangle ToRectangle()
            {
                return Rectangle.FromLTRB(left,
                    top, right, bottom);
            }
        }

        [ComImport]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        [Guid("fc4801a3-2ba9-11cf-a229-00aa003d7352")]
        public interface IObjectWithSite
        {
            void SetSite([In, MarshalAs(UnmanagedType.IUnknown)] object pUnkSite);
            void GetSite(ref Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppvSite);
        }

        [ComImport]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        [Guid("8895b1c6-b41f-4c1c-a562-0d564250836f")]
        interface IPreviewHandler
        {
            void SetWindow(IntPtr hwnd, ref RECT rect);
            void SetRect(ref RECT rect);
            void DoPreview();
            void Unload();
            void SetFocus();
            void QueryFocus(out IntPtr phwnd);
            [PreserveSig]
            uint TranslateAccelerator(ref MSG pmsg);
        }

        [StructLayout(LayoutKind.Sequential)]
        internal struct MSG
        {
            public IntPtr hwnd;
            public int message;
            public IntPtr wParam;
            public IntPtr lParam;
            public int time;
            public int pt_x;
            public int pt_y;
        }

        [ComImport]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        [Guid("b7d14566-0509-4cce-a71f-0a554233bd9b")]
        interface IInitializeWithFile
        {
            void Initialize([MarshalAs(UnmanagedType.LPWStr)] string
            pszFilePath, uint grfMode);
        }

        [ComImport]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        [Guid("b824b49d-22ac-4161-ac8a-9916e8fa3f7f")]
        interface IInitializeWithStream
        {
            void Initialize(IStream pstream, uint grfMode);
        }






        public class clsPreviewHandler
        {

            [DllImport("ole32.dll")]
            public extern static void CreateStreamOnHGlobal(IntPtr hGlobal, bool fDelete, out IStream stm);
         
            
            private static Dictionary<string, Guid> gGuidCache = new Dictionary<string, Guid>();
            private static string gNoPreviewFileName = string.Empty;
            private static string gPreviewNotSupportedFileName = string.Empty;

            private IPreviewHandler gPreviewHandler;
            private Control gControl;
            private string gFileNameToDelete = string.Empty;

            private Guid gLatestHandlerGuid = Guid.Empty;
            private object gLatestInstance = null;
            //  ~clsPreviewHandler()
            //  {
            // if (gFileNameToDelete.Length > 0)
            //     System.IO.File.Delete(gFileNameToDelete);

            // }


            // keep instances of

            // keep first word open so only one instance of word will be active
            // and not ping-pong of winword
            static IPreviewHandler gFirstWordPreviewerHandler = null;




            private static List<IPreviewHandler> previewsForDispose = new List<IPreviewHandler>();


            ~clsPreviewHandler()
            {
                try
                {
                  
                    rDispose();
                }
                catch (Exception  ex)
                {

                    clsLogger.rWriteToLog(enmLogType.Error, ex.ToString());
                }
            }


            /// <summary>
            /// this method is called upon exit
            /// </summary>
            public static void rDisposeAllPreviews()
            {
                foreach (IPreviewHandler handler in previewsForDispose)
                {
                     
                    handler.Unload();
                   /// Marshal.FinalReleaseComObject(handler);
     
                }
                previewsForDispose = null;
                 Marshal.FinalReleaseComObject(gFirstWordPreviewerHandler);
                 return;

            }





            public void rDispose()
            {
                
                 if (gPreviewHandler != null)
                {
                    try
                    {

                        // if was previously disposed with rDisposeAllPreviews - quit
                        if (previewsForDispose!=null && !previewsForDispose.Contains(gPreviewHandler))
                            return;


                        //if (previewsForDispose != null && gControl != null && previewsForDispose.ContainsKey(gControl.Handle))
                       // {
                          gPreviewHandler.Unload();
                          previewsForDispose.Remove(gPreviewHandler);
                      //  }

                        gPreviewHandler = null;
                      //  gControl = null;
                      

                      //  if (gPreviewHandler!=gFirstWordPreviewerHandler )
                       //     Marshal.FinalReleaseComObject(gPreviewHandler);
                    }
                    catch (Exception ex)
                    {
                        clsLogger.rWriteToLog(enmLogType.Error, ex.ToString());

                    }

                }

                if (gFileNameToDelete.Length > 0 && gFileNameToDelete != gNoPreviewFileName && System.IO.File.Exists(gFileNameToDelete))
                    System.IO.File.Delete(gFileNameToDelete);

            }

            private Guid rGetPreviewHandlerId(string ext)
            {

                const string cRegLocationForAppGuid = "\\ShellEx\\{8895b1c6-b41f-4c1c-a562-0d564250836f}";


                Guid result = Guid.Empty;
                if (gGuidCache.TryGetValue(ext, out result))
                    return result;




                result = Guid.Empty;
                RegistryKey key = Registry.ClassesRoot.OpenSubKey(ext + cRegLocationForAppGuid);
                if (key == null)
                    key = Registry.ClassesRoot.OpenSubKey("SystemFileAssociations\\" + ext + cRegLocationForAppGuid);




                if (key != null)
                {

                    object defaultValue = key.GetValue(String.Empty);

                    if (defaultValue != null)
                        result = new Guid(defaultValue.ToString());
                }


                // insert to cache
                gGuidCache.Add(ext, result);


                return result;  // returns Guid.Empty if no preview handler found for this file extension


            }


            private void Resize(object sender, EventArgs e)
            {
                if (gControl.IsDisposed)
                    return;
                if (gPreviewHandler == null)
                    return;

                RECT rect = rGetRect();
                gPreviewHandler.SetRect(ref rect);

            }

            private RECT rGetRect()
            {
                //set size
                RECT rect = new RECT();
                rect.left = gControl.ClientRectangle.Left;
                rect.top = gControl.ClientRectangle.Top;
                rect.bottom = gControl.ClientRectangle.Bottom;
                rect.right = gControl.ClientRectangle.Right;
                return rect;
            }


            private string rGetEmptyHtml()
            {
                if (gNoPreviewFileName.Length == 0)
                {
                    byte [] emptyHtml = System.Text.Encoding.Default.GetBytes(PRJ.Common.Declarations.clsResourceReader.rGetFileContent("NoPreviewExists"));
                    gNoPreviewFileName = PRJ.Common.Utils.clsConfig.rGetTemporaryFile("htm");
                    System.IO.File.WriteAllBytes(gNoPreviewFileName, emptyHtml);              
                }

                return gNoPreviewFileName;
            }

            private string rGetPreviewNotSupportedHtml()
            {
                if (gPreviewNotSupportedFileName.Length == 0)
                {
                    byte[] previewNotSupportedHtml = System.Text.Encoding.Default.GetBytes(PRJ.Common.Declarations.clsResourceReader.rGetFileContent("PreviewNotSupported"));
                    gPreviewNotSupportedFileName = PRJ.Common.Utils.clsConfig.rGetTemporaryFile("htm");
                    System.IO.File.WriteAllBytes(gPreviewNotSupportedFileName, previewNotSupportedHtml);
                }

                return gPreviewNotSupportedFileName;
            }

            private void InvokeOnPreviewThread(Control piControl,MethodInvoker d)
            {
                if (piControl.IsHandleCreated)
                    piControl.Invoke(d);
            }


            public void rPreview(string piFile, Control piControl, bool piDeleteFileOnExit = true)
            {

                InvokeOnPreviewThread(piControl,delegate()
                {
                    rPreviewInternal(piFile, piControl);
                });
            }


            private void rPreviewInternal(string piFile, Control piControl)
            {
                try
                {

                    // eldor - patch
                    if (piControl.IsDisposed)
                        return;
                    

     
                    Guid handlerGuid = Guid.Empty;
                    string fileExt = string.Empty;

                    //new control
                    if (gControl == null)
                    {
                        gControl = piControl;
                        gControl.SizeChanged += new System.EventHandler(this.Resize);
                    }


                    // dispose old if needed
                   if (gPreviewHandler!=null)
                   {
                       rDispose();
                    }


                    // replacing control
                    //if (gControl != piControl)
                   // {
                   //     if (!gControl.IsDisposed)
                        //    gControl.SizeChanged -= new System.EventHandler(this.Resize);
    //
    //                    gControl = piControl;
     //                   gControl.SizeChanged += new System.EventHandler(this.Resize);

     //               }





                    if (piFile != string.Empty)
                    {
                        fileExt = piFile.Substring(piFile.LastIndexOf("."));
                        handlerGuid = rGetPreviewHandlerId(fileExt);
                    }

                   
                   


                    if (piFile == string.Empty || handlerGuid == Guid.Empty)
                    {
                       
                        rPreview(rGetEmptyHtml(), gControl, false);
                        return;
                    }

                    gFileNameToDelete = piFile;

                    object instance = null;

                 
                     Type previewerType = Type.GetTypeFromCLSID(handlerGuid);

                        //create instance
                     instance = Activator.CreateInstance(previewerType);
                 

                    //now we need to querry interface for the required interfaces.
                    IObjectWithSite ows = (IObjectWithSite)instance;
                    gPreviewHandler = (IPreviewHandler)instance;
                    IInitializeWithFile iwf = instance as IInitializeWithFile;
                    IInitializeWithStream iws = instance as IInitializeWithStream;

                    //now we need to initialize the object

                    if (iwf != null)
                    {
                        iwf.Initialize(piFile, 0);
                    }
                    else
                    {
                        if (iws != null)
                        {
                            IStream stream;
                            byte[] fileData = System.IO.File.ReadAllBytes(piFile);
                            IntPtr hGlobal = Marshal.AllocHGlobal(fileData.Length);
                            Marshal.Copy(fileData, 0, hGlobal, fileData.Length);
                            CreateStreamOnHGlobal(hGlobal, true, out stream);
                            if (stream != null)
                                iws.Initialize(stream, 0);
                        }
                    }

                    //set the current form (implements IPreviewHandlerFrame)
                    ows.SetSite(gControl);

                    //set size
                    RECT rect = rGetRect();

                    gPreviewHandler.SetWindow(gControl.Handle, ref rect);

                    gPreviewHandler.SetRect(ref rect);
                  
                    //perform the preview
                    gPreviewHandler.DoPreview();
                    // gPreviewHandler.SetFocus();
                    ////// TRYING WITHOUT ELDOR gControl.Refresh();

                    //////previewsForDispose.Add(gControl.Handle, gPreviewHandler);
                    previewsForDispose.Add(gPreviewHandler);
                    // keep it as for cache purpose if is first
                    if (gFirstWordPreviewerHandler == null && fileExt.ToLower().Contains("doc"))
                    {
                        gFirstWordPreviewerHandler = gPreviewHandler;

                    }
     
                }
                catch (Exception ex)
                {
                    clsLogger.rWriteToLog(enmLogType.Error, ex.ToString());
                    if (gPreviewHandler != null)
                    {
                        gPreviewHandler.Unload();
                        if (gFileNameToDelete.Length > 0)
                        {
                            System.IO.File.Delete(gFileNameToDelete);
                            gFileNameToDelete = string.Empty;
                        }
                        gPreviewHandler = null;

                    }

                    // generating emty html
                    if (piFile != rGetPreviewNotSupportedHtml())
                    {
                        rPreview(rGetPreviewNotSupportedHtml(), gControl, false);
                    }                
                }           
            }       
        }

    }

    Saturday, November 4, 2017 9:42 AM
  • Hi Udi Mo,

    Thank you for feedback and sorry for late reply.

    I spend some time to test the code you provided. Some variables are defined by yourself, I try to make it and reproduce your scenario. But it does not work.

    The field of clsLogger and enmLogType, I do not know how to declare. I do not know how you add reference of PRJ.Common.

    Dear, it properly hundreds lines of codes. It would be better to provide a project for me to test. You could upload OneDrive and show the link in the reply. If you do not want to show the whole project for security, you could upload the part which could reproduce the error. The code could be test without any variables which is not declared.

    Best Regards,

    Wendy



    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.



    Thursday, November 16, 2017 3:23 PM
    Moderator
  • Hi Wendy,

    thank you for all that time and effort.

    unfortunately, this is all the code I can give you.

    again, thank you very much.

    Udi

    • Marked as answer by Udi Mo Sunday, November 19, 2017 8:28 AM
    Sunday, November 19, 2017 8:28 AM
  • Hi Wendy,

    thank you for all that time and effort.

    unfortunately, this is all the code I can give you.

    again, thank you very much.

    Udi

    Hi.

    Tell me please, did you solve this problem? I have the same problem. I would be very grateful for the answer. Sorry for my English.


    Wednesday, February 20, 2019 1:46 PM