Compare commits

..

15 Commits

Author SHA1 Message Date
Zachary Teutsch
6e9a4be1a5 update output path for kbm 2025-12-10 14:12:33 -05:00
Hao Liu
161240e9c0 [Keyboard Manager] New Keyboard Manager - Text Remapping Page and Code-behind functionalities (#39888)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

> [Target feature branch ``feature/KeyboardManagerWinUI3``]

Refactor the New Keyboard Manager code to generalize functions (like
Keyboard Hook) for use across pages. Implement Code-behind and the Text
Remapping Page.

- Implement the Text Remapping page
- Restructure the Key Remappings code
- Implement unified Keyboard Hook for all Pages
- Implement Save and Delete for Text Page
- Adjust the Text Page list UI
- Create Input Control for Text Page
- Validate the user input in Text Page and show teaching tip for the
validation error
- Move Remapping Saving into Helper
- Move Remapping Delete into Helper
- Don't check for duplicates if the original keys are the same as the
remapping being edited
- Use InputMode to indicate the active toggle for Original Keys/Remapped
Keys
- Add Rectangle for all pages


![image](https://github.com/user-attachments/assets/e109d82f-01c5-4da7-9efb-facea4070808)

![image](https://github.com/user-attachments/assets/09cc4462-43eb-4823-9b01-ab630a0bf9ed)

![image](https://github.com/user-attachments/assets/9b85c0f6-cbce-40cc-8e65-b755cb852eae)

![image](https://github.com/user-attachments/assets/ff7945cc-6535-4697-812e-93c2effab14e)

![image](https://github.com/user-attachments/assets/7cf887c8-24f3-45bd-956f-b3d655844974)

![image](https://github.com/user-attachments/assets/d958bb16-66b9-44e0-8918-32ddcc780f02)
2025-06-09 15:10:16 +08:00
Hao Liu
3e69b2a411 Merge branch 'main' into feature/KeyboardManagerWinUI3 2025-04-30 10:48:15 +08:00
Hao Liu
d349d81bd5 [Keyboard Manager] New Keyboard Manager - Keys Remapping Window, Keyboard Hook and Input Validator (#39081)
* Add delete remapping function

* Fix the problem that Keyboard Hook is not cleaned properly when the toggle button lost focus (user clicked other checkbox or switched to another app)

* Make sure original toggle button is checked for InputControl

* Disable app setting for single key remapping

* Update KBM Editor UI Signing

* Ensuring Modifier Keys Don't Repeat

* Make sure the shortcut takes at most 4 modifier keys and show notification to the user

* Show teaching tip for reserved illegal shortcuts - Win+L and Ctrl+Alt+Delete

* Add validation to check if the user is trying to remap a key or shortcut that's already mapped for the same app context

* Add validation to make sure key/shortcut cannot be mapped to itself

* Add validation to check the original/new keys are not empty. Application name must be entered if the specific app checkbox is checked.

* Add validation to check shortcuts must contain at least one action key in addition to modifier keys

* Add validation to warn orphaned key to user

* Unify and consolidate the validation code

* Refactor the validation mechanism

* Delete the existing remapping when user modified the content
2025-04-29 17:01:31 +08:00
Hao Liu
ed8b9c6ade Merge branch 'main' into feature/KeyboardManagerWinUI3 2025-04-10 10:56:41 +08:00
Hao Liu
c5635c1e3e [Keyboard Manager] Functional Improvements on new KBM UX (#38652)
* Make Disable toggle button functional in Shortcuts page

* Clean up main window and aggregate Constants

* Update key remapping naming

* Fix the key visual stretch out issue when the shortcut contains too many keys

* Refactor code structure

* fix wrapping in dialog

* update naming

* Implement Keyboard hook to get the user input of remappings

* Implement Reset for InputControl to make sure InputControl can have correct status for various dialog
2025-04-09 10:30:25 +08:00
Hao Liu
c641fd17d2 Merge branch 'main' into feature/KeyboardManagerWinUI3 2025-03-12 12:25:10 +08:00
Hao Liu
4f4bcbfb53 Merge the new WinUI3 Keyboard Manager FHL change into feature branch 2025-03-11 17:04:54 +08:00
Niels Laute
85dea93a50 Design tweaks and XAML refactoring 2025-03-10 11:11:28 +01:00
chenmy77
e184808068 [FHL] Add Select Key UI in Inputcontrol (#37788)
* add press button

* add right press button

* add right press button by original button

* change toggle button position

* fix type error

* merge

* add link

* brush blue in new keys

* remove unuse annotations

* remove unuse keyvisual
2025-03-06 20:48:55 +08:00
Hao Liu
e52ac85a1b [FHL] Save Remapping Config and Data (#37787)
* load URL remapping

* Save Remapping Config and Data

* update mock data for testing

* fix app mapping

* update xaml
2025-03-06 17:56:13 +08:00
Hao Liu
1e3108efbc [FHL] Load Remapping Config and Data for Keyboard Manager new UX (#37762)
* Load remapping config and data

* display single key to shortcuts mapping properly

* get remapping with operation type so we can display them in different tabs

* clean up the xaml
2025-03-05 18:48:16 +08:00
Hao Liu
f7ed043446 [FHL] New static UX for Keyboard Manager Editor (#37747)
* Set up static new UX for Keyboard Manager Editor

* Improve the formatting and performance

* fix spelling
2025-03-04 19:09:28 +08:00
Hao Liu
d90215ee8b [FHL] Set up dev UX for Keyboard Manager Editor (#37730)
* Implement a dev version ui which is copy of current WinUI2 UX

* Implement WinUI3 dropdown and P/Invoke the key list from existing C++ Library

* Update Dllimport path
2025-03-03 10:55:44 +08:00
Hao Liu
b2dae5b48e Initial commit: Have the WinUI3 Editor up and run 2025-02-27 15:42:30 +08:00
157 changed files with 6018 additions and 1327 deletions

View File

@@ -315,7 +315,6 @@ debugbreak
declatory
decryptor
Dedup
Deeplink
DEFAULTBOOTSTRAPPERINSTALLFOLDER
DEFAULTCOLOR
DEFAULTFLAGS
@@ -327,7 +326,6 @@ DEFAULTTONULL
DEFAULTTOPRIMARY
DEFERERASE
DEFPUSHBUTTON
DEFT
deinitialization
DELA
DELETEDKEYIMAGE
@@ -348,7 +346,6 @@ devmgmt
DEVMODE
DEVMODEW
devpal
DFX
DIALOGEX
digicert
dimm

View File

@@ -127,6 +127,7 @@
"PowerToys.KeyboardManager.dll",
"KeyboardManagerEditor\\PowerToys.KeyboardManagerEditor.exe",
"KeyboardManagerEditorUI\\PowerToys.KeyboardManagerEditorUI.exe",
"KeyboardManagerEngine\\PowerToys.KeyboardManagerEngine.exe",
"PowerToys.KeyboardManagerEditorLibraryWrapper.dll",

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.PowerToys.Telemetry" version="2.0.3" />
<package id="Microsoft.PowerToys.Telemetry" version="2.0.2" />
</packages>

View File

@@ -3,5 +3,5 @@
"notificationAliases": ["powertoys@microsoft.com"],
"instanceUrl": "https://microsoft.visualstudio.com",
"projectName": "OS",
"areaPath": "OS\\Windows Client and Services\\WinPD\\DFX-Developer Fundamentals and Experiences\\DEFT\\PowerToys"
"areaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\DIVE\\PowerToys"
}

View File

@@ -112,12 +112,10 @@ extends:
# Prepare the localizations and telemetry config before the release build
- template: .pipelines/v2/templates/steps-fetch-and-prepare-localizations.yml@self
- pwsh: |-
$ErrorActionPreference = 'Stop'
$PSNativeCommandUseErrorActionPreference = $true
& nuget.exe restore -configFile .pipelines/release-nuget.config -PackagesDirectory . .pipelines/packages.config
Move-Item -Force -Verbose "Microsoft.PowerToys.Telemetry.*\build\include\TraceLoggingDefines.h" "src\common\Telemetry\TraceLoggingDefines.h"
Move-Item -Force -Verbose "Microsoft.PowerToys.Telemetry.*\build\include\TelemetryBase.cs" "src\common\Telemetry\TelemetryBase.cs"
- script: |
call nuget.exe restore -configFile .pipelines/release-nuget.config -PackagesDirectory . .pipelines/packages.config || exit /b 1
move /Y "Microsoft.PowerToys.Telemetry.2.0.2\build\include\TraceLoggingDefines.h" "src\common\Telemetry\TraceLoggingDefines.h" || exit /b 1
move /Y "Microsoft.PowerToys.Telemetry.2.0.2\build\include\TelemetryBase.cs" "src\common\Telemetry\TelemetryBase.cs" || exit /b 1
displayName: Emplace telemetry files
- stage: Build_SDK

View File

@@ -344,11 +344,6 @@ jobs:
flattenFolders: True
OverWrite: True
# Check if all projects (located in src sub-folder) import common props
- pwsh: |-
& '.pipelines/verifyCommonProps.ps1' -sourceDir '$(build.sourcesdirectory)\src'
displayName: Audit shared common props for CSharp projects in src sub-folder
# Check if deps.json files don't reference different dll versions.
- pwsh: |-
& '.pipelines/verifyDepsJsonLibraryVersions.ps1' -targetDir '$(build.sourcesdirectory)\$(BuildPlatform)\$(BuildConfiguration)'

View File

@@ -1,54 +0,0 @@
[CmdletBinding()]
Param(
[Parameter(Mandatory = $True, Position = 1)]
[string]$sourceDir
)
# scan all csharp project in the source directory
function Get-CSharpProjects {
param (
[string]$path
)
# Get all .csproj files under the specified path
return Get-ChildItem -Path $path -Recurse -Filter *.csproj | Select-Object -ExpandProperty FullName
}
# Check if the project file imports 'Common.Dotnet.CsWinRT.props'
function Test-ImportSharedCsWinRTProps {
param (
[string]$filePath
)
# Load the XML content of the .csproj file
[xml]$csprojContent = Get-Content -Path $filePath
# Check if the Import element with Project attribute containing 'Common.Dotnet.CsWinRT.props' exists
return $csprojContent.Project.Import | Where-Object { $null -ne $_.Project -and $_.Project.EndsWith('Common.Dotnet.CsWinRT.props') }
}
# Call the function with the provided source directory
$csprojFilesArray = Get-CSharpProjects -path $sourceDir
$hasInvalidCsProj = $false
# Enumerate the array of file paths and call Validate-ImportSharedCsWinRTProps for each file
foreach ($csprojFile in $csprojFilesArray) {
# Skip if the file ends with 'TemplateCmdPalExtension.csproj'
if ($csprojFile -like '*TemplateCmdPalExtension.csproj') {
continue
}
$importExists = Test-ImportSharedCsWinRTProps -filePath $csprojFile
if (!$importExists) {
Write-Output "$csprojFile need to import 'Common.Dotnet.CsWinRT.props'."
$hasInvalidCsProj = $true
}
}
if ($hasInvalidCsProj) {
exit 1
}
exit 0

View File

@@ -31,22 +31,22 @@
<!-- Including MessagePack to force version, since it's used by StreamJsonRpc but contains vulnerabilities. After StreamJsonRpc updates the version of MessagePack, we can upgrade StreamJsonRpc instead. -->
<PackageVersion Include="MessagePack" Version="3.1.3" />
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="9.0.0" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.5" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.4" />
<!-- Including Microsoft.Bcl.AsyncInterfaces to force version, since it's used by Microsoft.SemanticKernel. -->
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.5" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.4" />
<PackageVersion Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="3.1.16" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.5" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.4" />
<PackageVersion Include="Microsoft.SemanticKernel" Version="1.15.0" />
<PackageVersion Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.2" />
<PackageVersion Include="Microsoft.Web.WebView2" Version="1.0.2903.40" />
<!-- Package Microsoft.Win32.SystemEvents added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Drawing.Common but the 8.0.1 version wasn't published to nuget. -->
<PackageVersion Include="Microsoft.Win32.SystemEvents" Version="9.0.5" />
<PackageVersion Include="Microsoft.Win32.SystemEvents" Version="9.0.4" />
<PackageVersion Include="Microsoft.WindowsPackageManager.ComInterop" Version="1.10.340" />
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="9.0.5" />
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="9.0.4" />
<PackageVersion Include="Microsoft.Windows.CsWin32" Version="0.2.46-beta" />
<!-- CsWinRT version needs to be set to have a WinRT.Runtime.dll at the same version contained inside the NET SDK we're currently building on CI. -->
<!--
@@ -72,28 +72,28 @@
<PackageVersion Include="StreamJsonRpc" Version="2.21.69" />
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
<!-- Package System.CodeDom added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Management but the 8.0.1 version wasn't published to nuget. -->
<PackageVersion Include="System.CodeDom" Version="9.0.5" />
<PackageVersion Include="System.CodeDom" Version="9.0.4" />
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
<PackageVersion Include="System.ComponentModel.Composition" Version="9.0.5" />
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="9.0.5" />
<PackageVersion Include="System.Data.OleDb" Version="9.0.5" />
<PackageVersion Include="System.ComponentModel.Composition" Version="9.0.4" />
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="9.0.4" />
<PackageVersion Include="System.Data.OleDb" Version="9.0.4" />
<!-- Package System.Data.SqlClient added to force it as a dependency of Microsoft.Windows.Compatibility to the latest version available at this time. -->
<PackageVersion Include="System.Data.SqlClient" Version="4.8.6" />
<!-- Package System.Diagnostics.EventLog added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Data.OleDb but the 8.0.1 version wasn't published to nuget. -->
<PackageVersion Include="System.Diagnostics.EventLog" Version="9.0.5" />
<PackageVersion Include="System.Diagnostics.EventLog" Version="9.0.4" />
<!-- Package System.Diagnostics.PerformanceCounter added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.11. -->
<PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="9.0.5" />
<PackageVersion Include="System.Drawing.Common" Version="9.0.5" />
<PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="9.0.4" />
<PackageVersion Include="System.Drawing.Common" Version="9.0.4" />
<PackageVersion Include="System.IO.Abstractions" Version="22.0.13" />
<PackageVersion Include="System.IO.Abstractions.TestingHelpers" Version="22.0.13" />
<PackageVersion Include="System.Management" Version="9.0.5" />
<PackageVersion Include="System.Management" Version="9.0.4" />
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
<PackageVersion Include="System.Private.Uri" Version="4.3.2" />
<PackageVersion Include="System.Reactive" Version="6.0.1" />
<PackageVersion Include="System.Runtime.Caching" Version="9.0.5" />
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="9.0.5" />
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.5" />
<PackageVersion Include="System.Text.Json" Version="9.0.5" />
<PackageVersion Include="System.Runtime.Caching" Version="9.0.4" />
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="9.0.4" />
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.4" />
<PackageVersion Include="System.Text.Json" Version="9.0.4" />
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
<PackageVersion Include="UnicodeInformation" Version="2.6.0" />
<PackageVersion Include="UnitsNet" Version="5.56.0" />

View File

@@ -1453,22 +1453,22 @@ SOFTWARE.
- Mages 3.0.0
- Markdig.Signed 0.34.0
- MessagePack 3.1.3
- Microsoft.Bcl.AsyncInterfaces 9.0.5
- Microsoft.Bcl.AsyncInterfaces 9.0.4
- Microsoft.CodeAnalysis.NetAnalyzers 9.0.0
- Microsoft.Data.Sqlite 9.0.5
- Microsoft.Data.Sqlite 9.0.4
- Microsoft.Diagnostics.Tracing.TraceEvent 3.1.16
- Microsoft.DotNet.ILCompiler (A)
- Microsoft.Extensions.DependencyInjection 9.0.5
- Microsoft.Extensions.Hosting 9.0.5
- Microsoft.Extensions.Hosting.WindowsServices 9.0.5
- Microsoft.Extensions.Logging 9.0.5
- Microsoft.Extensions.Logging.Abstractions 9.0.5
- Microsoft.Extensions.DependencyInjection 9.0.4
- Microsoft.Extensions.Hosting 9.0.4
- Microsoft.Extensions.Hosting.WindowsServices 9.0.4
- Microsoft.Extensions.Logging 9.0.4
- Microsoft.Extensions.Logging.Abstractions 9.0.4
- Microsoft.NET.ILLink.Tasks (A)
- Microsoft.SemanticKernel 1.15.0
- Microsoft.Toolkit.Uwp.Notifications 7.1.2
- Microsoft.Web.WebView2 1.0.2903.40
- Microsoft.Win32.SystemEvents 9.0.5
- Microsoft.Windows.Compatibility 9.0.5
- Microsoft.Win32.SystemEvents 9.0.4
- Microsoft.Windows.Compatibility 9.0.4
- Microsoft.Windows.CsWin32 0.2.46-beta
- Microsoft.Windows.CsWinRT 2.2.0
- Microsoft.Windows.SDK.BuildTools 10.0.22621.2428
@@ -1487,25 +1487,25 @@ SOFTWARE.
- SharpCompress 0.37.2
- StreamJsonRpc 2.21.69
- StyleCop.Analyzers 1.2.0-beta.556
- System.CodeDom 9.0.5
- System.CodeDom 9.0.4
- System.CommandLine 2.0.0-beta4.22272.1
- System.ComponentModel.Composition 9.0.5
- System.Configuration.ConfigurationManager 9.0.5
- System.Data.OleDb 9.0.5
- System.ComponentModel.Composition 9.0.4
- System.Configuration.ConfigurationManager 9.0.4
- System.Data.OleDb 9.0.4
- System.Data.SqlClient 4.8.6
- System.Diagnostics.EventLog 9.0.5
- System.Diagnostics.PerformanceCounter 9.0.5
- System.Drawing.Common 9.0.5
- System.Diagnostics.EventLog 9.0.4
- System.Diagnostics.PerformanceCounter 9.0.4
- System.Drawing.Common 9.0.4
- System.IO.Abstractions 22.0.13
- System.IO.Abstractions.TestingHelpers 22.0.13
- System.Management 9.0.5
- System.Management 9.0.4
- System.Net.Http 4.3.4
- System.Private.Uri 4.3.2
- System.Reactive 6.0.1
- System.Runtime.Caching 9.0.5
- System.ServiceProcess.ServiceController 9.0.5
- System.Text.Encoding.CodePages 9.0.5
- System.Text.Json 9.0.5
- System.Runtime.Caching 9.0.4
- System.ServiceProcess.ServiceController 9.0.4
- System.Text.Encoding.CodePages 9.0.4
- System.Text.Json 9.0.4
- System.Text.RegularExpressions 4.3.1
- UnicodeInformation 2.6.0
- UnitsNet 5.56.0

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Some items may be set in Directory.Build.props in root -->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- OneFuzz does not currently support testing with .NET 9.
As a temporary workaround, create a .NET 8 project and use file links
to include the code that needs testing. -->
<PropertyGroup>
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
</PropertyGroup>
</Project>

View File

@@ -1,8 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<!-- Look at Directory.Build.props in root for common stuff as well -->
<Import Project="..\..\..\Common.Dotnet.CsWinRT.props" />
<Import Project="..\..\..\Common.Dotnet.FuzzTest.props" />
<PropertyGroup>
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

View File

@@ -17,7 +17,7 @@
"org": "microsoft",
"project": "OS",
"AssignedTo": "leilzh@microsoft.com",
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DFX-Developer Fundamentals and Experiences\\DEFT\\SALT",
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\SHINE\\PowerToys",
"IterationPath": "OS\\Future"
},
"jobNotificationEmail": "leilzh@microsoft.com",

View File

@@ -1,9 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<!-- Look at Directory.Build.props in root for common stuff as well -->
<Import Project="..\..\..\Common.Dotnet.CsWinRT.props" />
<Import Project="..\..\..\Common.Dotnet.FuzzTest.props" />
<PropertyGroup>
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

View File

@@ -17,7 +17,7 @@
"org": "microsoft",
"project": "OS",
"AssignedTo": "mengyuanchen@microsoft.com",
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DFX-Developer Fundamentals and Experiences\\DEFT\\SALT",
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\SHINE\\PowerToys",
"IterationPath": "OS\\Future"
},
"jobNotificationEmail": "mengyuanchen@microsoft.com",
@@ -58,7 +58,7 @@
"org": "microsoft",
"project": "OS",
"AssignedTo": "mengyuanchen@microsoft.com",
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DFX-Developer Fundamentals and Experiences\\DEFT\\SALT",
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\SHINE\\PowerToys",
"IterationPath": "OS\\Future"
},
"jobNotificationEmail": "mengyuanchen@microsoft.com",
@@ -99,7 +99,7 @@
"org": "microsoft",
"project": "OS",
"AssignedTo": "mengyuanchen@microsoft.com",
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DFX-Developer Fundamentals and Experiences\\DEFT\\SALT",
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\SHINE\\PowerToys",
"IterationPath": "OS\\Future"
},
"jobNotificationEmail": "mengyuanchen@microsoft.com",
@@ -140,7 +140,7 @@
"org": "microsoft",
"project": "OS",
"AssignedTo": "mengyuanchen@microsoft.com",
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DFX-Developer Fundamentals and Experiences\\DEFT\\SALT",
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\SHINE\\PowerToys",
"IterationPath": "OS\\Future"
},
"jobNotificationEmail": "mengyuanchen@microsoft.com",

View File

@@ -25,7 +25,6 @@ namespace AppLauncher
const std::wstring ChromeFilename = L"chrome.exe";
const std::wstring ChromePwaFilename = L"chrome_proxy.exe";
const std::wstring PwaCommandLineAddition = L"--profile-directory=Default --app-id=";
const std::wstring SteamProtocolPrefix = L"steam:";
}
Result<SHELLEXECUTEINFO, std::wstring> LaunchApp(const std::wstring& appPath, const std::wstring& commandLineArgs, bool elevated)
@@ -135,11 +134,12 @@ namespace AppLauncher
}
}
// protocol launch for steam
if (!launched && !app.appUserModelId.empty() && app.appUserModelId.contains(NonLocalizable::SteamProtocolPrefix))
// win32 app with appUserModelId:
// usage example: steam games
if (!launched && !app.appUserModelId.empty())
{
Logger::trace(L"Launching {} as {}", app.name, app.appUserModelId);
auto res = LaunchApp(app.appUserModelId, app.commandLineArgs, app.isElevated);
auto res = LaunchApp(L"shell:AppsFolder\\" + app.appUserModelId, app.commandLineArgs, app.isElevated);
if (res.isOk())
{
launched = true;

View File

@@ -217,11 +217,10 @@ public:
CmdPal::m_enabled.store(true);
std::wstring packageName = L"Microsoft.CommandPalette";
// Launch CmdPal as normal user using explorer
std::wstring launchPath = L"explorer.exe";
std::wstring launchArgs = L"x-cmdpal://background";
std::wstring launchPath = L"shell:AppsFolder\\Microsoft.CommandPalette_8wekyb3d8bbwe!App";
#ifdef IS_DEV_BRANDING
packageName = L"Microsoft.CommandPalette.Dev";
launchPath = L"shell:AppsFolder\\Microsoft.CommandPalette.Dev_8wekyb3d8bbwe!App";
#endif
if (!package::GetRegisteredPackage(packageName, false).has_value())
@@ -270,13 +269,13 @@ public:
if (!firstEnableCall)
{
Logger::trace("Not first attempt, try to launch");
LaunchApp(launchPath, launchArgs, false /*no elevated*/, false /*error pop up*/);
LaunchApp(launchPath, L"RunFromPT", false /*no elevated*/, false /*error pop up*/);
}
else
{
// If first time enable, do retry launch.
Logger::trace("First attempt, try to launch");
std::thread launchThread(&CmdPal::RetryLaunch, launchPath, launchArgs);
std::thread launchThread(&CmdPal::RetryLaunch, launchPath);
launchThread.detach();
}
@@ -291,14 +290,14 @@ public:
CmdPal::m_enabled.store(false);
}
static void RetryLaunch(std::wstring path, std::wstring cmdArgs)
static void RetryLaunch(std::wstring path)
{
const int base_delay_milliseconds = 1000;
int max_retry = 9; // 2**9 - 1 seconds. Control total wait time within 10 min.
int retry = 0;
do
{
auto launch_result = LaunchApp(path, cmdArgs, false, retry < max_retry);
auto launch_result = LaunchApp(path, L"RunFromPT", false, retry < max_retry);
if (launch_result)
{
Logger::info(L"CmdPal launched successfully after {} retries.", retry);
@@ -350,4 +349,4 @@ std::atomic<bool> CmdPal::m_launched{ false };
extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
{
return new CmdPal();
}
}

View File

@@ -3,7 +3,7 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Microsoft.CommandPalette.Extensions" Version="0.2.0" />
<PackageVersion Include="Microsoft.CommandPalette.Extensions" Version="0.1.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="9.0.0-preview.24508.2" />
<PackageVersion Include="Microsoft.Web.WebView2" Version="1.0.2903.40" />
<PackageVersion Include="Microsoft.Windows.CsWin32" Version="0.2.46-beta" />
@@ -12,6 +12,6 @@
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.7.250401001" />
<PackageVersion Include="Shmuelie.WinRTServer" Version="2.1.1" />
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
<PackageVersion Include="System.Text.Json" Version="9.0.5" />
<PackageVersion Include="System.Text.Json" Version="9.0.3" />
</ItemGroup>
</Project>

View File

@@ -14,12 +14,11 @@ namespace TemplateCmdPalExtension;
public class Program
{
[MTAThread]
public static void Main(string[] args)
public static async Task Main(string[] args)
{
if (args.Length > 0 && args[0] == "-RegisterProcessAsComServer")
{
global::Shmuelie.WinRTServer.ComServer server = new();
await using global::Shmuelie.WinRTServer.ComServer server = new();
ManualResetEvent extensionDisposedEvent = new(false);
// We are instantiating an extension instance once above, and returning it every time the callback in RegisterExtension below is called.
@@ -32,8 +31,6 @@ public class Program
// This will make the main thread wait until the event is signalled by the extension class.
// Since we have single instance of the extension object, we exit as soon as it is disposed.
extensionDisposedEvent.WaitOne();
server.Stop();
server.UnsafeDispose();
}
else
{

View File

@@ -128,7 +128,7 @@ public partial class CommandBarViewModel : ObservableObject,
// this comes in when the primary button is tapped
public void InvokePrimaryCommand()
{
PerformCommand(PrimaryCommand);
PerformCommand(SecondaryCommand);
}
// this comes in when the secondary button is tapped

View File

@@ -190,7 +190,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
contextItem.SlowInitializeProperties();
});
if (!string.IsNullOrEmpty(model.Command?.Name))
if (!string.IsNullOrEmpty(model.Command.Name))
{
_defaultCommandContextItem = new(new CommandContextItem(model.Command!), PageContext)
{

View File

@@ -66,10 +66,8 @@ public sealed class CommandProviderWrapper
DisplayName = provider.DisplayName;
Icon = new(provider.Icon);
Icon.InitializeProperties();
// Note: explicitly not InitializeProperties()ing the settings here. If
// we do that, then we'd regress GH #38321
Settings = new(provider.Settings, this, _taskScheduler);
Settings.InitializeProperties();
Logger.LogDebug($"Initialized command provider {ProviderId}");
}
@@ -153,11 +151,9 @@ public sealed class CommandProviderWrapper
Icon = new(model.Icon);
Icon.InitializeProperties();
// Note: explicitly not InitializeProperties()ing the settings here. If
// we do that, then we'd regress GH #38321
Settings = new(model.Settings, this, _taskScheduler);
Settings.InitializeProperties();
// We do need to explicitly initialize commands though
InitializeCommands(commands, fallbacks, serviceProvider, pageContext);
Logger.LogDebug($"Loaded commands from {DisplayName} ({ProviderId})");
@@ -198,6 +194,21 @@ public sealed class CommandProviderWrapper
}
}
/* This is a View/ExtensionHost piece
* public void AllowSetForeground(bool allow)
{
if (!IsExtension)
{
return;
}
var iextn = extensionWrapper?.GetExtensionObject();
unsafe
{
PInvoke.CoAllowSetForegroundWindow(iextn);
}
}*/
public override bool Equals(object? obj) => obj is CommandProviderWrapper wrapper && isValid == wrapper.isValid;
public override int GetHashCode() => _commandProvider.GetHashCode();

View File

@@ -2,25 +2,18 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using ManagedCommon;
using Microsoft.CmdPal.UI.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
namespace Microsoft.CmdPal.UI.ViewModels;
public partial class CommandSettingsViewModel(ICommandSettings? _unsafeSettings, CommandProviderWrapper provider, TaskScheduler mainThread)
public partial class CommandSettingsViewModel(ICommandSettings _unsafeSettings, CommandProviderWrapper provider, TaskScheduler mainThread)
{
private readonly ExtensionObject<ICommandSettings> _model = new(_unsafeSettings);
public ContentPageViewModel? SettingsPage { get; private set; }
public bool Initialized { get; private set; }
public bool HasSettings =>
_model.Unsafe != null && // We have a settings model AND
(!Initialized || SettingsPage != null); // we weren't initialized, OR we were, and we do have a settings page
private void UnsafeInitializeProperties()
public void InitializeProperties()
{
var model = _model.Unsafe;
if (model == null)
@@ -34,27 +27,4 @@ public partial class CommandSettingsViewModel(ICommandSettings? _unsafeSettings,
SettingsPage.InitializeProperties();
}
}
public void SafeInitializeProperties()
{
try
{
UnsafeInitializeProperties();
}
catch (Exception ex)
{
Logger.LogError($"Failed to load settings page", ex: ex);
}
Initialized = true;
}
public void DoOnUiThread(Action action)
{
Task.Factory.StartNew(
action,
CancellationToken.None,
TaskCreationOptions.None,
mainThread);
}
}

View File

@@ -6,7 +6,6 @@ using System.Text.Json;
using AdaptiveCards.ObjectModel.WinUI3;
using AdaptiveCards.Templating;
using CommunityToolkit.Mvvm.Messaging;
using ManagedCommon;
using Microsoft.CmdPal.UI.ViewModels.Messages;
using Microsoft.CmdPal.UI.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
@@ -29,67 +28,43 @@ public partial class ContentFormViewModel(IFormContent _form, WeakReference<IPag
public AdaptiveCardParseResult? Card { get; private set; }
private static string Serialize(string? s) =>
JsonSerializer.Serialize(s, JsonSerializationContext.Default.String);
private static bool TryBuildCard(
string templateJson,
string dataJson,
out AdaptiveCardParseResult? card,
out Exception? error)
{
card = null;
error = null;
try
{
var template = new AdaptiveCardTemplate(templateJson);
var cardJson = template.Expand(dataJson);
card = AdaptiveCard.FromJsonString(cardJson);
return true;
}
catch (Exception ex)
{
Logger.LogError("Error building card from template: {Message}", ex.Message);
error = ex;
return false;
}
}
public override void InitializeProperties()
{
var model = _formModel.Unsafe;
if (model is null)
if (model == null)
{
return;
}
TemplateJson = model.TemplateJson;
StateJson = model.StateJson;
DataJson = model.DataJson;
if (TryBuildCard(TemplateJson, DataJson, out var builtCard, out var renderingError))
try
{
Card = builtCard;
UpdateProperty(nameof(Card));
return;
TemplateJson = model.TemplateJson;
StateJson = model.StateJson;
DataJson = model.DataJson;
AdaptiveCardTemplate template = new(TemplateJson);
var cardJson = template.Expand(DataJson);
Card = AdaptiveCard.FromJsonString(cardJson);
}
var errorPayload = $$"""
{
"error_message": {{Serialize(renderingError!.Message)}},
"error_stack": {{Serialize(renderingError.StackTrace)}},
"inner_exception": {{Serialize(renderingError.InnerException?.Message)}},
"template_json": {{Serialize(TemplateJson)}},
"data_json": {{Serialize(DataJson)}}
}
""";
if (TryBuildCard(ErrorCardJson, errorPayload, out var errorCard, out var _))
catch (Exception e)
{
Card = errorCard;
UpdateProperty(nameof(Card));
return;
// If we fail to parse the card JSON, then display _our own card_
// with the exception
AdaptiveCardTemplate template = new(ErrorCardJson);
var serializeString = (string? s) => JsonSerializer.Serialize(s, JsonSerializationContext.Default.String);
// todo: we could probably stick Card.Errors in there too
var dataJson = $$"""
{
"error_message": {{serializeString(e.Message)}},
"error_stack": {{serializeString(e.StackTrace)}},
"inner_exception": {{serializeString(e.InnerException?.Message)}},
"template_json": {{serializeString(TemplateJson)}},
"data_json": {{serializeString(DataJson)}}
}
""";
var cardJson = template.Expand(dataJson);
Card = AdaptiveCard.FromJsonString(cardJson);
}
UpdateProperty(nameof(Card));

View File

@@ -61,8 +61,6 @@ public partial class ListViewModel : PageViewModel, IDisposable
private Task? _initializeItemsTask;
private CancellationTokenSource? _cancellationTokenSource;
private ListItemViewModel? _lastSelectedItem;
public override bool IsInitialized
{
get => base.IsInitialized; protected set
@@ -330,24 +328,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
}
[RelayCommand]
private void UpdateSelectedItem(ListItemViewModel? item)
{
if (_lastSelectedItem != null)
{
_lastSelectedItem.PropertyChanged -= SelectedItemPropertyChanged;
}
if (item != null)
{
SetSelectedItem(item);
}
else
{
ClearSelectedItem();
}
}
private void SetSelectedItem(ListItemViewModel item)
private void UpdateSelectedItem(ListItemViewModel item)
{
if (!item.SafeSlowInit())
{
@@ -374,60 +355,6 @@ public partial class ListViewModel : PageViewModel, IDisposable
TextToSuggest = item.TextToSuggest;
});
_lastSelectedItem = item;
_lastSelectedItem.PropertyChanged += SelectedItemPropertyChanged;
}
private void SelectedItemPropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
{
var item = _lastSelectedItem;
if (item == null)
{
return;
}
// already on the UI thread here
switch (e.PropertyName)
{
case nameof(item.Command):
case nameof(item.SecondaryCommand):
case nameof(item.AllCommands):
case nameof(item.Name):
WeakReferenceMessenger.Default.Send<UpdateCommandBarMessage>(new(item));
break;
case nameof(item.Details):
if (ShowDetails && item.HasDetails)
{
WeakReferenceMessenger.Default.Send<ShowDetailsMessage>(new(item.Details));
}
else
{
WeakReferenceMessenger.Default.Send<HideDetailsMessage>();
}
break;
case nameof(item.TextToSuggest):
TextToSuggest = item.TextToSuggest;
break;
}
}
private void ClearSelectedItem()
{
// GH #322:
// For inexplicable reasons, if you try updating the command bar and
// the details on the same UI thread tick as updating the list, we'll
// explode
DoOnUiThread(
() =>
{
WeakReferenceMessenger.Default.Send<UpdateCommandBarMessage>(new(null));
WeakReferenceMessenger.Default.Send<HideDetailsMessage>();
TextToSuggest = string.Empty;
});
}
public override void InitializeProperties()

View File

@@ -18,8 +18,6 @@ public partial class ProviderSettingsViewModel(
IServiceProvider _serviceProvider) : ObservableObject
{
private readonly SettingsModel _settings = _serviceProvider.GetService<SettingsModel>()!;
private readonly Lock _initializeSettingsLock = new();
private Task? _initializeSettingsTask;
public string DisplayName => _provider.DisplayName;
@@ -36,9 +34,6 @@ public partial class ProviderSettingsViewModel(
public IconInfoViewModel Icon => _provider.Icon;
[ObservableProperty]
public partial bool LoadingSettings { get; set; } = _provider.Settings?.HasSettings ?? false;
public bool IsEnabled
{
get => _providerSettings.IsEnabled;
@@ -61,60 +56,15 @@ public partial class ProviderSettingsViewModel(
}
}
/// <summary>
/// Gets a value indicating whether returns true if we have a settings page
/// that's initialized, or we are still working on initializing that
/// settings page. If we don't have a settings object, or that settings
/// object doesn't have a settings page, then we'll return false.
/// </summary>
public bool HasSettings
private void Provider_CommandsChanged(CommandProviderWrapper sender, CommandPalette.Extensions.IItemsChangedEventArgs args)
{
get
{
if (_provider.Settings == null)
{
return false;
}
if (_provider.Settings.Initialized)
{
return _provider.Settings.HasSettings;
}
// settings still need to be loaded.
return LoadingSettings;
}
OnPropertyChanged(nameof(ExtensionSubtext));
OnPropertyChanged(nameof(TopLevelCommands));
}
/// <summary>
/// Gets will return the settings page, if we have one, and have initialized it.
/// If we haven't initialized it, this will kick off a thread to start
/// initializing it.
/// </summary>
public ContentPageViewModel? SettingsPage
{
get
{
if (_provider.Settings == null)
{
return null;
}
public bool HasSettings => _provider.Settings != null && _provider.Settings.SettingsPage != null;
if (_provider.Settings.Initialized)
{
LoadingSettings = false;
return _provider.Settings.SettingsPage;
}
// Don't load the settings if we're already working on it
lock (_initializeSettingsLock)
{
_initializeSettingsTask ??= Task.Run(InitializeSettingsPage);
}
return null;
}
}
public ContentPageViewModel? SettingsPage => HasSettings ? _provider?.Settings?.SettingsPage : null;
[field: AllowNull]
public List<TopLevelViewModel> TopLevelCommands
@@ -140,30 +90,4 @@ public partial class ProviderSettingsViewModel(
}
private void Save() => SettingsModel.SaveSettings(_settings);
private void InitializeSettingsPage()
{
if (_provider.Settings == null)
{
return;
}
_provider.Settings.SafeInitializeProperties();
_provider.Settings.DoOnUiThread(() =>
{
// Changing these properties will try to update XAML, and that has
// to be handled on the UI thread, so we need to raise them on the
// UI thread
LoadingSettings = false;
OnPropertyChanged(nameof(HasSettings));
OnPropertyChanged(nameof(LoadingSettings));
OnPropertyChanged(nameof(SettingsPage));
});
}
private void Provider_CommandsChanged(CommandProviderWrapper sender, CommandPalette.Extensions.IItemsChangedEventArgs args)
{
OnPropertyChanged(nameof(ExtensionSubtext));
OnPropertyChanged(nameof(TopLevelCommands));
}
}

View File

@@ -40,7 +40,7 @@ public partial class SettingsModel : ObservableObject
public bool ShowSystemTrayIcon { get; set; } = true;
public bool IgnoreShortcutWhenFullscreen { get; set; }
public bool IgnoreShortcutWhenFullscreen { get; set; } = true;
public Dictionary<string, ProviderSettings> ProviderSettings { get; set; } = [];

View File

@@ -4,7 +4,6 @@
using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.Diagnostics;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
@@ -45,9 +44,6 @@ public partial class TopLevelCommandManager : ObservableObject,
public async Task<bool> LoadBuiltinsAsync()
{
var s = new Stopwatch();
s.Start();
_builtInCommands.Clear();
// Load built-In commands first. These are all in-proc, and
@@ -57,48 +53,53 @@ public partial class TopLevelCommandManager : ObservableObject,
{
CommandProviderWrapper wrapper = new(provider, _taskScheduler);
_builtInCommands.Add(wrapper);
var commands = await LoadTopLevelCommandsFromProvider(wrapper);
lock (TopLevelCommands)
{
foreach (var c in commands)
{
TopLevelCommands.Add(c);
}
}
await LoadTopLevelCommandsFromProvider(wrapper);
}
s.Stop();
Logger.LogDebug($"Loading built-ins took {s.ElapsedMilliseconds}ms");
return true;
}
// May be called from a background thread
private async Task<IEnumerable<TopLevelViewModel>> LoadTopLevelCommandsFromProvider(CommandProviderWrapper commandProvider)
private async Task LoadTopLevelCommandsFromProvider(CommandProviderWrapper commandProvider)
{
WeakReference<IPageContext> weakSelf = new(this);
await commandProvider.LoadTopLevelCommands(_serviceProvider, weakSelf);
var settings = _serviceProvider.GetService<SettingsModel>()!;
List<TopLevelViewModel> commands = [];
foreach (var item in commandProvider.TopLevelItems)
var makeAndAdd = (ICommandItem? i, bool fallback) =>
{
commands.Add(item);
}
var commandItemViewModel = new CommandItemViewModel(new(i), weakSelf);
var topLevelViewModel = new TopLevelViewModel(commandItemViewModel, fallback, commandProvider.ExtensionHost, commandProvider.ProviderId, settings, _serviceProvider);
foreach (var item in commandProvider.FallbackItems)
{
commands.Add(item);
}
lock (TopLevelCommands)
{
TopLevelCommands.Add(topLevelViewModel);
}
};
await Task.Factory.StartNew(
() =>
{
lock (TopLevelCommands)
{
foreach (var item in commandProvider.TopLevelItems)
{
TopLevelCommands.Add(item);
}
foreach (var item in commandProvider.FallbackItems)
{
TopLevelCommands.Add(item);
}
}
},
CancellationToken.None,
TaskCreationOptions.None,
_taskScheduler);
commandProvider.CommandsChanged -= CommandProvider_CommandsChanged;
commandProvider.CommandsChanged += CommandProvider_CommandsChanged;
return commands;
}
// By all accounts, we're already on a background thread (the COM call
@@ -238,71 +239,25 @@ public partial class TopLevelCommandManager : ObservableObject,
private async Task StartExtensionsAndGetCommands(IEnumerable<IExtensionWrapper> extensions)
{
var timer = new Stopwatch();
timer.Start();
// Start all extensions in parallel
var startTasks = extensions.Select(StartExtensionWithTimeoutAsync);
// Wait for all extensions to start
var wrappers = (await Task.WhenAll(startTasks)).Where(wrapper => wrapper != null).Select(w => w!).ToList();
foreach (var wrapper in wrappers)
// TODO This most definitely needs a lock
foreach (var extension in extensions)
{
_extensionCommandProviders.Add(wrapper!);
}
// Load the commands from the providers in parallel
var loadTasks = wrappers.Select(LoadCommandsWithTimeoutAsync);
var commandSets = (await Task.WhenAll(loadTasks)).Where(results => results != null).Select(r => r!).ToList();
lock (TopLevelCommands)
{
foreach (var commands in commandSets)
Logger.LogDebug($"Starting {extension.PackageFullName}");
try
{
foreach (var c in commands)
{
TopLevelCommands.Add(c);
}
// start it ...
await extension.StartExtensionAsync();
// ... and fetch the command provider from it.
CommandProviderWrapper wrapper = new(extension, _taskScheduler);
_extensionCommandProviders.Add(wrapper);
await LoadTopLevelCommandsFromProvider(wrapper);
}
catch (Exception ex)
{
Logger.LogError(ex.ToString());
}
}
timer.Stop();
Logger.LogDebug($"Loading extensions took {timer.ElapsedMilliseconds} ms");
}
private async Task<CommandProviderWrapper?> StartExtensionWithTimeoutAsync(IExtensionWrapper extension)
{
Logger.LogDebug($"Starting {extension.PackageFullName}");
try
{
await extension.StartExtensionAsync().WaitAsync(TimeSpan.FromSeconds(10));
return new CommandProviderWrapper(extension, _taskScheduler);
}
catch (Exception ex)
{
Logger.LogError($"Failed to start extension {extension.PackageFullName}: {ex}");
return null; // Return null for failed extensions
}
}
private async Task<IEnumerable<TopLevelViewModel>?> LoadCommandsWithTimeoutAsync(CommandProviderWrapper wrapper)
{
try
{
return await LoadTopLevelCommandsFromProvider(wrapper!).WaitAsync(TimeSpan.FromSeconds(10));
}
catch (TimeoutException)
{
Logger.LogError($"Loading commands from {wrapper!.ExtensionHost?.Extension?.PackageFullName} timed out");
}
catch (Exception ex)
{
Logger.LogError($"Failed to load commands for extension {wrapper!.ExtensionHost?.Extension?.PackageFullName}: {ex}");
}
return null;
}
private void ExtensionService_OnExtensionRemoved(IExtensionService sender, IEnumerable<IExtensionWrapper> extensions)

View File

@@ -73,12 +73,26 @@ public partial class App : Application
/// Invoked when the application is launched.
/// </summary>
/// <param name="args">Details about the launch request and process.</param>
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
AppWindow = new MainWindow();
var activatedEventArgs = Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().GetActivatedEventArgs();
((MainWindow)AppWindow).HandleLaunch(activatedEventArgs);
var cmdArgs = Environment.GetCommandLineArgs();
var runFromPT = false;
foreach (var arg in cmdArgs)
{
if (arg == "RunFromPT")
{
runFromPT = true;
break;
}
}
if (!runFromPT)
{
AppWindow.Activate();
}
}
/// <summary>

View File

@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Diagnostics.Tracing;
using Microsoft.CommandPalette.Extensions;
using Microsoft.PowerToys.Telemetry;
using Microsoft.PowerToys.Telemetry.Events;
@@ -12,9 +13,4 @@ namespace Microsoft.CmdPal.UI.Events;
public class BeginInvoke : EventBase, IEvent
{
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
public BeginInvoke()
{
EventName = "CmdPal_BeginInvoke";
}
}

View File

@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Diagnostics.Tracing;
using Microsoft.CommandPalette.Extensions;
using Microsoft.PowerToys.Telemetry;
using Microsoft.PowerToys.Telemetry.Events;
@@ -12,9 +13,4 @@ namespace Microsoft.CmdPal.UI.Events;
public class ColdLaunch : EventBase, IEvent
{
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
public ColdLaunch()
{
EventName = "CmdPal_ColdLaunch";
}
}

View File

@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Diagnostics.Tracing;
using Microsoft.CommandPalette.Extensions;
using Microsoft.PowerToys.Telemetry;
using Microsoft.PowerToys.Telemetry.Events;
@@ -16,8 +17,6 @@ public class OpenPage : EventBase, IEvent
public OpenPage(int pageDepth)
{
PageDepth = pageDepth;
EventName = "CmdPal_OpenPage";
}
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;

View File

@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Diagnostics.Tracing;
using Microsoft.CommandPalette.Extensions;
using Microsoft.PowerToys.Telemetry;
using Microsoft.PowerToys.Telemetry.Events;
@@ -12,9 +13,4 @@ namespace Microsoft.CmdPal.UI.Events;
public class ReactivateInstance : EventBase, IEvent
{
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
public ReactivateInstance()
{
EventName = "CmdPal_ReactivateInstance";
}
}

View File

@@ -124,12 +124,14 @@ public sealed partial class ListPage : Page,
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "VS is too aggressive at pruning methods bound in XAML")]
private void ItemsList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var vm = ViewModel;
var li = ItemsList.SelectedItem as ListItemViewModel;
_ = Task.Run(() =>
if (ItemsList.SelectedItem is ListItemViewModel item)
{
vm?.UpdateSelectedItemCommand.Execute(li);
});
var vm = ViewModel;
_ = Task.Run(() =>
{
vm?.UpdateSelectedItemCommand.Execute(item);
});
}
// There's mysterious behavior here, where the selection seemingly
// changes to _nothing_ when we're backspacing to a single character.

View File

@@ -1,4 +1,4 @@
<winuiex:WindowEx
<Window
x:Class="Microsoft.CmdPal.UI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@@ -6,13 +6,8 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:pages="using:Microsoft.CmdPal.UI.Pages"
xmlns:viewmodels="using:Microsoft.CmdPal.UI.ViewModels"
xmlns:winuiex="using:WinUIEx"
Width="800"
Height="480"
MinWidth="320"
MinHeight="240"
Activated="MainWindow_Activated"
Closed="MainWindow_Closed"
mc:Ignorable="d">
<pages:ShellPage x:Name="RootShellPage" />
</winuiex:WindowEx>
</Window>

View File

@@ -19,25 +19,21 @@ using Microsoft.UI.Composition.SystemBackdrops;
using Microsoft.UI.Input;
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using Microsoft.Windows.AppLifecycle;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Graphics;
using Windows.UI;
using Windows.UI.WindowManagement;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.Graphics.Dwm;
using Windows.Win32.UI.Input.KeyboardAndMouse;
using Windows.Win32.UI.Shell;
using Windows.Win32.UI.WindowsAndMessaging;
using WinRT;
using WinUIEx;
using RS_ = Microsoft.CmdPal.UI.Helpers.ResourceLoaderInstance;
namespace Microsoft.CmdPal.UI;
public sealed partial class MainWindow : WindowEx,
public sealed partial class MainWindow : Window,
IRecipient<DismissMessage>,
IRecipient<ShowWindowMessage>,
IRecipient<HideWindowMessage>,
@@ -86,6 +82,7 @@ public sealed partial class MainWindow : WindowEx,
this.SetIcon();
AppWindow.Title = RS_.GetString("AppName");
AppWindow.Resize(new SizeInt32 { Width = 1000, Height = 620 });
PositionCentered();
SetAcrylic();
@@ -235,16 +232,6 @@ public sealed partial class MainWindow : WindowEx,
PositionCentered(display);
PInvoke.ShowWindow(hwnd, SHOW_WINDOW_CMD.SW_SHOW);
// instead of showing the window, uncloak it from DWM
// This will make it visible to the user, without the animation or frames for
// loading XAML with composition
unsafe
{
BOOL value = false;
PInvoke.DwmSetWindowAttribute(_hwnd, DWMWINDOWATTRIBUTE.DWMWA_CLOAK, &value, (uint)sizeof(BOOL));
}
PInvoke.SetForegroundWindow(hwnd);
PInvoke.SetActiveWindow(hwnd);
}
@@ -302,7 +289,7 @@ public sealed partial class MainWindow : WindowEx,
ShowHwnd(message.Hwnd, settings.SummonOn);
}
public void Receive(HideWindowMessage message) => HideWindow();
public void Receive(HideWindowMessage message) => PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_HIDE);
public void Receive(QuitMessage message) =>
@@ -310,21 +297,7 @@ public sealed partial class MainWindow : WindowEx,
DispatcherQueue.TryEnqueue(() => Close());
public void Receive(DismissMessage message) =>
HideWindow();
private void HideWindow()
{
// Hide our window
// Instead of hiding the window, cloak it from DWM
// This will make it invisible to the user, such that we can show it again
// by uncloaking it, which avoids an unnecessary "flicker in" that XAML does
unsafe
{
BOOL value = true;
PInvoke.DwmSetWindowAttribute(_hwnd, DWMWINDOWATTRIBUTE.DWMWA_CLOAK, &value, (uint)sizeof(BOOL));
}
}
PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_HIDE);
internal void MainWindow_Closed(object sender, WindowEventArgs args)
{
@@ -413,9 +386,7 @@ public sealed partial class MainWindow : WindowEx,
return;
}
// This will DWM cloak our window:
HideWindow();
PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_HIDE);
PowerToysTelemetry.Log.WriteEvent(new CmdPalDismissedOnLostFocus());
}
@@ -425,40 +396,6 @@ public sealed partial class MainWindow : WindowEx,
}
}
public void HandleLaunch(AppActivationArguments? activatedEventArgs)
{
if (activatedEventArgs == null)
{
Summon(string.Empty);
return;
}
if (activatedEventArgs.Kind == Microsoft.Windows.AppLifecycle.ExtendedActivationKind.Protocol)
{
if (activatedEventArgs.Data is IProtocolActivatedEventArgs protocolArgs)
{
if (protocolArgs.Uri.ToString() is string uri)
{
// was the URI "x-cmdpal://background" ?
if (uri.StartsWith("x-cmdpal://background", StringComparison.OrdinalIgnoreCase))
{
// we're running, we don't want to activate our window. bail
return;
}
else if (uri.StartsWith("x-cmdpal://settings", StringComparison.OrdinalIgnoreCase))
{
WeakReferenceMessenger.Default.Send<OpenSettingsMessage>(new());
return;
}
}
return;
}
}
Activate();
}
public void Summon(string commandId) =>
// The actual showing and hiding of the window will be done by the
@@ -467,6 +404,11 @@ public sealed partial class MainWindow : WindowEx,
// know till the message is being handled.
WeakReferenceMessenger.Default.Send<HotkeySummonMessage>(new(commandId, _hwnd));
#pragma warning disable SA1310 // Field names should not contain underscore
private const uint DOT_KEY = 0xBE;
private const uint WM_HOTKEY = 0x0312;
#pragma warning restore SA1310 // Field names should not contain underscore
private void UnregisterHotkeys()
{
_keyboardListener.ClearHotkeys();
@@ -537,24 +479,10 @@ public sealed partial class MainWindow : WindowEx,
var isRootHotkey = string.IsNullOrEmpty(commandId);
PowerToysTelemetry.Log.WriteEvent(new CmdPalHotkeySummoned(isRootHotkey));
var isVisible = this.Visible;
unsafe
{
// We need to check if our window is cloaked or not. A cloaked window is still
// technically visible, because SHOW/HIDE != iconic (minimized) != cloaked
// (these are all separate states)
long attr = 0;
PInvoke.DwmGetWindowAttribute(_hwnd, DWMWINDOWATTRIBUTE.DWMWA_CLOAKED, &attr, sizeof(long));
if (attr == 1 /* DWM_CLOAKED_APP */)
{
isVisible = false;
}
}
// Note to future us: the wParam will have the index of the hotkey we registered.
// We can use that in the future to differentiate the hotkeys we've pressed
// so that we can bind hotkeys to individual commands
if (!isVisible || !isRootHotkey)
if (!this.Visible || !isRootHotkey)
{
Activate();
@@ -562,16 +490,7 @@ public sealed partial class MainWindow : WindowEx,
}
else if (isRootHotkey)
{
// If there's a debugger attached...
if (System.Diagnostics.Debugger.IsAttached)
{
// ... then manually hide our window. When debugged, we won't get the cool cloaking,
// but that's the price to pay for having the HWND not light-dismiss while we're debugging.
PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_HIDE);
return;
}
HideWindow();
PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_HIDE);
}
}
@@ -583,10 +502,7 @@ public sealed partial class MainWindow : WindowEx,
{
switch (uMsg)
{
// Prevent the window from maximizing when double-clicking the title bar area
case PInvoke.WM_NCLBUTTONDBLCLK:
return (LRESULT)IntPtr.Zero;
case PInvoke.WM_HOTKEY:
case WM_HOTKEY:
{
var hotkeyIndex = (int)wParam.Value;
if (hotkeyIndex < _hotkeys.Count)
@@ -602,6 +518,22 @@ public sealed partial class MainWindow : WindowEx,
var hotkey = _hotkeys[hotkeyIndex];
HandleSummon(hotkey.CommandId);
// var isRootHotkey = string.IsNullOrEmpty(hotkey.CommandId);
// // Note to future us: the wParam will have the index of the hotkey we registered.
// // We can use that in the future to differentiate the hotkeys we've pressed
// // so that we can bind hotkeys to individual commands
// if (!this.Visible || !isRootHotkey)
// {
// Activate();
// Summon(hotkey.CommandId);
// }
// else if (isRootHotkey)
// {
// PInvoke.ShowWindow(hwnd, SHOW_WINDOW_CMD.SW_HIDE);
// }
}
return (LRESULT)IntPtr.Zero;

View File

@@ -66,7 +66,7 @@
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />
<PackageReference Include="Microsoft.WindowsAppSDK" />
<PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" />
<PackageReference Include="WinUIEx" />
<PackageReference Include="Microsoft.Windows.CsWin32">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>

View File

@@ -25,8 +25,6 @@ SHCreateStreamOnFileEx
CoAllowSetForegroundWindow
SHCreateStreamOnFileEx
SHLoadIndirectString
WM_HOTKEY
WM_NCLBUTTONDBLCLK
Shell_NotifyIcon
LoadIcon
@@ -38,8 +36,3 @@ ExtractIconEx
WM_RBUTTONUP
WM_LBUTTONUP
WM_LBUTTONDBLCLK
MessageBox
DwmGetWindowAttribute
DwmSetWindowAttribute
DWM_CLOAKED_APP

View File

@@ -70,13 +70,6 @@
DisplayName="ms-resource:StartupTaskNameDev" />
</uap5:Extension>
<uap:Extension Category="windows.protocol">
<uap:Protocol Name="x-cmdpal">
<uap:Logo>Assets\StoreLogo.png</uap:Logo>
<uap:DisplayName>Command Palette Dev URI scheme</uap:DisplayName>
</uap:Protocol>
</uap:Extension>
</Extensions>
</Application>

View File

@@ -70,14 +70,6 @@
DisplayName="ms-resource:StartupTaskName" />
</uap5:Extension>
<uap:Extension Category="windows.protocol">
<uap:Protocol Name="x-cmdpal">
<uap:Logo>Assets\StoreLogo.png</uap:Logo>
<uap:DisplayName>Command Palette URI scheme</uap:DisplayName>
</uap:Protocol>
</uap:Extension>
</Extensions>
</Application>

View File

@@ -418,20 +418,18 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page,
{
_ = DispatcherQueue.TryEnqueue(() =>
{
OpenSettings();
// Also hide our details pane about here, if we had one
HideDetails();
if (_settingsWindow == null)
{
_settingsWindow = new SettingsWindow();
}
_settingsWindow.Activate();
});
}
public void OpenSettings()
{
if (_settingsWindow == null)
{
_settingsWindow = new SettingsWindow();
}
_settingsWindow.Activate();
}
public void Receive(ShowDetailsMessage message)
{
// TERRIBLE HACK TODO GH #245

View File

@@ -2,14 +2,10 @@
// 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.Runtime.InteropServices;
using ManagedCommon;
using Microsoft.CmdPal.UI.Events;
using Microsoft.PowerToys.Telemetry;
using Microsoft.Windows.AppLifecycle;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.UI.WindowsAndMessaging;
namespace Microsoft.CmdPal.UI;
@@ -34,33 +30,7 @@ internal sealed class Program
return 0;
}
try
{
Logger.InitializeLogger("\\CmdPal\\Logs\\");
}
catch (COMException e)
{
// This is unexpected. For the sake of debugging:
// pop a message box
PInvoke.MessageBox(
(HWND)IntPtr.Zero,
$"Failed to initialize the logger. COMException: \r{e.Message}",
"Command Palette",
MESSAGEBOX_STYLE.MB_OK | MESSAGEBOX_STYLE.MB_ICONERROR);
return 0;
}
catch (Exception e2)
{
// This is unexpected. For the sake of debugging:
// pop a message box
PInvoke.MessageBox(
(HWND)IntPtr.Zero,
$"Failed to initialize the logger. Unknown Exception: \r{e2.Message}",
"Command Palette",
MESSAGEBOX_STYLE.MB_OK | MESSAGEBOX_STYLE.MB_ICONERROR);
return 0;
}
Logger.InitializeLogger("\\CmdPal\\Logs\\");
Logger.LogDebug($"Starting at {DateTime.UtcNow}");
PowerToysTelemetry.Log.WriteEvent(new CmdPalProcessStarted());
@@ -109,9 +79,7 @@ internal sealed class Program
if (thisApp.AppWindow is not null and
MainWindow mainWindow)
{
mainWindow.HandleLaunch(args);
// mainWindow.Summon(string.Empty);
mainWindow.Summon(string.Empty);
}
}
}

