mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-01-09 13:57:05 +01:00
Compare commits
13 Commits
leilzh/app
...
leilzh/ini
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c3fc5f817 | ||
|
|
5ef63a19ce | ||
|
|
d51e2b5357 | ||
|
|
e6d6edce57 | ||
|
|
b3cda2cd55 | ||
|
|
b941fc64bf | ||
|
|
1952a17a17 | ||
|
|
20dda12dbc | ||
|
|
0c870d68c6 | ||
|
|
f31497e08e | ||
|
|
718600a379 | ||
|
|
63b13d219c | ||
|
|
1e79a98b2e |
@@ -22,6 +22,7 @@
|
||||
"CalculatorEngineCommon.dll",
|
||||
"PowerToys.ManagedTelemetry.dll",
|
||||
"PowerToys.ManagedCommon.dll",
|
||||
"PowerToys.ManagedCsWin32.dll",
|
||||
"PowerToys.Common.UI.dll",
|
||||
"PowerToys.Settings.UI.Lib.dll",
|
||||
"PowerToys.GPOWrapper.dll",
|
||||
|
||||
@@ -9,6 +9,7 @@ Param(
|
||||
$DirPath = $targetDir; #this file is in pipeline, we need root.
|
||||
$items = Get-ChildItem -Path $DirPath -File -Include *.exe, *.dll, *.ttf, PTCustomActions -Recurse -Force -ErrorAction SilentlyContinue
|
||||
$versionExceptions = @(
|
||||
"AdaptiveCards.Templating.dll",
|
||||
"Microsoft.Windows.ApplicationModel.DynamicDependency.Projection.dll",
|
||||
"Microsoft.Windows.ApplicationModel.Resources.Projection.dll",
|
||||
"Microsoft.Windows.ApplicationModel.WindowsAppRuntime.Projection.dll",
|
||||
|
||||
@@ -173,6 +173,25 @@ public class UWPApplication : IProgram
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string TryLoadIndirectString(string source, Span<char> buffer, string errorContext)
|
||||
{
|
||||
try
|
||||
{
|
||||
PInvoke.SHLoadIndirectString(source, buffer).ThrowOnFailure();
|
||||
|
||||
var len = buffer.IndexOf('\0');
|
||||
var loaded = len >= 0
|
||||
? buffer[..len].ToString()
|
||||
: buffer.ToString();
|
||||
return string.IsNullOrEmpty(loaded) ? string.Empty : loaded;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Unable to load resource {source} : {errorContext} : {ex.Message}");
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
internal unsafe string ResourceFromPri(string packageFullName, string resourceReference)
|
||||
{
|
||||
const string prefix = "ms-resource:";
|
||||
@@ -221,28 +240,15 @@ public class UWPApplication : IProgram
|
||||
Span<char> outBuffer = stackalloc char[1024];
|
||||
var source = $"@{{{packageFullName}? {parsed}}}";
|
||||
|
||||
try
|
||||
{
|
||||
PInvoke.SHLoadIndirectString(source, outBuffer).ThrowOnFailure();
|
||||
var loaded = TryLoadIndirectString(source, outBuffer, resourceReference);
|
||||
|
||||
var loaded = outBuffer.ToString();
|
||||
return string.IsNullOrEmpty(loaded) ? string.Empty : loaded;
|
||||
}
|
||||
catch (Exception)
|
||||
if (!string.IsNullOrEmpty(loaded))
|
||||
{
|
||||
try
|
||||
{
|
||||
var sourceFallback = $"@{{{packageFullName}?{parsedFallback}}}";
|
||||
PInvoke.SHLoadIndirectString(sourceFallback, outBuffer).ThrowOnFailure();
|
||||
var loaded = outBuffer.ToString();
|
||||
return string.IsNullOrEmpty(loaded) ? string.Empty : loaded;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ProgramLogger.Exception($"Unable to load resource {resourceReference} from {packageFullName}", new InvalidOperationException(), GetType(), packageFullName);
|
||||
return string.Empty;
|
||||
}
|
||||
return loaded;
|
||||
}
|
||||
|
||||
var sourceFallback = $"@{{{packageFullName}?{parsedFallback}}}";
|
||||
return TryLoadIndirectString(sourceFallback, outBuffer, $"{resourceReference} (fallback)");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -84,11 +84,7 @@ public static class CalculateEngine
|
||||
|
||||
var decimalResult = Convert.ToDecimal(result, cultureInfo);
|
||||
|
||||
// Remove trailing zeros from the decimal string representation (e.g., "1.2300" -> "1.23")
|
||||
// This is necessary because the value extracted from exprtk may contain unnecessary trailing zeros.
|
||||
var formatted = decimalResult.ToString("G29", cultureInfo);
|
||||
decimalResult = Convert.ToDecimal(formatted, cultureInfo);
|
||||
var roundedResult = Round(decimalResult);
|
||||
var roundedResult = FormatMax15Digits(decimalResult, cultureInfo);
|
||||
|
||||
return new CalculateResult()
|
||||
{
|
||||
@@ -101,4 +97,28 @@ public static class CalculateEngine
|
||||
{
|
||||
return Math.Round(value, RoundingDigits, MidpointRounding.AwayFromZero);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Format a decimal so that the output contains **at most 15 total digits**
|
||||
/// (integer + fraction, not counting the decimal point or minus sign).
|
||||
/// Any extra fractional digits are rounded using “away-from-zero” rounding.
|
||||
/// Trailing zeros in the fractional part—and a dangling decimal point—are removed.
|
||||
/// Examples
|
||||
/// 1.9999999999 → "1.9999999999"
|
||||
/// 100000.9999999999 → "100001"
|
||||
/// 1234567890123.45 → "1234567890123.45"
|
||||
/// </summary>
|
||||
private static decimal FormatMax15Digits(decimal value, CultureInfo cultureInfo)
|
||||
{
|
||||
var absValue = Math.Abs(value);
|
||||
var integerDigits = absValue >= 1 ? (int)Math.Floor(Math.Log10((double)absValue)) + 1 : 1;
|
||||
|
||||
var maxDecimalDigits = Math.Max(0, 15 - integerDigits);
|
||||
|
||||
var rounded = Math.Round(value, maxDecimalDigits, MidpointRounding.AwayFromZero);
|
||||
|
||||
var formatted = rounded.ToString("G29", cultureInfo);
|
||||
|
||||
return Convert.ToDecimal(formatted, cultureInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// 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.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ManagedCommon;
|
||||
using Windows.AI.Actions;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Indexer.Data;
|
||||
|
||||
public static class ActionRuntimeManager
|
||||
{
|
||||
private static readonly Lazy<Task<ActionRuntime>> _lazyRuntime = new(InitializeAsync);
|
||||
|
||||
public static Task<ActionRuntime> InstanceAsync => _lazyRuntime.Value;
|
||||
|
||||
private static async Task<ActionRuntime> InitializeAsync()
|
||||
{
|
||||
// If we tried 3 times and failed, should we think the action runtime is not working?
|
||||
// then we should not use it anymore.
|
||||
const int maxAttempts = 3;
|
||||
|
||||
for (var attempt = 1; attempt <= maxAttempts; attempt++)
|
||||
{
|
||||
try
|
||||
{
|
||||
var runtime = ActionRuntimeFactory.CreateActionRuntime();
|
||||
await Task.Delay(500);
|
||||
|
||||
return runtime;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Attempt {attempt} to initialize ActionRuntime failed: {ex.Message}");
|
||||
|
||||
if (attempt == maxAttempts)
|
||||
{
|
||||
Logger.LogError($"Failed to initialize ActionRuntime: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,11 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.CmdPal.Ext.Indexer.Data;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Properties;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Windows.Foundation.Metadata;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Indexer;
|
||||
|
||||
@@ -17,6 +19,10 @@ public partial class IndexerCommandsProvider : CommandProvider
|
||||
Id = "Files";
|
||||
DisplayName = Resources.IndexerCommandsProvider_DisplayName;
|
||||
Icon = Icons.FileExplorer;
|
||||
if (ApiInformation.IsApiContractPresent("Windows.AI.Actions.ActionsContract", 4))
|
||||
{
|
||||
_ = ActionRuntimeManager.InstanceAsync;
|
||||
}
|
||||
}
|
||||
|
||||
public override ICommandItem[] TopLevelCommands()
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
// 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.Globalization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ManagedCommon;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Commands;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Data;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Properties;
|
||||
@@ -15,7 +17,7 @@ using Windows.System;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Indexer.Pages;
|
||||
|
||||
internal sealed partial class ActionsListContextItem : CommandContextItem
|
||||
internal sealed partial class ActionsListContextItem : CommandContextItem, IDisposable
|
||||
{
|
||||
private readonly string fullPath;
|
||||
private readonly List<CommandContextItem> actions = [];
|
||||
@@ -41,20 +43,24 @@ internal sealed partial class ActionsListContextItem : CommandContextItem
|
||||
|
||||
private void UpdateMoreCommands()
|
||||
{
|
||||
try
|
||||
lock (UpdateMoreCommandsLock)
|
||||
{
|
||||
lock (UpdateMoreCommandsLock)
|
||||
if (actionRuntime == null)
|
||||
{
|
||||
if (actionRuntime == null)
|
||||
{
|
||||
actionRuntime = ActionRuntimeFactory.CreateActionRuntime();
|
||||
Task.Delay(500).Wait();
|
||||
}
|
||||
|
||||
actionRuntime.ActionCatalog.Changed -= ActionCatalog_Changed;
|
||||
actionRuntime.ActionCatalog.Changed += ActionCatalog_Changed;
|
||||
actionRuntime = ActionRuntimeManager.InstanceAsync.GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
if (actionRuntime == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
actionRuntime.ActionCatalog.Changed -= ActionCatalog_Changed;
|
||||
actionRuntime.ActionCatalog.Changed += ActionCatalog_Changed;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var extension = System.IO.Path.GetExtension(fullPath).ToLower(CultureInfo.InvariantCulture);
|
||||
ActionEntity entity = null;
|
||||
if (extension != null)
|
||||
@@ -85,9 +91,20 @@ internal sealed partial class ActionsListContextItem : CommandContextItem
|
||||
MoreCommands = [.. actions];
|
||||
}
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
actionRuntime = null;
|
||||
Logger.LogError($"Error updating commands: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
lock (UpdateMoreCommandsLock)
|
||||
{
|
||||
if (actionRuntime != null)
|
||||
{
|
||||
actionRuntime.ActionCatalog.Changed -= ActionCatalog_Changed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,4 +12,4 @@ To view the full docs, you can head over to [our docs site](https://go.microsoft
|
||||
There are samples of just about everything you can do in [the samples project].
|
||||
Head over there to see basic usage of the APIs.
|
||||
|
||||
[the samples project]: https://github.com/microsoft/PowerToys/tree/main/src/modules/cmdpal/Exts/SamplePagesExtension
|
||||
[the samples project]: https://github.com/microsoft/PowerToys/tree/main/src/modules/cmdpal/ext/SamplePagesExtension
|
||||
|
||||
@@ -180,9 +180,6 @@
|
||||
<value>Exit</value>
|
||||
<comment>Exit as a verb, as in Exit the application</comment>
|
||||
</data>
|
||||
<data name="SHOW_TRAY_ICON_MENU_TEXT" xml:space="preserve">
|
||||
<value>Show icon</value>
|
||||
</data>
|
||||
<data name="SUBMIT_BUG_TEXT" xml:space="preserve">
|
||||
<value>Report bug</value>
|
||||
</data>
|
||||
|
||||
@@ -164,7 +164,8 @@ void apply_general_settings(const json::JsonObject& general_configs, bool save)
|
||||
else
|
||||
{
|
||||
delete_auto_start_task_for_this_user();
|
||||
if (gpo_run_as_startup == powertoys_gpo::gpo_rule_configured_enabled || gpo_run_as_startup == powertoys_gpo::gpo_rule_configured_not_configured) {
|
||||
if (gpo_run_as_startup == powertoys_gpo::gpo_rule_configured_enabled || gpo_run_as_startup == powertoys_gpo::gpo_rule_configured_not_configured)
|
||||
{
|
||||
create_auto_start_task_for_this_user(run_as_elevated);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,4 +21,3 @@
|
||||
#define ID_REPORT_BUG_COMMAND 40004
|
||||
#define ID_DOCUMENTATION_MENU_COMMAND 40005
|
||||
#define ID_QUICK_ACCESS_MENU_COMMAND 40006
|
||||
#define ID_SHOW_TRAY_ICON_MENU_COMMAND 40007
|
||||
|
||||
Binary file not shown.
@@ -91,13 +91,6 @@ void handle_tray_command(HWND window, const WPARAM command_id, LPARAM lparam)
|
||||
}
|
||||
DestroyWindow(window);
|
||||
break;
|
||||
case ID_SHOW_TRAY_ICON_MENU_COMMAND:
|
||||
{
|
||||
GeneralSettings settings = get_general_settings();
|
||||
settings.showSystemTrayIcon = true;
|
||||
apply_general_settings(settings.to_json(), true);
|
||||
break;
|
||||
}
|
||||
case ID_ABOUT_MENU_COMMAND:
|
||||
if (!about_box_shown)
|
||||
{
|
||||
@@ -199,13 +192,11 @@ LRESULT __stdcall tray_icon_window_proc(HWND window, UINT message, WPARAM wparam
|
||||
{
|
||||
static std::wstring settings_menuitem_label = GET_RESOURCE_STRING(IDS_SETTINGS_MENU_TEXT);
|
||||
static std::wstring exit_menuitem_label = GET_RESOURCE_STRING(IDS_EXIT_MENU_TEXT);
|
||||
static std::wstring show_tray_icon_menuitem_label = GET_RESOURCE_STRING(IDS_SHOW_TRAY_ICON_MENU_TEXT);
|
||||
static std::wstring submit_bug_menuitem_label = GET_RESOURCE_STRING(IDS_SUBMIT_BUG_TEXT);
|
||||
static std::wstring documentation_menuitem_label = GET_RESOURCE_STRING(IDS_DOCUMENTATION_MENU_TEXT);
|
||||
static std::wstring quick_access_menuitem_label = GET_RESOURCE_STRING(IDS_QUICK_ACCESS_MENU_TEXT);
|
||||
change_menu_item_text(ID_SETTINGS_MENU_COMMAND, settings_menuitem_label.data());
|
||||
change_menu_item_text(ID_EXIT_MENU_COMMAND, exit_menuitem_label.data());
|
||||
change_menu_item_text(ID_SHOW_TRAY_ICON_MENU_COMMAND, show_tray_icon_menuitem_label.data());
|
||||
change_menu_item_text(ID_REPORT_BUG_COMMAND, submit_bug_menuitem_label.data());
|
||||
bool bug_report_disabled = is_bug_report_running();
|
||||
EnableMenuItem(h_sub_menu, ID_REPORT_BUG_COMMAND, MF_BYCOMMAND | (bug_report_disabled ? MF_GRAYED : MF_ENABLED));
|
||||
|
||||
Reference in New Issue
Block a user