Compare commits

...

4 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
f7bdb5d8d3 Implement admin permission checks for update installer
Co-authored-by: yeelam-gordon <73506701+yeelam-gordon@users.noreply.github.com>
2025-08-29 07:10:38 +00:00
copilot-swe-agent[bot]
516e9878a9 Initial plan 2025-08-29 06:58:46 +00:00
Copilot
eb35b3a249 Fix grammatical error in Awake taskbar context menu: "1 hours" → "1 hour" (#41454)
This PR fixes a grammatical mistake in the PowerToys Awake taskbar
context menu where "1 hours" was displayed instead of the correct "1
hour".

## Problem
When right-clicking the Awake icon in the taskbar and hovering over
"Keep awake on interval", the menu incorrectly showed "1 hours" for the
one-hour option, which is grammatically incorrect in English.

![Before fix showing "1
hours"](https://github.com/user-attachments/assets/bd78b3b1-d076-4c84-8de0-bcd6d1ebefd8)

## Root Cause
The code always used the `AWAKE_HOURS` resource string (`"{0} hours"`)
regardless of the value, even when the count was 1. This resulted in
grammatically incorrect text like "1 hours".

## Solution
Added proper singular/plural handling by:

1. **Added new singular resources:**
   - `AWAKE_HOUR`: `"{0} hour"` for singular form
   - `AWAKE_MINUTE`: `"{0} minute"` for completeness and future-proofing

2. **Updated the logic in `Manager.cs`:**
- Modified `GetDefaultTrayOptions()` to use `AwakeHour` (singular) when
the value is 1
- Preserved existing behavior for all other values (30 minutes, 2 hours,
etc.)

3. **Generated corresponding code in `Resources.Designer.cs`** to expose
the new resource properties

## Impact
-  "1 hours" → "1 hour" (grammatically correct)
-  "2 hours" remains unchanged (still correct)
-  "30 minutes" behavior preserved
-  No breaking changes to existing functionality
-  Future-proofed for potential 1-minute custom intervals

The fix follows established patterns in the PowerToys codebase (similar
to `TimeRemainingConverter.cs` in ImageResizer) and makes minimal,
surgical changes to address only the reported issue.

Fixes #41220.

> [!WARNING]
>
> <details>
> <summary>Firewall rules blocked me from connecting to one or more
addresses (expand for details)</summary>
>
> #### I tried to connect to the following addresses, but was blocked by
firewall rules:
>
> - `i1qvsblobprodcus353.vsblob.vsassets.io`
> - Triggering command: `dotnet build
src/modules/awake/Awake/Awake.csproj` (dns block)
>
> If you need me to access, download, or install something from one of
these locations, you can either:
>
> - Configure [Actions setup
steps](https://gh.io/copilot/actions-setup-steps) to set up my
environment, which run before the firewall is enabled
> - Add the appropriate URLs or hosts to the custom allowlist in this
repository's [Copilot coding agent
settings](https://github.com/microsoft/PowerToys/settings/copilot/coding_agent)
(admins only)
>
> </details>



<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: yeelam-gordon <73506701+yeelam-gordon@users.noreply.github.com>
2025-08-29 13:36:46 +08:00
Jiří Polášek
5daec13bc4 CmdPal | Bug Report Tool: Allow collection of Command Palette events from Windows Event Logs by Bug Report Tool (#41400)
## Summary of the Pull Request

Adds `Microsoft.CmdPal.UI.exe` to the list of processes, so Bug Report
Tool can pick Applications Logs for it when generating its report.

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [x] Closes: #41399
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2025-08-28 12:48:30 -05:00
8 changed files with 80 additions and 1 deletions

View File

@@ -201,6 +201,13 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
if (action == UPDATE_NOW_LAUNCH_STAGE1)
{
// Check if user has admin permissions before proceeding
if (!check_user_is_admin())
{
Logger::error("Update failed: Administrator permissions required to install updates");
return 1;
}
bool isUpToDate = false;
auto installerPath = ObtainInstaller(isUpToDate);
bool failed = !installerPath.has_value();
@@ -217,6 +224,12 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
}
else if (action == UPDATE_NOW_LAUNCH_STAGE2)
{
// Check if user has admin permissions before proceeding
if (!check_user_is_admin())
{
Logger::error("Update failed: Administrator permissions required to install updates");
return 1;
}
using namespace std::string_view_literals;
const bool failed = !InstallNewVersionStage2(args[2]);
if (failed)

View File

@@ -49,7 +49,9 @@ namespace Awake.Core
private static DateTimeOffset ExpireAt { get; set; }
private static readonly CompositeFormat AwakeMinute = CompositeFormat.Parse(Resources.AWAKE_MINUTE);
private static readonly CompositeFormat AwakeMinutes = CompositeFormat.Parse(Resources.AWAKE_MINUTES);
private static readonly CompositeFormat AwakeHour = CompositeFormat.Parse(Resources.AWAKE_HOUR);
private static readonly CompositeFormat AwakeHours = CompositeFormat.Parse(Resources.AWAKE_HOURS);
private static readonly BlockingCollection<ExecutionState> _stateQueue;
private static CancellationTokenSource _tokenSource;
@@ -451,7 +453,7 @@ namespace Awake.Core
Dictionary<string, uint> optionsList = new()
{
{ string.Format(CultureInfo.InvariantCulture, AwakeMinutes, 30), 1800 },
{ string.Format(CultureInfo.InvariantCulture, AwakeHours, 1), 3600 },
{ string.Format(CultureInfo.InvariantCulture, AwakeHour, 1), 3600 },
{ string.Format(CultureInfo.InvariantCulture, AwakeHours, 2), 7200 },
};
return optionsList;

View File

@@ -159,6 +159,15 @@ namespace Awake.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to {0} hour.
/// </summary>
internal static string AWAKE_HOUR {
get {
return ResourceManager.GetString("AWAKE_HOUR", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0} hours.
/// </summary>
@@ -240,6 +249,15 @@ namespace Awake.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to {0} minute.
/// </summary>
internal static string AWAKE_MINUTE {
get {
return ResourceManager.GetString("AWAKE_MINUTE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0} minutes.
/// </summary>

View File

@@ -123,6 +123,10 @@
<data name="AWAKE_EXIT" xml:space="preserve">
<value>Exit</value>
</data>
<data name="AWAKE_HOUR" xml:space="preserve">
<value>{0} hour</value>
<comment>{0} shouldn't be removed. It will be replaced by the number 1 at runtime by the application. Used for defining a period to keep the PC awake.</comment>
</data>
<data name="AWAKE_HOURS" xml:space="preserve">
<value>{0} hours</value>
<comment>{0} shouldn't be removed. It will be replaced by a number greater than 1 at runtime by the application. Used for defining a period to keep the PC awake.</comment>
@@ -142,6 +146,10 @@
<value>Keep awake until expiration date and time</value>
<comment>Keep the system awake until expiration date and time</comment>
</data>
<data name="AWAKE_MINUTE" xml:space="preserve">
<value>{0} minute</value>
<comment>{0} shouldn't be removed. It will be replaced by the number 1 at runtime by the application. Used for defining a period to keep the PC awake.</comment>
</data>
<data name="AWAKE_MINUTES" xml:space="preserve">
<value>{0} minutes</value>
<comment>{0} shouldn't be removed. It will be replaced by a number greater than 1 at runtime by the application. Used for defining a period to keep the PC awake.</comment>

View File

@@ -102,6 +102,14 @@
IsTabStop="{x:Bind ViewModel.IsNoNetwork, Mode=OneWay}"
Severity="Error" />
<!-- Insufficient permissions error -->
<InfoBar
x:Uid="General_InsufficientPermissions"
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsInsufficientPermissions, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsInsufficientPermissions, Mode=OneWay}"
Severity="Error" />
<!-- New version available -->
<InfoBar
x:Uid="General_NewVersionAvailable"

View File

@@ -2414,6 +2414,9 @@ From there, simply click on one of the supported files in the File Explorer and
<data name="General_CantCheck.Title" xml:space="preserve">
<value>Network error. Please try again later</value>
</data>
<data name="General_InsufficientPermissions.Title" xml:space="preserve">
<value>Administrator permissions required. Please restart PowerToys as administrator to install updates.</value>
</data>
<data name="General_DownloadAndInstall.Content" xml:space="preserve">
<value>Download &amp; install</value>
</data>

View File

@@ -260,6 +260,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
private bool _isNewVersionDownloading;
private bool _isNewVersionChecked;
private bool _isNoNetwork;
private bool _isInsufficientPermissions;
private bool _isBugReportRunning;
private bool _settingsBackupRestoreMessageVisible;
@@ -953,6 +954,14 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
}
}
public bool IsInsufficientPermissions
{
get
{
return _isInsufficientPermissions;
}
}
public bool IsBugReportRunning
{
get
@@ -1178,6 +1187,18 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
private void UpdateNowClick()
{
// Check if user has admin permissions before starting update
if (!IsAdmin)
{
_isInsufficientPermissions = true;
NotifyPropertyChanged(nameof(IsInsufficientPermissions));
return;
}
// Clear any previous permission error
_isInsufficientPermissions = false;
NotifyPropertyChanged(nameof(IsInsufficientPermissions));
IsNewVersionDownloading = string.IsNullOrEmpty(UpdatingSettingsConfig.DownloadedInstallerFilename);
NotifyPropertyChanged(nameof(IsDownloadAllowed));
@@ -1299,6 +1320,11 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
_isNoNetwork = PowerToysUpdatingState == UpdatingSettings.UpdatingState.NetworkError;
NotifyPropertyChanged(nameof(IsNoNetwork));
// Clear permission error when updating state changes
_isInsufficientPermissions = false;
NotifyPropertyChanged(nameof(IsInsufficientPermissions));
NotifyPropertyChanged(nameof(IsNewVersionDownloading));
NotifyPropertyChanged(nameof(IsUpdatePanelVisible));
_isNewVersionChecked = PowerToysUpdatingState == UpdatingSettings.UpdatingState.UpToDate && !IsNewVersionDownloading;

View File

@@ -51,4 +51,5 @@ std::vector<std::wstring> processes =
L"PowerToys.WorkspacesWindowArranger.exe",
L"PowerToys.WorkspacesEditor.exe",
L"PowerToys.ZoomIt.exe",
L"Microsoft.CmdPal.UI.exe",
};