View File

@@ -2,8 +2,7 @@
"profiles": {
"Microsoft.CmdPal.UI (Package)": {
"commandName": "MsixPackage",
"nativeDebugging": false,
"doNotLaunchApp": false
"nativeDebugging": false
},
"Microsoft.CmdPal.UI (Unpackaged)": {
"commandName": "Project"

View File

@@ -113,24 +113,7 @@
Visibility="{x:Bind ViewModel.HasSettings}" />
<Frame x:Name="SettingsFrame" Visibility="{x:Bind ViewModel.HasSettings}">
<controls:SwitchPresenter
HorizontalAlignment="Stretch"
TargetType="x:Boolean"
Value="{x:Bind ViewModel.LoadingSettings, Mode=OneWay}">
<controls:Case Value="True">
<ProgressRing
Width="36"
Height="36"
HorizontalAlignment="Center"
VerticalAlignment="Center"
IsIndeterminate="True" />
</controls:Case>
<controls:Case Value="False">
<cmdpalUI:ContentPage ViewModel="{x:Bind ViewModel.SettingsPage, Mode=OneWay}" />
</controls:Case>
</controls:SwitchPresenter>
<cmdpalUI:ContentPage ViewModel="{x:Bind ViewModel.SettingsPage, Mode=OneWay}" />
</Frame>
<TextBlock

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" ?>
<winuiex:WindowEx
<Window
x:Class="Microsoft.CmdPal.UI.Settings.SettingsWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@@ -7,18 +7,13 @@
xmlns:local="using:Microsoft.CmdPal.UI.Settings"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="using:CommunityToolkit.WinUI"
xmlns:winuiex="using:WinUIEx"
Title="SettingsWindow"
Width="1280"
Height="720"
MinWidth="480"
MinHeight="480"
Activated="Window_Activated"
Closed="Window_Closed"
mc:Ignorable="d">
<winuiex:WindowEx.SystemBackdrop>
<Window.SystemBackdrop>
<MicaBackdrop />
</winuiex:WindowEx.SystemBackdrop>
</Window.SystemBackdrop>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
@@ -42,10 +37,10 @@
Height="16"
Source="ms-appx:///Assets/icon.svg" />
<TextBlock
x:Uid="CmdPalSettingsHeader"
Margin="12,0,0,0"
VerticalAlignment="Center"
Style="{StaticResource CaptionTextBlockStyle}" />
Style="{StaticResource CaptionTextBlockStyle}"
Text="Command Palette Settings" />
</StackPanel>
<NavigationView
x:Name="NavView"
@@ -105,4 +100,4 @@
</Grid>
</NavigationView>
</Grid>
</winuiex:WindowEx>
</Window>

View File

@@ -11,12 +11,11 @@ using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Windows.Graphics;
using WinUIEx;
using RS_ = Microsoft.CmdPal.UI.Helpers.ResourceLoaderInstance;
namespace Microsoft.CmdPal.UI.Settings;
public sealed partial class SettingsWindow : WindowEx,
public sealed partial class SettingsWindow : Window,
IRecipient<NavigateToExtensionSettingsMessage>,
IRecipient<QuitMessage>
{
@@ -71,6 +70,7 @@ public sealed partial class SettingsWindow : WindowEx,
private void PositionCentered()
{
AppWindow.Resize(new SizeInt32 { Width = 1280, Height = 720 });
var displayArea = DisplayArea.GetFromWindowId(AppWindow.Id, DisplayAreaFallback.Nearest);
if (displayArea is not null)
{

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" ?>
<winuiex:WindowEx
<Window
x:Class="Microsoft.CmdPal.UI.ToastWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@@ -7,18 +7,17 @@
xmlns:local="using:Microsoft.CmdPal.UI"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="using:CommunityToolkit.WinUI"
xmlns:winuiex="using:WinUIEx"
Title="Command Palette Toast"
mc:Ignorable="d">
<winuiex:WindowEx.SystemBackdrop>
<Window.SystemBackdrop>
<DesktopAcrylicBackdrop />
</winuiex:WindowEx.SystemBackdrop>
</Window.SystemBackdrop>
<Grid x:Name="ToastGrid">
<!-- This padding is used to calculate the dimensions of the ToastWindow -->
<TextBlock
x:Name="ToastText"
Padding="12,12,24,20"
Padding="16,16,36,24"
Text="{x:Bind ViewModel.ToastMessage, Mode=OneWay}"
TextAlignment="Center" />
</Grid>
</winuiex:WindowEx>
</Window>

View File

@@ -17,12 +17,11 @@ using Windows.Win32.Foundation;
using Windows.Win32.Graphics.Gdi;
using Windows.Win32.UI.HiDpi;
using Windows.Win32.UI.WindowsAndMessaging;
using WinUIEx;
using RS_ = Microsoft.CmdPal.UI.Helpers.ResourceLoaderInstance;
namespace Microsoft.CmdPal.UI;
public sealed partial class ToastWindow : WindowEx,
public sealed partial class ToastWindow : Window,
IRecipient<QuitMessage>
{
private readonly HWND _hwnd;
@@ -65,7 +64,19 @@ public sealed partial class ToastWindow : WindowEx,
private void PositionCentered()
{
this.SetWindowSize(ToastText.ActualWidth, ToastText.ActualHeight);
var intSize = new SizeInt32
{
Width = Convert.ToInt32(ToastText.ActualWidth),
Height = Convert.ToInt32(ToastText.ActualHeight),
};
var scaleAdjustment = GetScaleFactor(_hwnd);
var scaled = new SizeInt32
{
Width = (int)Math.Round(intSize.Width * scaleAdjustment),
Height = (int)Math.Round(intSize.Height * scaleAdjustment),
};
AppWindow.Resize(scaled);
var displayArea = DisplayArea.GetFromWindowId(AppWindow.Id, DisplayAreaFallback.Nearest);
if (displayArea is not null)
@@ -75,7 +86,7 @@ public sealed partial class ToastWindow : WindowEx,
var monitorHeight = displayArea.WorkArea.Height;
var windowHeight = AppWindow.Size.Height;
centeredPosition.Y = monitorHeight - (windowHeight + 8); // Align with other shell toasts, like the volume indicator.
centeredPosition.Y = monitorHeight - (windowHeight * 2);
AppWindow.Move(centeredPosition);
}
}

View File

@@ -9,7 +9,7 @@ By default, CmdPal is bound to <kbd>Win+Alt+Space</kbd>.
The fastest way to get started is just to run the "Create extension" command in the palette itself. That'll prompt you for a project name and a Display Name, and where you want to place your project. Then just open the `sln` it produces. You should be ready to go 🙂.
The official API documentation can be found [on this docs site](https://learn.microsoft.com/windows/powertoys/command-palette/extensibility-overview).
The official API documentation can be found [on this docs site](TODO! Add docs link when we have one)
We've also got samples, so that you can see how the APIs in-action.

View File

@@ -12,7 +12,7 @@ using Microsoft.CmdPal.Ext.Apps.Utils;
namespace Microsoft.CmdPal.Ext.Apps;
public sealed partial class AppCache : IDisposable
public sealed class AppCache : IDisposable
{
private Win32ProgramFileSystemWatchers _win32ProgramRepositoryHelper;

View File

@@ -2,10 +2,8 @@
// 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.Threading.Tasks;
using ManagedCommon;
using Microsoft.CmdPal.Ext.Apps.Programs;
using Microsoft.CmdPal.Ext.Apps.Properties;
using Microsoft.CommandPalette.Extensions.Toolkit;
@@ -35,9 +33,8 @@ internal sealed partial class AppCommand : InvokableCommand
{
appManager.ActivateApplication(aumid, /*queryArguments*/ string.Empty, noFlags, out var unusedPid);
}
catch (System.Exception ex)
catch (System.Exception)
{
Logger.LogError(ex.Message);
}
}).ConfigureAwait(false);
}
@@ -49,14 +46,7 @@ internal sealed partial class AppCommand : InvokableCommand
// const ActivateOptions noFlags = ActivateOptions.None;
await Task.Run(() =>
{
try
{
Process.Start(new ProcessStartInfo(path) { UseShellExecute = true });
}
catch (System.Exception ex)
{
Logger.LogError(ex.Message);
}
Process.Start(new ProcessStartInfo(path) { UseShellExecute = true });
});
}

View File

@@ -5,7 +5,6 @@
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using ManagedCommon;
using Microsoft.CmdPal.Ext.Apps.Properties;
using Microsoft.CommandPalette.Extensions.Toolkit;
@@ -39,9 +38,9 @@ internal sealed partial class OpenInConsoleCommand : InvokableCommand
Process.Start(processStartInfo);
}
catch (Exception ex)
catch (Exception)
{
Logger.LogError(ex.Message);
// Log.Exception($"Failed to open {Name} in console, {e.Message}", e, GetType());
}
});
}

