mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-06-07 17:42:45 +08:00
[PTRun]Fix dispatcher crash on Adobe Reader (#23789)
* improve thumbnail handling and fix dispatcher crash * spell check * fix spellcheck 2 * restore old code * add adobe thumbnail check * clean spell-check * fix reading of default reg value * switch to real time evaluation * fix spelling * add comment * improve comments * Add additional logs and exception handler * result cache, code improvements, comment improvements * reset log marker to report when switching back to Adobe * spell checker * Improve log text * fix bug where detection was incorrect * spell check * fix return on exception
This commit is contained in:
parent
c6528cc4ed
commit
7dafb45ab4
1
.github/actions/spell-check/expect.txt
vendored
1
.github/actions/spell-check/expect.txt
vendored
@ -1479,6 +1479,7 @@ rescap
|
|||||||
resgen
|
resgen
|
||||||
resheader
|
resheader
|
||||||
resizers
|
resizers
|
||||||
|
RESIZETOFIT
|
||||||
resmimetype
|
resmimetype
|
||||||
RESOURCEID
|
RESOURCEID
|
||||||
resourcemanager
|
resourcemanager
|
||||||
|
@ -180,10 +180,17 @@ namespace Wox.Infrastructure.Image
|
|||||||
image = WindowsThumbnailProvider.GetThumbnail(path, Constant.ThumbnailSize, Constant.ThumbnailSize, ThumbnailOptions.ThumbnailOnly);
|
image = WindowsThumbnailProvider.GetThumbnail(path, Constant.ThumbnailSize, Constant.ThumbnailSize, ThumbnailOptions.ThumbnailOnly);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (extension == ".pdf" && WindowsThumbnailProvider.DoesPdfUseAcrobatAsProvider())
|
||||||
|
{
|
||||||
|
// The PDF thumbnail provider from Adobe Reader and Acrobat Pro lets crash PT Run with an Dispatcher exception. (https://github.com/microsoft/PowerToys/issues/18166)
|
||||||
|
// To not run into the crash, we only request the icon of PDF files if the PDF thumbnail handler is set to Adobe Reader/Acrobat Pro.
|
||||||
|
type = ImageType.File;
|
||||||
|
image = WindowsThumbnailProvider.GetThumbnail(path, Constant.ThumbnailSize, Constant.ThumbnailSize, ThumbnailOptions.IconOnly);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
type = ImageType.File;
|
type = ImageType.File;
|
||||||
image = WindowsThumbnailProvider.GetThumbnail(path, Constant.ThumbnailSize, Constant.ThumbnailSize, ThumbnailOptions.None);
|
image = WindowsThumbnailProvider.GetThumbnail(path, Constant.ThumbnailSize, Constant.ThumbnailSize, ThumbnailOptions.RESIZETOFIT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -4,17 +4,20 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO.Abstractions;
|
using System.IO.Abstractions;
|
||||||
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Interop;
|
using System.Windows.Interop;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
using Wox.Plugin.Logger;
|
||||||
|
|
||||||
namespace Wox.Infrastructure.Image
|
namespace Wox.Infrastructure.Image
|
||||||
{
|
{
|
||||||
[Flags]
|
[Flags]
|
||||||
public enum ThumbnailOptions
|
public enum ThumbnailOptions
|
||||||
{
|
{
|
||||||
None = 0x00,
|
RESIZETOFIT = 0x00,
|
||||||
BiggerSizeOk = 0x01,
|
BiggerSizeOk = 0x01,
|
||||||
InMemoryOnly = 0x02,
|
InMemoryOnly = 0x02,
|
||||||
IconOnly = 0x04,
|
IconOnly = 0x04,
|
||||||
@ -125,5 +128,97 @@ namespace Wox.Infrastructure.Image
|
|||||||
|
|
||||||
throw new InvalidComObjectException($"Error while extracting thumbnail for {fileName}", Marshal.GetExceptionForHR((int)hr));
|
throw new InvalidComObjectException($"Error while extracting thumbnail for {fileName}", Marshal.GetExceptionForHR((int)hr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool logReportedAdobeReaderDetected; // Keep track if Adobe Reader detection has been logged yet.
|
||||||
|
private static bool logReportedErrorInDetectingAdobeReader; // Keep track if we reported an exception while trying to detect Adobe Reader yet.
|
||||||
|
private static bool adobeReaderDetectionLastResult; // The last result when Adobe Reader detection has read the registry.
|
||||||
|
private static DateTime adobeReaderDetectionLastTime; // The last time when Adobe Reader detection has read the registry.
|
||||||
|
|
||||||
|
// We have to evaluate this in real time to not crash, if the user switches to Adobe Reader/Acrobat Pro after starting PT Run.
|
||||||
|
// Adobe registers its thumbnail handler always in "HKCR\Acrobat.Document.*\shellex\{BB2E617C-0920-11d1-9A0B-00C04FC2D6C1}".
|
||||||
|
public static bool DoesPdfUseAcrobatAsProvider()
|
||||||
|
{
|
||||||
|
// If the last run is not more than five seconds ago use its result.
|
||||||
|
// Doing this we minimize the amount of Registry queries, if more than one new PDF file is shown in the results.
|
||||||
|
if ((DateTime.Now - adobeReaderDetectionLastTime).TotalSeconds < 5)
|
||||||
|
{
|
||||||
|
return adobeReaderDetectionLastResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If cache condition is false, then query the registry.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// First detect if there is a provider other than Adobe. For example PowerToys.
|
||||||
|
// Generic GUIDs used by Explorer to identify the configured provider types: {E357FCCD-A995-4576-B01F-234630154E96} = File thumbnail, {BB2E617C-0920-11d1-9A0B-00C04FC2D6C1} = Image thumbnail.
|
||||||
|
RegistryKey key1 = Registry.ClassesRoot.OpenSubKey(".pdf\\shellex\\{E357FCCD-A995-4576-B01F-234630154E96}", false);
|
||||||
|
string value1 = (string)key1?.GetValue(string.Empty);
|
||||||
|
key1?.Close();
|
||||||
|
RegistryKey key2 = Registry.ClassesRoot.OpenSubKey(".pdf\\shellex\\{BB2E617C-0920-11d1-9A0B-00C04FC2D6C1}", false);
|
||||||
|
string value2 = (string)key2?.GetValue(string.Empty);
|
||||||
|
key2?.Close();
|
||||||
|
if (!string.IsNullOrEmpty(value1) || !string.IsNullOrEmpty(value2))
|
||||||
|
{
|
||||||
|
// A provider other than Adobe is used. (For example the PowerToys PDF Thumbnail provider.)
|
||||||
|
logReportedAdobeReaderDetected = false; // Reset log marker to report when Adobe is reused. (Example: Adobe -> Test PowerToys. -> Back to Adobe.)
|
||||||
|
adobeReaderDetectionLastResult = false;
|
||||||
|
adobeReaderDetectionLastTime = DateTime.Now;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then detect if Adobe is the default PDF application.
|
||||||
|
// The global config can be found under "HKCR\.pdf", but the "UserChoice" key under HKCU has precedence.
|
||||||
|
RegistryKey pdfKeyUser = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\.pdf\\UserChoice", false);
|
||||||
|
string pdfAppUser = (string)pdfKeyUser?.GetValue("ProgId");
|
||||||
|
pdfKeyUser?.Close();
|
||||||
|
RegistryKey pdfKeyGlobal = Registry.ClassesRoot.OpenSubKey(".pdf", false);
|
||||||
|
string pdfAppGlobal = (string)pdfKeyGlobal?.GetValue(string.Empty);
|
||||||
|
pdfKeyGlobal?.Close();
|
||||||
|
string pdfApp = !string.IsNullOrEmpty(pdfAppUser) ? pdfAppUser : pdfAppGlobal; // User choice has precedence.
|
||||||
|
if (string.IsNullOrEmpty(pdfApp) || !pdfApp.StartsWith("Acrobat.Document.", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
// Adobe is not used as PDF application.
|
||||||
|
logReportedAdobeReaderDetected = false; // Reset log marker to report when Adobe is reused. (Example: Adobe -> Test PowerToys. -> Back to Adobe.)
|
||||||
|
adobeReaderDetectionLastResult = false;
|
||||||
|
adobeReaderDetectionLastTime = DateTime.Now;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect if the thumbnail handler from Adobe is disabled.
|
||||||
|
RegistryKey adobeAppKey = Registry.ClassesRoot.OpenSubKey(pdfApp + "\\shellex\\{BB2E617C-0920-11d1-9A0B-00C04FC2D6C1}", false);
|
||||||
|
string adobeAppProvider = (string)adobeAppKey?.GetValue(string.Empty);
|
||||||
|
adobeAppKey?.Close();
|
||||||
|
if (string.IsNullOrEmpty(adobeAppProvider))
|
||||||
|
{
|
||||||
|
// No Adobe handler.
|
||||||
|
logReportedAdobeReaderDetected = false; // Reset log marker to report when Adobe is reused. (Example: Adobe -> Test PowerToys. -> Back to Adobe.)
|
||||||
|
adobeReaderDetectionLastResult = false;
|
||||||
|
adobeReaderDetectionLastTime = DateTime.Now;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thumbnail handler from Adobe is enabled and used.
|
||||||
|
if (!logReportedAdobeReaderDetected)
|
||||||
|
{
|
||||||
|
logReportedAdobeReaderDetected = true;
|
||||||
|
Log.Info("Adobe Reader / Adobe Acrobat Pro has been detected as the PDF thumbnail provider.", MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
}
|
||||||
|
|
||||||
|
adobeReaderDetectionLastResult = true;
|
||||||
|
adobeReaderDetectionLastTime = DateTime.Now;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (System.Exception ex)
|
||||||
|
{
|
||||||
|
if (!logReportedErrorInDetectingAdobeReader)
|
||||||
|
{
|
||||||
|
logReportedErrorInDetectingAdobeReader = true;
|
||||||
|
Log.Exception("Got an exception while trying to detect Adobe Reader / Adobe Acrobat Pro as PDF thumbnail provider. To prevent PT Run from a Dispatcher crash, we report that Adobe Reader / Adobe Acrobat Pro is used and show only the PDF icon in the results.", ex, MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we fail to detect it, we return that Adobe is used. Otherwise we could run into the Dispatcher crash.
|
||||||
|
// (This only results in showing the icon instead of a thumbnail. It has no other functional impact.)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user