From b9de59ce64e8e4be1acae256e4d9ed21e7d841d1 Mon Sep 17 00:00:00 2001
From: Kai Tao <69313318+vanzue@users.noreply.github.com>
Date: Thu, 8 Jan 2026 12:04:03 +0800
Subject: [PATCH] Cmdpal: Peek command in indexer (#44581)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## Summary of the Pull Request
Add a peek command, so we could quickly view the files found by indexer
I’m aware that wiring the Peek command directly into the indexer
extension is fairly PowerToys-specific.
I’m open to suggestions if we think this should instead be handled via a
more general extension / plugin mechanism; if a broader framework is
planned, I’m happy to wait and revisit this once that structure is in
place.
## PR Checklist
- [ ] Closes: #43517
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx
## Detailed Description of the Pull Request / Additional comments
## Validation Steps Performed
---
.../Assets/Peek.png | Bin 0 -> 3122 bytes
.../Commands/PeekFileCommand.cs | 73 ++++++++++++++++++
.../Data/IndexerListItem.cs | 8 ++
.../ext/Microsoft.CmdPal.Ext.Indexer/Icons.cs | 2 +
.../Microsoft.CmdPal.Ext.Indexer/KeyChords.cs | 4 +
.../Microsoft.CmdPal.Ext.Indexer.csproj | 3 +
.../Properties/Resources.Designer.cs | 27 +++++++
.../Properties/Resources.resx | 9 +++
8 files changed, 126 insertions(+)
create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Assets/Peek.png
create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Commands/PeekFileCommand.cs
diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Assets/Peek.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Assets/Peek.png
new file mode 100644
index 0000000000000000000000000000000000000000..3beeccaf1775d0d28bf61303cf90b17cc053f61f
GIT binary patch
literal 3122
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
literal 0
HcmV?d00001
diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Commands/PeekFileCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Commands/PeekFileCommand.cs
new file mode 100644
index 0000000000..808daa567f
--- /dev/null
+++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Commands/PeekFileCommand.cs
@@ -0,0 +1,73 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics;
+using System.IO;
+using ManagedCommon;
+using Microsoft.CmdPal.Ext.Indexer.Properties;
+using Microsoft.CommandPalette.Extensions.Toolkit;
+
+namespace Microsoft.CmdPal.Ext.Indexer.Commands;
+
+///
+/// Command to preview a file using PowerToys Peek.
+///
+public sealed partial class PeekFileCommand : InvokableCommand
+{
+ private const string PeekExecutable = @"WinUI3Apps\PowerToys.Peek.UI.exe";
+
+ private static readonly Lazy _peekPath = new(GetPeekExecutablePath);
+
+ private readonly string _fullPath;
+
+ public PeekFileCommand(string fullPath)
+ {
+ _fullPath = fullPath;
+ Name = Resources.Indexer_Command_Peek;
+ Icon = Icons.PeekIcon;
+ }
+
+ ///
+ /// Gets a value indicating whether Peek is available on this system.
+ ///
+ public static bool IsPeekAvailable => !string.IsNullOrEmpty(_peekPath.Value);
+
+ public override CommandResult Invoke()
+ {
+ var peekExe = _peekPath.Value;
+ if (string.IsNullOrEmpty(peekExe))
+ {
+ return CommandResult.ShowToast(Resources.Indexer_Command_Peek_NotAvailable);
+ }
+
+ try
+ {
+ using var process = new Process();
+ process.StartInfo.FileName = peekExe;
+ process.StartInfo.Arguments = $"\"{_fullPath}\"";
+ process.StartInfo.UseShellExecute = false;
+ process.Start();
+ }
+ catch (Exception ex)
+ {
+ ExtensionHost.LogMessage($"Unable to launch Peek for {_fullPath}\n{ex}");
+ return CommandResult.ShowToast(Resources.Indexer_Command_Peek_Failed);
+ }
+
+ return CommandResult.Dismiss();
+ }
+
+ private static string GetPeekExecutablePath()
+ {
+ var installPath = PowerToysPathResolver.GetPowerToysInstallPath();
+ if (string.IsNullOrEmpty(installPath))
+ {
+ return string.Empty;
+ }
+
+ var peekPath = Path.Combine(installPath, PeekExecutable);
+ return File.Exists(peekPath) ? peekPath : string.Empty;
+ }
+}
diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Data/IndexerListItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Data/IndexerListItem.cs
index 51a30ddc86..54d2744abd 100644
--- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Data/IndexerListItem.cs
+++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Data/IndexerListItem.cs
@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.CmdPal.Core.Common.Commands;
+using Microsoft.CmdPal.Ext.Indexer.Commands;
using Microsoft.CmdPal.Ext.Indexer.Helpers;
using Microsoft.CmdPal.Ext.Indexer.Pages;
using Microsoft.CmdPal.Ext.Indexer.Properties;
@@ -96,6 +97,13 @@ internal sealed partial class IndexerListItem : ListItem
}
commands.Add(new CommandContextItem(new OpenWithCommand(fullPath)));
+
+ // Add Peek command if available (only for files, not directories)
+ if (!isDir && PeekFileCommand.IsPeekAvailable)
+ {
+ commands.Add(new CommandContextItem(new PeekFileCommand(fullPath)) { RequestedShortcut = KeyChords.Peek });
+ }
+
commands.Add(new CommandContextItem(new ShowFileInFolderCommand(fullPath) { Name = Resources.Indexer_Command_ShowInFolder }) { RequestedShortcut = KeyChords.OpenFileLocation });
commands.Add(new CommandContextItem(new CopyPathCommand(fullPath) { Name = Resources.Indexer_Command_CopyPath }) { RequestedShortcut = KeyChords.CopyFilePath });
commands.Add(new CommandContextItem(new OpenInConsoleCommand(fullPath)) { RequestedShortcut = KeyChords.OpenInConsole });
diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Icons.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Icons.cs
index bd9759514c..1e92d9f323 100644
--- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Icons.cs
+++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Icons.cs
@@ -23,4 +23,6 @@ internal static class Icons
internal static IconInfo FilesIcon { get; } = new("\uF571"); // PrintAllPages
internal static IconInfo FilterIcon { get; } = new("\uE71C"); // Filter
+
+ internal static IconInfo PeekIcon { get; } = IconHelpers.FromRelativePath("Assets\\Peek.png");
}
diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/KeyChords.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/KeyChords.cs
index c0fd69d0f2..aa44696a7b 100644
--- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/KeyChords.cs
+++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/KeyChords.cs
@@ -4,6 +4,8 @@
using Microsoft.CmdPal.Core.Common.Helpers;
using Microsoft.CommandPalette.Extensions;
+using Microsoft.CommandPalette.Extensions.Toolkit;
+using Windows.System;
namespace Microsoft.CmdPal.Ext.Indexer;
@@ -14,4 +16,6 @@ internal static class KeyChords
internal static KeyChord CopyFilePath { get; } = WellKnownKeyChords.CopyFilePath;
internal static KeyChord OpenInConsole { get; } = WellKnownKeyChords.OpenInConsole;
+
+ internal static KeyChord Peek { get; } = KeyChordHelpers.FromModifiers(ctrl: true, vkey: (int)VirtualKey.Space);
}
diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Microsoft.CmdPal.Ext.Indexer.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Microsoft.CmdPal.Ext.Indexer.csproj
index 6b3b304825..2c40afd19c 100644
--- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Microsoft.CmdPal.Ext.Indexer.csproj
+++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Microsoft.CmdPal.Ext.Indexer.csproj
@@ -42,6 +42,9 @@
PreserveNewest
+
+ PreserveNewest
+
diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.Designer.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.Designer.cs
index 4394cd6697..469c5faf61 100644
--- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.Designer.cs
+++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.Designer.cs
@@ -132,6 +132,33 @@ namespace Microsoft.CmdPal.Ext.Indexer.Properties {
}
}
+ ///
+ /// Looks up a localized string similar to Peek preview.
+ ///
+ internal static string Indexer_Command_Peek {
+ get {
+ return ResourceManager.GetString("Indexer_Command_Peek", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Failed to launch Peek.
+ ///
+ internal static string Indexer_Command_Peek_Failed {
+ get {
+ return ResourceManager.GetString("Indexer_Command_Peek_Failed", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to PowerToys Peek is not available.
+ ///
+ internal static string Indexer_Command_Peek_NotAvailable {
+ get {
+ return ResourceManager.GetString("Indexer_Command_Peek_NotAvailable", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Search all files.
///
diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.resx b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.resx
index 9ea1c4563e..8f5f760137 100644
--- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.resx
+++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.resx
@@ -202,4 +202,13 @@ You can try searching all files on this PC or adjust your indexing settings.
Files
+
+ Peek preview
+
+
+ PowerToys Peek is not available
+
+
+ Failed to launch Peek
+
\ No newline at end of file