View File

@@ -4,7 +4,6 @@
using System;
using System.IO;
using ManagedCommon;
using Windows.Foundation.Metadata;
using Package = Windows.ApplicationModel.Package;

View File

@@ -319,7 +319,7 @@ public static class ReparsePoint
public static AppExecutionAliasMetadata FromPersistedRepresentationIntPtr(IntPtr reparseDataBufferPtr, AppExecutionAliasReparseTagBufferLayoutVersion version)
{
var dataOffset = Marshal.SizeOf<AppExecutionAliasReparseTagHeader>();
var dataOffset = Marshal.SizeOf(typeof(AppExecutionAliasReparseTagHeader));
var dataBufferPtr = reparseDataBufferPtr + dataOffset;
string? packageFullName = null;

View File

@@ -7,9 +7,7 @@ using System.Collections.Generic;
using System.IO.Abstractions;
using System.Linq;
using System.Xml.Linq;
using ManagedCommon;
using Microsoft.CmdPal.Ext.Apps.Utils;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.System.Com;
@@ -133,9 +131,8 @@ public partial class UWP
u = new UWP(p);
u.InitializeAppInfo(p.InstalledLocation);
}
catch (Exception ex)
catch (Exception )
{
Logger.LogError(ex.Message);
return Array.Empty<UWPApplication>();
}
@@ -164,9 +161,8 @@ public partial class UWP
var path = p.InstalledLocation;
return !f && !string.IsNullOrEmpty(path);
}
catch (Exception ex)
catch (Exception )
{
Logger.LogError(ex.Message);
return false;
}
});

