diff --git a/QuickLook.Plugin/QuickLook.Plugin.OfficeViewer/CLSIDRegister.cs b/QuickLook.Plugin/QuickLook.Plugin.OfficeViewer/CLSIDRegister.cs index 7b07792..5fc1ed3 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.OfficeViewer/CLSIDRegister.cs +++ b/QuickLook.Plugin/QuickLook.Plugin.OfficeViewer/CLSIDRegister.cs @@ -23,8 +23,10 @@ namespace QuickLook.Plugin.OfficeViewer; internal static class CLSIDRegister { - public const string Office = "{84F66100-FF7C-4fb4-B0C0-02CD7FB668FE}"; - public const string Visio = "{279D6C9A-652E-4833-BEFC-312CA8887857}"; + public const string MicrosoftWord = "{84F66100-FF7C-4fb4-B0C0-02CD7FB668FE}"; + public const string MicrosoftExcel = "{00020827-0000-0000-C000-000000000046}"; + public const string MicrosoftPowerPoint = "{65235197-874B-4A07-BDC5-E65EA825B718}"; + public const string MicrosoftVisio = "{21E17C2F-AD3A-4b89-841F-09CFE02D16B7}"; public static string GetName(string clsid) { diff --git a/QuickLook.Plugin/QuickLook.Plugin.OfficeViewer/Plugin.cs b/QuickLook.Plugin/QuickLook.Plugin.OfficeViewer/Plugin.cs index c7d7abf..918093a 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.OfficeViewer/Plugin.cs +++ b/QuickLook.Plugin/QuickLook.Plugin.OfficeViewer/Plugin.cs @@ -31,8 +31,8 @@ public class Plugin : IViewer [ ".doc", ".docx", ".docm", ".xls", ".xlsx", ".xlsm", ".xlsb", - ".vsd", ".vsdx", ".ppt", ".pptx", + ".vsd", ".vsdx", ".odt", ".ods", ".odp" ]; @@ -52,12 +52,41 @@ public class Plugin : IViewer if (!Extensions.Any(path.ToLower().EndsWith)) return false; - var previewHandler = PreviewHandlerHost.GetPreviewHandlerGUID(path); + var previewHandler = ShellExRegister.GetPreviewHandlerGUID(Path.GetExtension(path)); if (previewHandler == Guid.Empty) return false; - if (!string.IsNullOrWhiteSpace(CLSIDRegister.GetName($"{{{previewHandler}}}"))) + if (!string.IsNullOrWhiteSpace(CLSIDRegister.GetName(previewHandler.ToString("B")))) + { return true; + } + else + { + // To restore the preview handler CLSID to MS Office + // if running with administrative privileges + if (ShellExRegister.IsRunAsAdmin()) + { + var fileExtension = Path.GetExtension(path); + var fallbackHandler = fileExtension switch + { + ".doc" or ".docx" or ".docm" or ".odt" => CLSIDRegister.MicrosoftWord, + ".xls" or ".xlsx" or ".xlsm" or ".xlsb" or ".ods" => CLSIDRegister.MicrosoftExcel, + ".ppt" or ".pptx" or ".odp" => CLSIDRegister.MicrosoftPowerPoint, + ".vsd" or ".vsdx" => CLSIDRegister.MicrosoftVisio, + _ => null, + }; + + if (fallbackHandler == null) + return false; + + if (!string.IsNullOrWhiteSpace(CLSIDRegister.GetName(fallbackHandler))) + { + // Admin requested + ShellExRegister.SetPreviewHandlerGUID(fileExtension, new Guid(fallbackHandler)); + return true; + } + } + } return false; } diff --git a/QuickLook.Plugin/QuickLook.Plugin.OfficeViewer/PreviewHandlerHost.cs b/QuickLook.Plugin/QuickLook.Plugin.OfficeViewer/PreviewHandlerHost.cs index 1e94495..a1d304d 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.OfficeViewer/PreviewHandlerHost.cs +++ b/QuickLook.Plugin/QuickLook.Plugin.OfficeViewer/PreviewHandlerHost.cs @@ -21,7 +21,6 @@ using System.Drawing; using System.IO; using System.Runtime.InteropServices; using System.Windows.Forms; -using Microsoft.Win32; namespace QuickLook.Plugin.OfficeViewer; @@ -70,34 +69,6 @@ public class PreviewHandlerHost : Control base.Dispose(disposing); } - /// - /// Returns the GUID of the preview handler associated with the specified file. - /// - /// - /// - public static Guid GetPreviewHandlerGUID(string filename) - { - // open the registry key corresponding to the file extension - var ext = Registry.ClassesRoot.OpenSubKey(Path.GetExtension(filename)); - if (ext != null) - { - // open the key that indicates the GUID of the preview handler type - var test = ext.OpenSubKey(@"shellex\{8895b1c6-b41f-4c1c-a562-0d564250836f}"); - if (test != null) return new Guid(Convert.ToString(test.GetValue(null))); - - // sometimes preview handlers are declared on key for the class - var className = Convert.ToString(ext.GetValue(null)); - if (className != null) - { - test = Registry.ClassesRoot.OpenSubKey( - className + @"\shellex\{8895b1c6-b41f-4c1c-a562-0d564250836f}"); - if (test != null) return new Guid(Convert.ToString(test.GetValue(null))); - } - } - - return Guid.Empty; - } - /// /// Resizes the hosted preview handler when this PreviewHandlerHost is resized. /// @@ -123,7 +94,7 @@ public class PreviewHandlerHost : Control return false; // try to get GUID for the preview handler - var guid = GetPreviewHandlerGUID(path); + var guid = ShellExRegister.GetPreviewHandlerGUID(Path.GetExtension(path)); if (guid == Guid.Empty) return false; diff --git a/QuickLook.Plugin/QuickLook.Plugin.OfficeViewer/ShellExRegister.cs b/QuickLook.Plugin/QuickLook.Plugin.OfficeViewer/ShellExRegister.cs new file mode 100644 index 0000000..f5d1026 --- /dev/null +++ b/QuickLook.Plugin/QuickLook.Plugin.OfficeViewer/ShellExRegister.cs @@ -0,0 +1,66 @@ +using Microsoft.Win32; +using System; +using System.IO; +using System.Security.Principal; + +namespace QuickLook.Plugin.OfficeViewer; + +internal static class ShellExRegister +{ + /// + /// Returns the GUID of the preview handler associated with the specified file extension. + /// + /// + /// + public static Guid GetPreviewHandlerGUID(string fileExtension) + { + // open the registry key corresponding to the file extension + var ext = Registry.ClassesRoot.OpenSubKey(fileExtension); + if (ext != null) + { + // open the key that indicates the GUID of the preview handler type + // Such as `Computer\HKEY_CLASSES_ROOT\.docx\shellex\{8895b1c6-b41f-4c1c-a562-0d564250836f}` + // Such as `Computer\HKEY_CLASSES_ROOT\.xlsx\shellex\{8895b1c6-b41f-4c1c-a562-0d564250836f}` + var test = ext.OpenSubKey(@"shellex\{8895b1c6-b41f-4c1c-a562-0d564250836f}"); + if (test != null) return new Guid(Convert.ToString(test.GetValue(null))); + + // sometimes preview handlers are declared on key for the class + var className = Convert.ToString(ext.GetValue(null)); + if (className != null) + { + // Such as `Computer\HKEY_CLASSES_ROOT\{CLASS_NAME}\shellex\{8895b1c6-b41f-4c1c-a562-0d564250836f}` + test = Registry.ClassesRoot.OpenSubKey( + className + @"\shellex\{8895b1c6-b41f-4c1c-a562-0d564250836f}"); + if (test != null) return new Guid(Convert.ToString(test.GetValue(null))); + } + } + + return Guid.Empty; + } + + /// + /// Set the GUID of the preview handler associated with the specified file extension. + /// + /// + /// + public static void SetPreviewHandlerGUID(string fileExtension, Guid guid) + { + // open the registry key corresponding to the file extension + var ext = Registry.ClassesRoot.OpenSubKey(fileExtension); + if (ext != null) + { + // open the key that indicates the GUID of the preview handler type + // Such as `Computer\HKEY_CLASSES_ROOT\.docx\shellex\{8895b1c6-b41f-4c1c-a562-0d564250836f}` + // Such as `Computer\HKEY_CLASSES_ROOT\.xlsx\shellex\{8895b1c6-b41f-4c1c-a562-0d564250836f}` + var test = ext.OpenSubKey(@"shellex\{8895b1c6-b41f-4c1c-a562-0d564250836f}", true); + test?.SetValue(null, guid.ToString("B")); + } + } + + public static bool IsRunAsAdmin() + { + using WindowsIdentity identity = WindowsIdentity.GetCurrent(); + WindowsPrincipal principal = new(identity); + return principal.IsInRole(WindowsBuiltInRole.Administrator); + } +}