View File

@@ -8,14 +8,12 @@ using System.IO.Abstractions;
using System.Linq;
using System.Text;
using System.Xml;
using ManagedCommon;
using Microsoft.CmdPal.Ext.Apps.Commands;
using Microsoft.CmdPal.Ext.Apps.Properties;
using Microsoft.CmdPal.Ext.Apps.Utils;
using Microsoft.CommandPalette.Extensions.Toolkit;
using static Microsoft.CmdPal.Ext.Apps.Utils.Native;
using PackageVersion = Microsoft.CmdPal.Ext.Apps.Programs.UWP.PackageVersion;
using Theme = Microsoft.CmdPal.Ext.Apps.Utils.Theme;
namespace Microsoft.CmdPal.Ext.Apps.Programs;
@@ -156,9 +154,8 @@ public class UWPApplication : IProgram
return true;
}
}
catch (Exception ex)
catch (Exception)
{
Logger.LogError(ex.Message);
}
}
}

View File

@@ -15,7 +15,6 @@ using System.Security;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Input;
using ManagedCommon;
using Microsoft.CmdPal.Ext.Apps.Commands;
using Microsoft.CmdPal.Ext.Apps.Properties;
using Microsoft.CmdPal.Ext.Apps.Utils;
@@ -240,12 +239,10 @@ public class Win32Program : IProgram
}
catch (Exception e) when (e is SecurityException || e is UnauthorizedAccessException)
{
Logger.LogError(e.Message);
return InvalidProgram;
}
catch (Exception e)
catch (Exception)
{
Logger.LogError(e.Message);
return InvalidProgram;
}
}
@@ -320,13 +317,11 @@ public class Win32Program : IProgram
}
catch (Exception e) when (e is SecurityException || e is UnauthorizedAccessException)
{
Logger.LogError(e.Message);
return InvalidProgram;
}
}
catch (Exception e)
catch (Exception)
{
Logger.LogError(e.Message);
return InvalidProgram;
}
}
@@ -379,17 +374,15 @@ public class Win32Program : IProgram
return program;
}
catch (System.IO.FileLoadException e)
catch (System.IO.FileLoadException)
{
Logger.LogError(e.Message);
return InvalidProgram;
}
// Only do a catch all in production. This is so make developer aware of any unhandled exception and add the exception handling in.
// Error caused likely due to trying to get the description of the program
catch (Exception e)
catch (Exception)
{
Logger.LogError(e.Message);
return InvalidProgram;
}
}
@@ -409,17 +402,14 @@ public class Win32Program : IProgram
}
catch (Exception e) when (e is SecurityException || e is UnauthorizedAccessException)
{
Logger.LogError(e.Message);
return InvalidProgram;
}
catch (FileNotFoundException e)
catch (FileNotFoundException)
{
Logger.LogError(e.Message);
return InvalidProgram;
}
catch (Exception e)
catch (Exception)
{
Logger.LogError(e.Message);
return InvalidProgram;
}
}
@@ -525,19 +515,16 @@ public class Win32Program : IProgram
{
files.AddRange(Directory.EnumerateFiles(currentDirectory, $"*.{suffix}", SearchOption.TopDirectoryOnly));
}
catch (DirectoryNotFoundException e)
catch (DirectoryNotFoundException)
{
Logger.LogError(e.Message);
}
}
}
catch (Exception e) when (e is SecurityException || e is UnauthorizedAccessException)
{
Logger.LogError(e.Message);
}
catch (Exception e)
catch (Exception)
{
Logger.LogError(e.Message);
}
try
@@ -561,11 +548,9 @@ public class Win32Program : IProgram
}
catch (Exception e) when (e is SecurityException || e is UnauthorizedAccessException)
{
Logger.LogError(e.Message);
}
catch (Exception e)
catch (Exception)
{
Logger.LogError(e.Message);
}
}
while (folderQueue.Count > 0);
@@ -697,7 +682,6 @@ public class Win32Program : IProgram
}
catch (Exception e) when (e is SecurityException || e is UnauthorizedAccessException)
{
Logger.LogError(e.Message);
return string.Empty;
}
}
@@ -785,9 +769,8 @@ public class Win32Program : IProgram
icoPath = ExpandEnvironmentVariables(redirectionPath);
return true;
}
catch (IOException e)
catch (IOException)
{
Logger.LogError(e.Message);
}
icoPath = null;
@@ -856,9 +839,8 @@ public class Win32Program : IProgram
return DeduplicatePrograms(programs.Concat(runCommandPrograms).Where(program => program?.Valid == true));
}
catch (Exception e)
catch (Exception)
{
Logger.LogError(e.Message);
return Array.Empty<Win32Program>();
}
}

View File

@@ -8,7 +8,7 @@ using System.IO;
namespace Microsoft.CmdPal.Ext.Apps.Storage;
// File System Watcher Wrapper class which implements the IFileSystemWatcherWrapper interface
public sealed partial class FileSystemWatcherWrapper : FileSystemWatcher, IFileSystemWatcherWrapper
public sealed class FileSystemWatcherWrapper : FileSystemWatcher, IFileSystemWatcherWrapper
{
public FileSystemWatcherWrapper()
{

View File

@@ -7,7 +7,6 @@ using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using ManagedCommon;
namespace Microsoft.CmdPal.Ext.Apps.Storage;
@@ -38,9 +37,8 @@ public class ListRepository<T> : IRepository<T>, IEnumerable<T>
_items = new ConcurrentDictionary<int, T>(list.ToDictionary(i => i.GetHashCode()));
#pragma warning restore CS8602 // Dereference of a possibly null reference.
}
catch (ArgumentException ex)
catch (ArgumentException)
{
Logger.LogInfo(ex.Message);
}
}

View File

@@ -4,8 +4,8 @@
using System;
using System.Linq;
using ManagedCommon;
using Microsoft.CmdPal.Ext.Apps.Programs;
using Microsoft.CmdPal.Ext.Apps.Storage;
using Microsoft.CmdPal.Ext.Apps.Utils;
using Windows.ApplicationModel;
@@ -15,7 +15,7 @@ namespace Microsoft.CmdPal.Ext.Apps.Storage;
/// A repository for storing packaged applications such as UWP apps or appx packaged desktop apps.
/// This repository will also monitor for changes to the PackageCatalog and update the repository accordingly
/// </summary>
internal sealed partial class PackageRepository : ListRepository<UWPApplication>, IProgramRepository
internal sealed class PackageRepository : ListRepository<UWPApplication>, IProgramRepository
{
private readonly IPackageCatalog _packageCatalog;
@@ -93,9 +93,8 @@ internal sealed partial class PackageRepository : ListRepository<UWPApplication>
// InitializeAppInfo will throw if there is no AppxManifest.xml for the package.
// Note there are sometimes multiple packages per product and this doesn't necessarily mean that we haven't found the app.
// eg. "Could not find file 'C:\\Program Files\\WindowsApps\\Microsoft.WindowsTerminalPreview_2020.616.45.0_neutral_~_8wekyb3d8bbwe\\AppxManifest.xml'."
catch (System.IO.FileNotFoundException ex)
catch (System.IO.FileNotFoundException)
{
Logger.LogError(ex.Message);
}
}

View File

@@ -6,11 +6,10 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ManagedCommon;
namespace Microsoft.CmdPal.Ext.Apps.Storage;
internal sealed partial class Win32ProgramFileSystemWatchers : IDisposable
internal sealed class Win32ProgramFileSystemWatchers : IDisposable
{
public string[] PathsToWatch { get; set; }
@@ -48,9 +47,8 @@ internal sealed partial class Win32ProgramFileSystemWatchers : IDisposable
{
Directory.GetFiles(path);
}
catch (Exception e)
catch (Exception)
{
Logger.LogError(e.Message);
invalidPaths.Add(path);
}
}

View File

@@ -9,13 +9,12 @@ using System.Collections.ObjectModel;
using System.IO;
using System.IO.Abstractions;
using System.Threading.Tasks;
using ManagedCommon;
using Microsoft.CmdPal.Ext.Apps.Programs;
using Win32Program = Microsoft.CmdPal.Ext.Apps.Programs.Win32Program;
namespace Microsoft.CmdPal.Ext.Apps.Storage;
internal sealed partial class Win32ProgramRepository : ListRepository<Programs.Win32Program>, IProgramRepository
internal sealed class Win32ProgramRepository : ListRepository<Programs.Win32Program>, IProgramRepository
{
private static readonly IFileSystem FileSystem = new FileSystem();
private static readonly IPath Path = FileSystem.Path;
@@ -133,9 +132,8 @@ internal sealed partial class Win32ProgramRepository : ListRepository<Programs.W
oldApp = Win32Program.GetAppFromPath(oldPath);
}
}
catch (Exception ex)
catch (Exception)
{
Logger.LogError(ex.Message);
}
// To remove the old app which has been renamed and to add the new application.
@@ -194,9 +192,8 @@ internal sealed partial class Win32ProgramRepository : ListRepository<Programs.W
app = Programs.Win32Program.GetAppFromPath(path);
}
}
catch (Exception ex)
catch (Exception)
{
Logger.LogError(ex.Message);
}
if (app != null)

View File

@@ -6,7 +6,6 @@ using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using ManagedCommon;
namespace Microsoft.CmdPal.Ext.Apps.Utils;
@@ -139,9 +138,9 @@ public class ShellLinkHelper : IShellLinkHelper
{
((IPersistFile)link).Load(path, STGM_READ);
}
catch (System.IO.FileNotFoundException ex)
catch (System.IO.FileNotFoundException)
{
Logger.LogError(ex.Message);
// Log.Exception("Path could not be retrieved", ex, GetType(), path);
return string.Empty;
}
@@ -164,9 +163,9 @@ public class ShellLinkHelper : IShellLinkHelper
((IShellLinkW)link).GetDescription(buffer, MAX_PATH);
Description = buffer.ToString();
}
catch (Exception ex)
catch (Exception)
{
Logger.LogError(ex.Message);
// Log.Exception($"Failed to fetch description for {target}, {e.Message}", e, GetType());
Description = string.Empty;
}

View File

@@ -9,7 +9,6 @@ using System.Linq;
using System.Text;
using System.Text.Json.Nodes;
using System.Text.RegularExpressions;
using ManagedCommon;
using Microsoft.CmdPal.Ext.Bookmarks.Properties;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Windows.System;
@@ -102,7 +101,7 @@ internal sealed partial class BookmarkPlaceholderForm : FormContent
}
catch (Exception ex)
{
Logger.LogError(ex.Message);
System.Diagnostics.Debug.WriteLine($"Error launching URL: {ex.Message}");
}
return CommandResult.GoHome();

View File

@@ -7,7 +7,6 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using ManagedCommon;
using Microsoft.CmdPal.Ext.Bookmarks.Properties;
using Microsoft.CmdPal.Ext.Indexer;
using Microsoft.CommandPalette.Extensions;
@@ -98,7 +97,8 @@ public partial class BookmarksCommandProvider : CommandProvider
}
catch (Exception ex)
{
Logger.LogError(ex.Message);
// debug log error
Debug.WriteLine($"Error loading commands: {ex.Message}");
}
if (_bookmarks == null)

View File

@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System;
using ManagedCommon;
using Microsoft.CmdPal.Ext.Bookmarks.Properties;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
@@ -35,7 +34,7 @@ internal sealed partial class OpenInTerminalCommand : InvokableCommand
}
catch (Exception ex)
{
Logger.LogError(ex.Message);
System.Diagnostics.Debug.WriteLine($"Error launching Windows Terminal: {ex.Message}");
}
return CommandResult.Dismiss();

View File

@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System;
using ManagedCommon;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Windows.System;
@@ -45,7 +44,7 @@ public partial class UrlCommand : InvokableCommand
}
catch (Exception ex)
{
Logger.LogError(ex.Message);
System.Diagnostics.Debug.WriteLine($"Error launching URL: {ex.Message}");
}
return CommandResult.Dismiss();
@@ -88,9 +87,9 @@ public partial class UrlCommand : InvokableCommand
return faviconUrl;
}
}
catch (UriFormatException ex)
catch (UriFormatException)
{
Logger.LogError(ex.Message);
// return "🔗";
}
return "🔗";

View File

@@ -2,10 +2,7 @@
// 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.Globalization;
using System.IO;
using System.Text;
using Microsoft.CmdPal.Ext.Indexer.Data;
using Microsoft.CmdPal.Ext.Indexer.Properties;
using Microsoft.CommandPalette.Extensions.Toolkit;
@@ -13,14 +10,8 @@ using Windows.Storage.Streams;
namespace Microsoft.CmdPal.Ext.Indexer;
internal sealed partial class FallbackOpenFileItem : FallbackCommandItem, System.IDisposable
internal sealed partial class FallbackOpenFileItem : FallbackCommandItem
{
private readonly CompositeFormat fallbackItemSearchPageTitleCompositeFormat = CompositeFormat.Parse(Resources.Indexer_fallback_searchPage_title);
private readonly SearchEngine _searchEngine = new();
private uint _queryCookie = 10;
public FallbackOpenFileItem()
: base(new NoOpCommand(), Resources.Indexer_Find_Path_fallback_display_title)
{
@@ -30,20 +21,8 @@ internal sealed partial class FallbackOpenFileItem : FallbackCommandItem, System
public override void UpdateQuery(string query)
{
if (string.IsNullOrWhiteSpace(query))
{
Command = new NoOpCommand();
Title = string.Empty;
Subtitle = string.Empty;
Icon = null;
MoreCommands = null;
return;
}
if (Path.Exists(query))
{
// Exit 1: The query is a direct path to a file. Great! Return it.
var item = new IndexerItem() { FullPath = query, FileName = Path.GetFileName(query) };
var listItemForUs = new IndexerListItem(item, IncludeBrowseCommand.AsDefault);
Command = listItemForUs.Command;
@@ -64,65 +43,12 @@ internal sealed partial class FallbackOpenFileItem : FallbackCommandItem, System
catch
{
}
return;
}
else
{
_queryCookie++;
try
{
_searchEngine.Query(query, _queryCookie);
var results = _searchEngine.FetchItems(0, 20, _queryCookie, out var _);
if (results.Count == 0 || ((results[0] as IndexerListItem) == null))
{
// Exit 2: We searched for the file, and found nothing. Oh well.
// Hide ourselves.
Title = string.Empty;
Subtitle = string.Empty;
Command = new NoOpCommand();
return;
}
if (results.Count == 1)
{
// Exit 3: We searched for the file, and found exactly one thing. Awesome!
// Return it.
Title = results[0].Title;
Subtitle = results[0].Subtitle;
Icon = results[0].Icon;
Command = results[0].Command;
MoreCommands = results[0].MoreCommands;
return;
}
// Exit 4: We found more than one result. Make our command take
// us to the file search page, prepopulated with this search.
var indexerPage = new IndexerPage(query, _searchEngine, _queryCookie, results);
Title = string.Format(CultureInfo.CurrentCulture, fallbackItemSearchPageTitleCompositeFormat, query);
Icon = Icons.FileExplorer;
Subtitle = Resources.Indexer_Subtitle;
Command = indexerPage;
return;
}
catch
{
Title = string.Empty;
Subtitle = string.Empty;
Icon = null;
Command = new NoOpCommand();
MoreCommands = null;
}
Title = string.Empty;
Subtitle = string.Empty;
Command = new NoOpCommand();
}
}
public void Dispose()
{
_searchEngine.Dispose();
GC.SuppressFinalize(this);
}
}

View File

@@ -4,22 +4,25 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using ManagedCommon;
using Microsoft.CmdPal.Ext.Indexer.Data;
using Microsoft.CmdPal.Ext.Indexer.Indexer;
using Microsoft.CmdPal.Ext.Indexer.Properties;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Windows.Storage.Streams;
namespace Microsoft.CmdPal.Ext.Indexer;
internal sealed partial class IndexerPage : DynamicListPage, IDisposable
{
private readonly List<IListItem> _indexerListItems = [];
private readonly SearchEngine _searchEngine;
private readonly bool disposeSearchEngine = true;
private uint _queryCookie;
private SearchQuery _searchQuery = new();
private string initialQuery = string.Empty;
private uint _queryCookie = 10;
public IndexerPage()
{
@@ -27,31 +30,16 @@ internal sealed partial class IndexerPage : DynamicListPage, IDisposable
Icon = Icons.FileExplorer;
Name = Resources.Indexer_Title;
PlaceholderText = Resources.Indexer_PlaceholderText;
_searchEngine = new();
_queryCookie = 10;
}
public IndexerPage(string query, SearchEngine searchEngine, uint queryCookie, IList<IListItem> firstPageData)
{
Icon = Icons.FileExplorer;
Name = Resources.Indexer_Title;
_searchEngine = searchEngine;
_queryCookie = queryCookie;
_indexerListItems.AddRange(firstPageData);
initialQuery = query;
SearchText = query;
disposeSearchEngine = false;
}
public override void UpdateSearchText(string oldSearch, string newSearch)
{
if (oldSearch != newSearch && newSearch != initialQuery)
if (oldSearch != newSearch)
{
_ = Task.Run(() =>
{
Query(newSearch);
LoadMore();
initialQuery = string.Empty;
});
}
}
@@ -61,9 +49,7 @@ internal sealed partial class IndexerPage : DynamicListPage, IDisposable
public override void LoadMore()
{
IsLoading = true;
var results = _searchEngine.FetchItems(_indexerListItems.Count, 20, _queryCookie, out var hasMore);
_indexerListItems.AddRange(results);
HasMoreItems = hasMore;
FetchItems(20);
IsLoading = false;
RaiseItemsChanged(_indexerListItems.Count);
}
@@ -72,16 +58,70 @@ internal sealed partial class IndexerPage : DynamicListPage, IDisposable
{
++_queryCookie;
_indexerListItems.Clear();
_searchQuery.SearchResults.Clear();
_searchQuery.CancelOutstandingQueries();
_searchEngine.Query(query, _queryCookie);
if (query == string.Empty)
{
return;
}
Stopwatch stopwatch = new();
stopwatch.Start();
_searchQuery.Execute(query, _queryCookie);
stopwatch.Stop();
Logger.LogDebug($"Query time: {stopwatch.ElapsedMilliseconds} ms, query: \"{query}\"");
}
private void FetchItems(int limit)
{
if (_searchQuery != null)
{
var cookie = _searchQuery.Cookie;
if (cookie == _queryCookie)
{
var index = 0;
SearchResult result;
var hasMoreItems = _searchQuery.FetchRows(_indexerListItems.Count, limit);
while (!_searchQuery.SearchResults.IsEmpty && _searchQuery.SearchResults.TryDequeue(out result) && ++index <= limit)
{
IconInfo icon = null;
try
{
var stream = ThumbnailHelper.GetThumbnail(result.LaunchUri).Result;
if (stream != null)
{
var data = new IconData(RandomAccessStreamReference.CreateFromStream(stream));
icon = new IconInfo(data, data);
}
}
catch (Exception ex)
{
Logger.LogError("Failed to get the icon.", ex);
}
_indexerListItems.Add(new IndexerListItem(new IndexerItem
{
FileName = result.ItemDisplayName,
FullPath = result.LaunchUri,
})
{
Icon = icon,
});
}
HasMoreItems = hasMoreItems;
}
}
}
public void Dispose()
{
if (disposeSearchEngine)
{
_searchEngine.Dispose();
GC.SuppressFinalize(this);
}
_searchQuery = null;
GC.SuppressFinalize(this);
}
}

View File

@@ -123,15 +123,6 @@ namespace Microsoft.CmdPal.Ext.Indexer.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Search for &quot;{0}&quot; in files.
/// </summary>
internal static string Indexer_fallback_searchPage_title {
get {
return ResourceManager.GetString("Indexer_fallback_searchPage_title", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to This file doesn&apos;t exist.
/// </summary>
@@ -177,42 +168,6 @@ namespace Microsoft.CmdPal.Ext.Indexer.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Always on.
/// </summary>
internal static string Indexer_Settings_FallbackCommand_AlwaysOn {
get {
return ResourceManager.GetString("Indexer_Settings_FallbackCommand_AlwaysOn", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Only when file path exist.
/// </summary>
internal static string Indexer_Settings_FallbackCommand_FilePathExist {
get {
return ResourceManager.GetString("Indexer_Settings_FallbackCommand_FilePathExist", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Shows file search results on the top-level search results.
/// </summary>
internal static string Indexer_Settings_FallbackCommand_Mode {
get {
return ResourceManager.GetString("Indexer_Settings_FallbackCommand_Mode", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Always off.
/// </summary>
internal static string Indexer_Settings_FallbackCommand_Off {
get {
return ResourceManager.GetString("Indexer_Settings_FallbackCommand_Off", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Search files on this device.
/// </summary>

View File

@@ -156,25 +156,10 @@
<data name="Indexer_PlaceholderText" xml:space="preserve">
<value>Search for files and folders...</value>
</data>
<data name="Indexer_Settings_FallbackCommand_AlwaysOn" xml:space="preserve">
<value>Always on</value>
</data>
<data name="Indexer_Settings_FallbackCommand_Mode" xml:space="preserve">
<value>Shows file search results on the top-level search results</value>
</data>
<data name="Indexer_Settings_FallbackCommand_Off" xml:space="preserve">
<value>Always off</value>
</data>
<data name="Indexer_Settings_FallbackCommand_FilePathExist" xml:space="preserve">
<value>Only when file path exist</value>
</data>
<data name="Indexer_Subtitle" xml:space="preserve">
<value>Search files on this device</value>
</data>
<data name="Indexer_Title" xml:space="preserve">
<value>Search files</value>
</data>
<data name="Indexer_fallback_searchPage_title" xml:space="preserve">
<value>Search for "{0}" in files</value>
</data>
</root>

View File

@@ -1,95 +0,0 @@
// 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.Collections.Generic;
using System.Diagnostics;
using ManagedCommon;
using Microsoft.CmdPal.Ext.Indexer.Data;
using Microsoft.CmdPal.Ext.Indexer.Indexer;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Windows.Storage.Streams;
namespace Microsoft.CmdPal.Ext.Indexer;
public sealed partial class SearchEngine : IDisposable
{
private SearchQuery _searchQuery = new();
public void Query(string query, uint queryCookie)
{
// _indexerListItems.Clear();
_searchQuery.SearchResults.Clear();
_searchQuery.CancelOutstandingQueries();
if (query == string.Empty)
{
return;
}
Stopwatch stopwatch = new();
stopwatch.Start();
_searchQuery.Execute(query, queryCookie);
stopwatch.Stop();
Logger.LogDebug($"Query time: {stopwatch.ElapsedMilliseconds} ms, query: \"{query}\"");
}
public IList<IListItem> FetchItems(int offset, int limit, uint queryCookie, out bool hasMore)
{
hasMore = false;
var results = new List<IListItem>();
if (_searchQuery != null)
{
var cookie = _searchQuery.Cookie;
if (cookie == queryCookie)
{
var index = 0;
SearchResult result;
// var hasMoreItems = _searchQuery.FetchRows(_indexerListItems.Count, limit);
var hasMoreItems = _searchQuery.FetchRows(offset, limit);
while (!_searchQuery.SearchResults.IsEmpty && _searchQuery.SearchResults.TryDequeue(out result) && ++index <= limit)
{
IconInfo icon = null;
try
{
var stream = ThumbnailHelper.GetThumbnail(result.LaunchUri).Result;
if (stream != null)
{
var data = new IconData(RandomAccessStreamReference.CreateFromStream(stream));
icon = new IconInfo(data, data);
}
}
catch (Exception ex)
{
Logger.LogError("Failed to get the icon.", ex);
}
results.Add(new IndexerListItem(new IndexerItem
{
FileName = result.ItemDisplayName,
FullPath = result.LaunchUri,
})
{
Icon = icon,
});
}
hasMore = hasMoreItems;
}
}
return results;
}
public void Dispose()
{
_searchQuery = null;
GC.SuppressFinalize(this);
}
}

View File

@@ -9,7 +9,6 @@ using System.Linq;
using System.Resources;
using System.Text;
using System.Threading.Tasks;
using ManagedCommon;
using Microsoft.CmdPal.Ext.Registry.Classes;
using Microsoft.CmdPal.Ext.Registry.Helpers;
using Microsoft.CmdPal.Ext.Registry.Properties;
@@ -38,7 +37,7 @@ internal sealed partial class OpenKeyInEditorCommand : InvokableCommand
RegistryHelper.OpenRegistryKey(entry.Key?.Name ?? entry.KeyPath);
return true;
}
catch (System.ComponentModel.Win32Exception ex)
catch (System.ComponentModel.Win32Exception)
{
// TODO GH #118 We need a convenient way to show errors to a user
// MessageBox.Show(
@@ -46,13 +45,13 @@ internal sealed partial class OpenKeyInEditorCommand : InvokableCommand
// Resources.OpenInRegistryEditorAccessExceptionTitle,
// MessageBoxButton.OK,
// MessageBoxImage.Error);
Logger.LogError(ex.Message);
return false;
}
#pragma warning disable CS0168, IDE0059
catch (Exception exception)
{
Logger.LogError(exception.Message);
// TODO GH #108: Logging
// Log.Exception("Error on opening Windows registry editor", exception, typeof(Main));
return false;
}
#pragma warning restore CS0168, IDE0059

View File

@@ -7,7 +7,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using ManagedCommon;
using Microsoft.CmdPal.Ext.Registry.Classes;
using Microsoft.CmdPal.Ext.Registry.Constants;
using Microsoft.CmdPal.Ext.Registry.Properties;

View File

@@ -5,7 +5,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ManagedCommon;
using Microsoft.CmdPal.Ext.Registry.Classes;
using Microsoft.CmdPal.Ext.Registry.Commands;
using Microsoft.CmdPal.Ext.Registry.Constants;
@@ -96,7 +96,6 @@ internal static class ResultHelper
}
catch (Exception valueException)
{
Logger.LogError(valueException.Message);
var registryEntry = new RegistryEntry(key.Name, valueException);
resultList.Add(new ListItem(new OpenKeyInEditorCommand(registryEntry))

View File

@@ -14,7 +14,6 @@
<PackageReference Include="System.ServiceProcess.ServiceController" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
<ProjectReference Include="..\..\extensionsdk\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
</ItemGroup>
<ItemGroup>

View File

@@ -32,7 +32,6 @@ internal sealed partial class FallbackSystemCommandItem : FallbackCommandItem
{
if (string.IsNullOrWhiteSpace(query))
{
Command = null;
Title = string.Empty;
Subtitle = string.Empty;
return;
@@ -59,7 +58,6 @@ internal sealed partial class FallbackSystemCommandItem : FallbackCommandItem
if (result == null)
{
Command = null;
Title = string.Empty;
Subtitle = string.Empty;

View File

@@ -10,12 +10,12 @@ namespace Microsoft.CmdPal.Ext.System.Pages;
public sealed partial class SystemCommandPage : ListPage
{
private readonly SettingsManager _settingsManager;
private SettingsManager _settingsManager;
public SystemCommandPage(SettingsManager settingsManager)
{
Title = Resources.Microsoft_plugin_ext_system_page_title;
Name = Resources.Microsoft_plugin_command_name_open;
Title = Resources.Microsoft_plugin_ext_system_page_name;
Name = Resources.Microsoft_plugin_ext_system_page_name;
Icon = IconHelpers.FromRelativePath("Assets\\SystemCommand.svg");
_settingsManager = settingsManager;
ShowDetails = true;

View File

@@ -205,7 +205,7 @@ namespace Microsoft.CmdPal.Ext.System {
}
/// <summary>
/// Looks up a localized string similar to System Commands.
/// Looks up a localized string similar to Windows System Command.
/// </summary>
public static string Microsoft_plugin_ext_system_page_name {
get {
@@ -213,15 +213,6 @@ namespace Microsoft.CmdPal.Ext.System {
}
}
/// <summary>
/// Looks up a localized string similar to Windows System Commands.
/// </summary>
public static string Microsoft_plugin_ext_system_page_title {
get {
return ResourceManager.GetString("Microsoft_plugin_ext_system_page_title", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Adapter name.
/// </summary>

View File

@@ -160,11 +160,8 @@
<data name="Microsoft_plugin_ext_settings_hideDisconnectedNetworkInfo" xml:space="preserve">
<value>Hide disconnected network info</value>
</data>
<data name="Microsoft_plugin_ext_system_page_title" xml:space="preserve">
<value>Windows System Commands</value>
</data>
<data name="Microsoft_plugin_ext_system_page_name" xml:space="preserve">
<value>System Commands</value>
<value>Windows System Command</value>
</data>
<data name="Microsoft_plugin_sys_AdapterName" xml:space="preserve">
<value>Adapter name</value>

View File

@@ -14,7 +14,7 @@ public partial class SystemCommandExtensionProvider : CommandProvider
private readonly ICommandItem[] _commands;
private static readonly SettingsManager _settingsManager = new();
public static readonly SystemCommandPage Page = new(_settingsManager);
private readonly FallbackSystemCommandItem _fallbackSystemItem = new(_settingsManager);
private readonly FallbackSystemCommandItem _fallbackFileItem = new(_settingsManager);
public SystemCommandExtensionProvider()
{
@@ -23,7 +23,7 @@ public partial class SystemCommandExtensionProvider : CommandProvider
_commands = [
new CommandItem(Page)
{
Title = Resources.Microsoft_plugin_ext_system_page_title,
Title = Resources.Microsoft_plugin_ext_system_page_name,
Icon = Page.Icon,
MoreCommands = [new CommandContextItem(_settingsManager.Settings.SettingsPage)],
},
@@ -38,5 +38,5 @@ public partial class SystemCommandExtensionProvider : CommandProvider
return _commands;
}
public override IFallbackCommandItem[] FallbackCommands() => [_fallbackSystemItem];
public override IFallbackCommandItem[] FallbackCommands() => [_fallbackFileItem];
}

View File

@@ -7,7 +7,6 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using ManagedCommon;
namespace Microsoft.CmdPal.Ext.TimeDate.Helpers;
@@ -110,11 +109,10 @@ internal static class AvailableResultsList
{
value = dtObject.ToString(value, CultureInfo.CurrentCulture);
}
catch (Exception ex)
catch
{
if (!containsCustomSyntax)
{
Logger.LogError($"Unable to format date time with format: {value}. Error: {ex.Message}");
throw;
}
else
@@ -135,7 +133,6 @@ internal static class AvailableResultsList
}
catch (ArgumentOutOfRangeException e)
{
Logger.LogError($"ArgumentOutOfRangeException with format: {formatSyntax}. Error: {e.Message}");
results.Add(new AvailableResult()
{
Value = Resources.Microsoft_plugin_timedate_ErrorConvertCustomFormat,
@@ -147,7 +144,6 @@ internal static class AvailableResultsList
}
catch (Exception e)
{
Logger.LogError($"Exception with format: {formatSyntax}. Error: {e.Message}");
results.Add(new AvailableResult()
{
Value = Resources.Microsoft_plugin_timedate_InvalidCustomFormat + " " + formatSyntax,
@@ -329,9 +325,8 @@ internal static class AvailableResultsList
IconType = ResultIconType.DateTime,
});
}
catch (Exception ex)
catch
{
Logger.LogError($"Unable to convert to Windows file time: {ex.Message}");
results.Add(new AvailableResult()
{
Value = Resources.Microsoft_plugin_timedate_ErrorConvertWft,

View File

@@ -6,7 +6,6 @@ using System;
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;
using ManagedCommon;
namespace Microsoft.CmdPal.Ext.TimeDate.Helpers;
@@ -167,7 +166,6 @@ internal static class TimeAndDateHelper
if (DateTime.TryParse(input, out timestamp))
{
// Known date/time format
Logger.LogDebug($"Successfully parsed standard date/time format: '{input}' as {timestamp}");
return true;
}
else if (Regex.IsMatch(input, @"^u[\+-]?\d+$"))
@@ -181,12 +179,10 @@ internal static class TimeAndDateHelper
{
inputParsingErrorMsg = string.Format(CultureInfo.CurrentCulture, errorMessage, Resources.Microsoft_plugin_timedate_Unix, UnixTimeSecondsMin, UnixTimeSecondsMax);
timestamp = new DateTime(1, 1, 1, 1, 1, 1);
Logger.LogError($"Failed to parse unix timestamp: '{input}'. Value out of range.");
return false;
}
timestamp = DateTimeOffset.FromUnixTimeSeconds(secondsU).LocalDateTime;
Logger.LogDebug($"Successfully parsed unix timestamp: '{input}' as {timestamp}");
return true;
}
else if (Regex.IsMatch(input, @"^ums[\+-]?\d+$"))
@@ -200,12 +196,10 @@ internal static class TimeAndDateHelper
{
inputParsingErrorMsg = string.Format(CultureInfo.CurrentCulture, errorMessage, Resources.Microsoft_plugin_timedate_Unix_Milliseconds, UnixTimeMillisecondsMin, UnixTimeMillisecondsMax);
timestamp = new DateTime(1, 1, 1, 1, 1, 1);
Logger.LogError($"Failed to parse unix millisecond timestamp: '{input}'. Value out of range.");
return false;
}
timestamp = DateTimeOffset.FromUnixTimeMilliseconds(millisecondsUms).LocalDateTime;
Logger.LogDebug($"Successfully parsed unix millisecond timestamp: '{input}' as {timestamp}");
return true;
}
else if (Regex.IsMatch(input, @"^ft\d+$"))
@@ -218,13 +212,11 @@ internal static class TimeAndDateHelper
{
inputParsingErrorMsg = string.Format(CultureInfo.CurrentCulture, errorMessage, Resources.Microsoft_plugin_timedate_WindowsFileTime, WindowsFileTimeMin, WindowsFileTimeMax);
timestamp = new DateTime(1, 1, 1, 1, 1, 1);
Logger.LogError($"Failed to parse Windows file time: '{input}'. Value out of range.");
return false;
}
// DateTime.FromFileTime returns as local time.
timestamp = DateTime.FromFileTime(secondsFt);
Logger.LogDebug($"Successfully parsed Windows file time: '{input}' as {timestamp}");
return true;
}
else if (Regex.IsMatch(input, @"^oa[+-]?\d+[,.0-9]*$"))
@@ -238,12 +230,10 @@ internal static class TimeAndDateHelper
{
inputParsingErrorMsg = string.Format(CultureInfo.CurrentCulture, errorMessage, Resources.Microsoft_plugin_timedate_OADate, OADateMin, OADateMax);
timestamp = new DateTime(1, 1, 1, 1, 1, 1);
Logger.LogError($"Failed to parse OLE Automation date: '{input}'. Value out of range.");
return false;
}
timestamp = DateTime.FromOADate(oADate);
Logger.LogDebug($"Successfully parsed OLE Automation date: '{input}' as {timestamp}");
return true;
}
else if (Regex.IsMatch(input, @"^exc[+-]?\d+[,.0-9]*$"))
@@ -259,7 +249,6 @@ internal static class TimeAndDateHelper
// For the if itself we use 0 as min value that we can show a special message if input is 0.
inputParsingErrorMsg = string.Format(CultureInfo.CurrentCulture, errorMessage, Resources.Microsoft_plugin_timedate_Excel1900, Excel1900DateMin, Excel1900DateMax);
timestamp = new DateTime(1, 1, 1, 1, 1, 1);
Logger.LogError($"Failed to parse Excel 1900 date value: '{input}'. Value out of range.");
return false;
}
@@ -267,13 +256,11 @@ internal static class TimeAndDateHelper
{
inputParsingErrorMsg = Resources.Microsoft_plugin_timedate_InvalidInput_FakeExcel1900;
timestamp = new DateTime(1, 1, 1, 1, 1, 1);
Logger.LogError($"Failed to parse Excel 1900 date value: '{input}'. Invalid date (0 or 60).");
return false;
}
excDate = excDate <= 60 ? excDate + 1 : excDate;
timestamp = DateTime.FromOADate(excDate);
Logger.LogDebug($"Successfully parsed Excel 1900 date value: '{input}' as {timestamp}");
return true;
}
else if (Regex.IsMatch(input, @"^exf[+-]?\d+[,.0-9]*$"))
@@ -288,18 +275,15 @@ internal static class TimeAndDateHelper
{
inputParsingErrorMsg = string.Format(CultureInfo.CurrentCulture, errorMessage, Resources.Microsoft_plugin_timedate_Excel1904, Excel1904DateMin, Excel1904DateMax);
timestamp = new DateTime(1, 1, 1, 1, 1, 1);
Logger.LogError($"Failed to parse Excel 1904 date value: '{input}'. Value out of range.");
return false;
}
timestamp = DateTime.FromOADate(exfDate + 1462);
Logger.LogDebug($"Successfully parsed Excel 1904 date value: '{input}' as {timestamp}");
return true;
}
else
{
timestamp = new DateTime(1, 1, 1, 1, 1, 1);
Logger.LogWarning($"Failed to parse input: '{input}'. Format not recognized.");
return false;
}
}

View File

@@ -19,7 +19,6 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
<ProjectReference Include="..\..\extensionsdk\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
</ItemGroup>

View File

@@ -5,7 +5,6 @@
using System;
using System.Text;
using System.Threading;
using ManagedCommon;
namespace Microsoft.CmdPal.Ext.WebSearch.Helpers;
@@ -171,7 +170,6 @@ public static class DefaultBrowserInfo
if (!_errorLogged)
{
// Log.Exception("Exception when retrieving browser path/name. Path and Name are set to use Microsoft Edge.", e, typeof(DefaultBrowserInfo));
Logger.LogError("Exception when retrieving browser path/name. Path and Name are set to use Microsoft Edge.");
_errorLogged = true;
}
}

View File

@@ -10,7 +10,6 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
<ProjectReference Include="..\..\extensionsdk\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
</ItemGroup>

View File

@@ -156,22 +156,7 @@ public partial class InstallPackageListItem : ListItem
private async void UpdatedInstalledStatus()
{
try
{
var status = await _package.CheckInstalledStatusAsync();
}
catch (OperationCanceledException)
{
// DO NOTHING HERE
return;
}
catch (Exception ex)
{
// Handle other exceptions
ExtensionHost.LogMessage($"[WinGet] UpdatedInstalledStatus throw exception: {ex.Message}");
return;
}
var status = await _package.CheckInstalledStatusAsync();
var isInstalled = _package.InstalledVersion != null;
var installedState = isInstalled ?

View File

@@ -57,7 +57,7 @@ internal sealed partial class WinGetExtensionPage : DynamicListPage, IDisposable
{
// emptySearchForTag ===
// we don't have results yet, we haven't typed anything, and we're searching for a tag
var emptySearchForTag = _results == null &&
bool emptySearchForTag = _results == null &&
string.IsNullOrEmpty(SearchText) &&
HasTag;
@@ -116,22 +116,8 @@ internal sealed partial class WinGetExtensionPage : DynamicListPage, IDisposable
IsLoading = true;
try
{
// Save the latest search task
_currentSearchTask = DoSearchAsync(newSearch, cancellationToken);
}
catch (OperationCanceledException)
{
// DO NOTHING HERE
return;
}
catch (Exception ex)
{
// Handle other exceptions
ExtensionHost.LogMessage($"[WinGet] DoUpdateSearchText throw exception: {ex.Message}");
return;
}
// Save the latest search task
_currentSearchTask = DoSearchAsync(newSearch, cancellationToken);
// Await the task to ensure only the latest one gets processed
_ = ProcessSearchResultsAsync(_currentSearchTask, newSearch);

View File

@@ -13,7 +13,6 @@
<None Remove="Assets\WindowWalker.svg" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
<ProjectReference Include="..\..\extensionsdk\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
</ItemGroup>
<ItemGroup>

View File

@@ -8,7 +8,6 @@ using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using ManagedCommon;
using Microsoft.CmdPal.Ext.WindowsServices.Commands;
using Microsoft.CmdPal.Ext.WindowsServices.Properties;
using Microsoft.CommandPalette.Extensions.Toolkit;
@@ -148,14 +147,12 @@ public static class ServiceHelper
// TODO GH #108 We need to figure out some logging
// contextAPI.ShowNotification(GetLocalizedErrorMessage(action), serviceResult.DisplayName);
// Log.Error($"The command returned {exitCode}", MethodBase.GetCurrentMethod().DeclaringType);
Logger.LogError($"The command returned {exitCode}");
}
}
catch (Win32Exception ex)
{
// TODO GH #108 We need to figure out some logging
// Log.Error(ex.Message, MethodBase.GetCurrentMethod().DeclaringType);
Logger.LogError($"Failed to change service '{serviceResult.DisplayName}' status to {action}: {ex.Message}");
}
}
#pragma warning restore IDE0059, CS0168, SA1005
@@ -176,7 +173,6 @@ public static class ServiceHelper
catch (Exception ex)
{
// TODO GH #108 We need to figure out some logging
Logger.LogError($"Failed to open services.msc: {ex.Message}");
}
}
#pragma warning restore IDE0059, CS0168, SA1005

View File

@@ -17,7 +17,6 @@
<PackageReference Include="System.ServiceProcess.ServiceController" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
<ProjectReference Include="..\..\extensionsdk\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
</ItemGroup>
<ItemGroup>

View File

@@ -4,7 +4,6 @@
using System;
using System.ServiceProcess;
using ManagedCommon;
namespace Microsoft.CmdPal.Ext.WindowsServices;
@@ -36,11 +35,10 @@ public class ServiceResult
return result;
}
catch (Exception ex)
catch (Exception)
{
// try to log the exception in the future
// retrieve properties from serviceController will throw exception. Such as PlatformNotSupportedException.
Logger.LogError($"Failed to create ServiceController: {ex.GetType().Name} - {ex.Message}");
}
return null;

View File

@@ -6,7 +6,6 @@ using System;
using System.IO;
using System.Reflection;
using System.Text.Json;
using ManagedCommon;
namespace Microsoft.CmdPal.Ext.WindowsSettings.Helpers;
@@ -61,7 +60,6 @@ internal static class JsonSettingsListHelper
{
// TODO GH #108 Logging is something we have to take care of
// Log.Exception("Error loading settings JSON file", exception, typeof(JsonSettingsListHelper));
Logger.LogError($"Error loading settings JSON file: {exception.Message}");
}
#pragma warning restore CS0168
return settings ?? new Classes.WindowsSettings();

View File

@@ -7,7 +7,6 @@ using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using ManagedCommon;
using Microsoft.CmdPal.Ext.WindowsSettings.Properties;
namespace Microsoft.CmdPal.Ext.WindowsSettings.Helpers;
@@ -37,7 +36,6 @@ internal static class TranslationHelper
if (string.IsNullOrEmpty(name))
{
// Log.Warn($"Resource string for [{settings.Name}] not found", typeof(TranslationHelper));
Logger.LogWarning($"Resource string for [{settings.Name}] not found");
}
settings.Name = name ?? settings.Name ?? string.Empty;
@@ -50,7 +48,6 @@ internal static class TranslationHelper
if (string.IsNullOrEmpty(type))
{
// Log.Warn($"Resource string for [{settings.Type}] not found", typeof(TranslationHelper));
Logger.LogWarning($"Resource string for [{settings.Type}] not found");
}
settings.Type = type ?? settings.Type ?? string.Empty;
@@ -72,7 +69,6 @@ internal static class TranslationHelper
if (string.IsNullOrEmpty(translatedArea))
{
// Log.Warn($"Resource string for [{area}] not found", typeof(TranslationHelper));
Logger.LogWarning($"Resource string for [{area}] not found");
}
translatedAreas.Add(translatedArea ?? area);
@@ -97,7 +93,6 @@ internal static class TranslationHelper
if (string.IsNullOrEmpty(translatedAltName))
{
// Log.Warn($"Resource string for [{altName}] not found", typeof(TranslationHelper));
Logger.LogWarning($"Resource string for [{altName}] not found");
}
translatedAltNames.Add(translatedAltName ?? altName);
@@ -113,7 +108,6 @@ internal static class TranslationHelper
if (string.IsNullOrEmpty(note))
{
// Log.Warn($"Resource string for [{settings.Note}] not found", typeof(TranslationHelper));
Logger.LogWarning($"Resource string for [{settings.Note}] not found");
}
settings.Note = note ?? settings.Note ?? string.Empty;

View File

@@ -4,7 +4,6 @@
using System;
using System.Linq;
using ManagedCommon;
namespace Microsoft.CmdPal.Ext.WindowsSettings.Helpers;
@@ -41,7 +40,6 @@ internal static class UnsupportedSettingsHelper
// TODO GH #108 Logging is something we have to take care of
// Log.Warn(warningMessage, typeof(UnsupportedSettingsHelper));
Logger.LogWarning(warningMessage);
}
var currentWindowsBuild = currentBuild != uint.MinValue
@@ -73,9 +71,12 @@ internal static class UnsupportedSettingsHelper
{
registryValueData = Win32.Registry.GetValue(registryKey, valueName, uint.MinValue);
}
catch (Exception ex)
catch
{
Logger.LogError($"Can't get registry value for '{valueName}' - {ex.Message}");
// Log.Exception(
// $"Can't get registry value for '{valueName}'",
// exception,
// typeof(UnsupportedSettingsHelper));
return uint.MinValue;
}

View File

@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System.Linq;
using ManagedCommon;
namespace Microsoft.CmdPal.Ext.WindowsSettings.Helpers;
@@ -35,7 +34,6 @@ internal static class WindowsSettingsPathHelper
{
// TODO GH #108 Logging is something we have to take care of
// Log.Warn($"The type property is not set for setting [{settings.Name}] in json. Skipping generating of settings path.", typeof(WindowsSettingsPathHelper));
Logger.LogWarning($"The type property is not set for setting [{settings.Name}] in json. Skipping generating of settings path.");
continue;
}
@@ -43,14 +41,12 @@ internal static class WindowsSettingsPathHelper
if (!string.IsNullOrEmpty(settings.JoinedAreaPath))
{
// Log.Debug($"The property [JoinedAreaPath] of setting [{settings.Name}] was filled from the json. This value is not used and will be overwritten.", typeof(WindowsSettingsPathHelper));
Logger.LogDebug($"The property [JoinedAreaPath] of setting [{settings.Name}] was filled from the json. This value is not used and will be overwritten.");
}
if (!string.IsNullOrEmpty(settings.JoinedFullSettingsPath))
{
// TODO GH #108 Logging is something we have to take care of
// Log.Debug($"The property [JoinedFullSettingsPath] of setting [{settings.Name}] was filled from the json. This value is not used and will be overwritten.", typeof(WindowsSettingsPathHelper));
Logger.LogDebug($"The property [JoinedFullSettingsPath] of setting [{settings.Name}] was filled from the json. This value is not used and will be overwritten.");
}
// Generating path values.

View File

@@ -20,7 +20,6 @@
<PackageReference Include="System.ServiceProcess.ServiceController" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
<ProjectReference Include="..\..\extensionsdk\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
</ItemGroup>
<ItemGroup>

View File

@@ -9,7 +9,6 @@ using System.Linq;
using System.Resources;
using System.Text;
using System.Threading.Tasks;
using ManagedCommon;
using Microsoft.CmdPal.Ext.WindowsTerminal.Helpers;
using Microsoft.CmdPal.Ext.WindowsTerminal.Properties;
using Microsoft.CommandPalette.Extensions;
@@ -61,7 +60,6 @@ internal sealed partial class LaunchProfileAsAdminCommand : InvokableCommand
//var message = Resources.run_terminal_failed;
//Log.Exception("Failed to open Windows Terminal", ex, GetType());
//_context.API.ShowMsg(name, message, string.Empty);
Logger.LogError($"Failed to open Windows Terminal: {ex.Message}");
}
}
#pragma warning restore IDE0059, CS0168, SA1005
@@ -83,7 +81,6 @@ internal sealed partial class LaunchProfileAsAdminCommand : InvokableCommand
// var message = Resources.run_terminal_failed;
// Log.Exception("Failed to open Windows Terminal", ex, GetType());
// _context.API.ShowMsg(name, message, string.Empty);
Logger.LogError($"Failed to open Windows Terminal: {ex.Message}");
}
}
#pragma warning restore IDE0059, CS0168
@@ -97,7 +94,6 @@ internal sealed partial class LaunchProfileAsAdminCommand : InvokableCommand
catch
{
// TODO GH #108 We need to figure out some logging
// No need to log here, as the exception is already logged in LaunchElevated
}
return CommandResult.Dismiss();

View File

@@ -9,7 +9,6 @@ using System.Linq;
using System.Resources;
using System.Text;
using System.Threading.Tasks;
using ManagedCommon;
using Microsoft.CmdPal.Ext.WindowsTerminal.Helpers;
using Microsoft.CmdPal.Ext.WindowsTerminal.Properties;
using Microsoft.CommandPalette.Extensions;
@@ -53,7 +52,6 @@ internal sealed partial class LaunchProfileCommand : InvokableCommand
// var message = Resources.run_terminal_failed;
// Log.Exception("Failed to open Windows Terminal", ex, GetType());
// _context.API.ShowMsg(name, message, string.Empty);
Logger.LogError($"Failed to open Windows Terminal: {ex.Message}");
}
}
#pragma warning restore IDE0059, CS0168
@@ -67,7 +65,6 @@ internal sealed partial class LaunchProfileCommand : InvokableCommand
catch
{
// TODO GH #108 We need to figure out some logging
// No need to log here, as the exception is already logged in the Launch method
}
return CommandResult.Dismiss();

View File

@@ -8,7 +8,7 @@ using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Security.Principal;
using ManagedCommon;
using Windows.Management.Deployment;
// using Wox.Plugin.Logger;
@@ -41,7 +41,6 @@ public class TerminalQuery : ITerminalQuery
{
// TODO: what kind of logging should we do?
// Log.Warn($"No Windows Terminal packages installed", typeof(TerminalQuery));
Logger.LogWarning("No Windows Terminal packages installed");
}
foreach (var terminal in Terminals)
@@ -50,7 +49,6 @@ public class TerminalQuery : ITerminalQuery
{
// TODO: what kind of logging should we do?
// Log.Warn($"Failed to find settings file {terminal.SettingsPath}", typeof(TerminalQuery));
Logger.LogWarning($"Failed to find settings file {terminal.SettingsPath}");
continue;
}

Some files were not shown because too many files have changed in this diff Show More