Compare commits

..

198 Commits

Author SHA1 Message Date
Noraa Junker
dad8d00cda faster 2 2026-05-21 22:19:18 +02:00
Noraa Junker
1b71d64ef8 h 2026-05-21 19:28:38 +02:00
Noraa Junker
111d5b387e Try to make things faster 2026-05-21 19:25:12 +02:00
Noraa Junker
47d348f4ec Remove ZoomIt again, as it still does not work 2026-05-21 18:52:25 +02:00
Noraa Junker
4a71f79901 Fix missing PowerToys modules 2026-05-21 18:45:20 +02:00
Noraa Junker
79f69b87f2 Terminate more cleanly 2026-05-21 18:11:20 +02:00
Noraa Junker
6a0ff6a131 Fix wrong Shortcut Guide Shortcut 2026-05-21 17:47:42 +02:00
Noraa Junker
9123365993 Fix OOBE string 2026-05-21 17:36:14 +02:00
Niels Laute
82e4705ed6 Merge branch 'main' into feature/shortcutguidev2 2026-05-20 12:20:34 +02:00
Muyuan Li (from Dev Box)
cffddcdcb7 Revert personal website link change - not an issue per maintainer
Reverts the noraajunker.ch -> PR link change. As confirmed by @niels9001,
personal contributor links are standard in PowerToys settings pages.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-20 15:24:06 +08:00
Muyuan Li (from Dev Box)
e7b6e36987 Resolve all PR #40834 review comments locally
Applied fixes:
- DpiHelper: int→nint for window handles (pointer truncation)
- DisplayHelper: static fields→lambda closure + bounds check
- NativeMethods: FindWindowA→FindWindowW (Unicode)
- MainWindow: MenuItems[0] guard, remove .ToInt32()
- TaskbarWindow: remove .ToInt32()
- Program.cs: logger init order, args handling, Environment.Exit(0)
- ShortcutDescription/ShortcutEntry: proper GetHashCode
- ShortcutDescriptionToKeysConverter: remove unused using
- excluded_app.cpp: m_excludedApps.clear() before parsing
- tasklist_positions: COM pointers from header to static in .cpp
- IndexYmlGenerator: O(n²) array rebuild→LINQ
- ShortcutGuidePage.xaml: personal link→GitHub PR link

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-20 15:05:06 +08:00
Niels Laute
c07a3d9bd9 Merge remote-tracking branch 'origin/main' into pr/40834 2026-05-19 12:02:29 +02:00
Niels Laute
dcfcd0a699 Fix CS0105: remove duplicate using ManagedCommon directive
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-19 12:02:21 +02:00
Niels Laute
7da07303b3 Update src/modules/ShortcutGuide/ShortcutGuide.Ui/Converters/ShortcutDescriptionToKeysConverter.cs
Co-authored-by: Muyuan Li <116717757+MuyuanMS@users.noreply.github.com>
2026-05-19 10:42:36 +02:00
Niels Laute
97d3b99bc5 Fix spellcheck: add ShortcutGuide V2 word variants, fix forbidden comma pattern
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-18 14:15:28 +02:00
Niels Laute
e0409b0271 Merge branch 'main' into feature/shortcutguidev2 2026-05-18 14:11:36 +02:00
Niels Laute
b58803642d Restore CmdPal files lost via rename-detection in earlier restore
These 7 files exist on main but were dropped by the bad merge. Git's
rename detection paired them with newly-resurrected files at different
paths, so the earlier --diff-filter=DM restore pass missed them.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-17 19:40:37 +02:00
Niels Laute
87c91c5a2a Remove files resurrected by bad merge conflict resolution
These files were intentionally deleted on main by recent PRs but were
resurrected when 7aae7343aa merged main with a bad conflict resolution:
- HideWindowMessage.cs (deleted by #47826 CmdPal parameters)
- BookmarkPlaceholderForm.cs (deleted by #47886 bookmarks-as-parameters)
- NativeMethods.json/.txt + WindowsPackageManager.Interop/* (deleted by
  #46636 Extension Gallery)
- Ext.Indexer/Assets/Actions.png (moved/deleted by #46636)
- DdcCiValidationResult.cs (deleted by #47875 PowerDisplay max-compat)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-17 19:39:34 +02:00
Niels Laute
7716010a38 Restore files dropped by merge conflict resolution
Restores 114 deleted files and re-applies 129 file modifications that
were lost when a divergent merge of main into feature/shortcutguidev2
resolved conflicts by dropping recent CmdPal/Settings work from main
(ExtensionGallery, ListItemsView, ParametersViewModels, HttpCaching,
DangerousFeatureWarningDialog, etc.).

Source: tree of bf8493225d (the good merge sibling of 7aae7343aa).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-17 19:34:10 +02:00
Niels Laute
e77e7dfe68 Merge branch 'feature/shortcutguidev2' of https://github.com/microsoft/PowerToys into feature/shortcutguidev2 2026-05-17 19:27:25 +02:00
Niels Laute
7aae7343aa Merge branch 'main' into feature/shortcutguidev2 2026-05-17 19:27:21 +02:00
Niels Laute
bf8493225d Merge branch 'main' into feature/shortcutguidev2 2026-05-17 18:25:56 +01:00
Niels Laute
12eddcb320 More improvements 2026-05-16 19:31:23 +02:00
Niels Laute
9473657670 Update expect.txt 2026-05-13 22:10:23 +02:00
Niels Laute
9948a2831f Having a single list of shortcuts 2026-05-13 16:43:14 +02:00
Niels Laute
e746675ebf Move manifests to subfolder 2026-05-13 15:42:12 +02:00
Niels Laute
c3ec5b529b Logging 2026-05-13 14:50:05 +02:00
Niels Laute
6a8e439847 More minor refactoring 2026-05-13 14:47:34 +02:00
Niels Laute
36c30ae2fd Minor refactoring 2026-05-13 14:33:08 +02:00
Niels Laute
d09408ce43 Update Resources.resw 2026-05-13 13:32:08 +02:00
Niels Laute
ab79ae7477 Merge branch 'main' into feature/shortcutguidev2 2026-05-13 13:30:07 +02:00
Niels Laute
b6eb027558 Adding more shortcut files 2026-05-13 13:22:23 +02:00
Copilot
999ba28e34 Normalize spell-check expect list with case-sensitive dedupe and stable sort (#47112)
## Summary of the Pull Request

This updates the spell-check allowlist at
`.github/actions/spell-check/expect.txt` to remove duplicate entries and
enforce a single alphabetical ordering. Matching remains case-sensitive
(e.g., `AAA` and `aaa` are treated as distinct entries).

## PR Checklist

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

## Detailed Description of the Pull Request / Additional comments

- **Scope**
  - Updated only `.github/actions/spell-check/expect.txt`.

- **Changes**
  - Removed exact duplicate words.
  - Reordered file into strict alphabetical order.
  - Preserved case-sensitive distinctions.

- **Example**
  ```bash
LC_ALL=C sort -u .github/actions/spell-check/expect.txt -o
.github/actions/spell-check/expect.txt
  ```

## Validation Steps Performed

N/A (no behavioral/code-path changes; list normalization only).

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: noraa-junker <58633848+noraa-junker@users.noreply.github.com>
2026-04-20 14:35:52 +02:00
Noraa Junker
03ff49601d Update expect.txt 2026-04-20 14:14:18 +02:00
Noraa Junker
406b42db64 Update expect.txt 2026-04-20 14:03:48 +02:00
Noraa Junker
8d4a24cd3f Merge branch 'main' into feature/shortcutguidev2 2026-04-20 13:57:22 +02:00
copilot-swe-agent[bot]
0a20b7efb5 Add spelling exceptions for ShortcutGuide-related words to expect.txt
Agent-Logs-Url: https://github.com/microsoft/PowerToys/sessions/9b871785-a2b4-4e2b-8fc0-d19b49fb0792

Co-authored-by: noraa-junker <58633848+noraa-junker@users.noreply.github.com>
2026-04-20 11:53:26 +00:00
Noraa Junker
bf18e7815b Correct postion logic 2026-04-20 13:49:10 +02:00
copilot-swe-agent[bot]
43b37bc733 Add window position dropdown (Left/Right) to Shortcut Guide settings
Agent-Logs-Url: https://github.com/microsoft/PowerToys/sessions/3883a5cc-f63f-4d66-8d5f-a73a94b9d86a

Co-authored-by: noraa-junker <58633848+noraa-junker@users.noreply.github.com>
2026-04-20 11:38:30 +00:00
Niels Laute
c011b2223c More shortcuts MORE! 2026-04-17 17:51:18 +02:00
Niels Laute
019ee046da Update Resources.resw 2026-04-17 17:45:48 +02:00
Niels Laute
e8579c39d0 Showing app icons 2026-04-17 17:14:29 +02:00
Niels Laute
911b39256c Fix crashing on launch 2026-04-17 16:24:46 +02:00
Noraa Junker
250a8cb5b7 Merge main 2026-04-01 12:53:28 +02:00
Noraa Junker
9f9d221eab Adjust docs 2026-02-02 01:40:19 +01:00
Noraa Junker
b9c5c15be2 Fix taskbar indicator to work with the latest canary builds 2026-02-02 01:35:08 +01:00
Noraa Junker
3a4f9c2274 Move cpp project files to powertoys.interop 2026-02-02 00:14:14 +01:00
Noraa Junker
a51fe19f82 merge main and adapt to new modules (aswell fix no taskbar bug) 2026-02-01 22:46:35 +01:00
Noraa Junker
efc814a610 merge main 2026-02-01 12:10:14 +01:00
Noraa Junker
1d1ae0d191 Merge main 2025-10-31 11:32:22 +01:00
Noraa Junker
3df4b45849 Merge remote-tracking branch 'origin/main' into feature/shortcutguidev2 2025-10-29 20:21:45 +01:00
Noraa Junker
88357a5a99 Fixed spawning on wrong display and taskbar window not working under certain circumstances on secondary displays 2025-10-29 20:21:20 +01:00
Noraa Junker
b4773affa7 Fix installer 2025-10-28 21:47:11 +01:00
Noraa Junker
e82c2d20cb Fix spelling again 2025-10-28 14:59:33 +01:00
Noraa Junker
e3a1f97ef3 Fix spelling 2025-10-28 14:51:48 +01:00
Noraa Junker
b26ded5370 Fix spelling 2025-10-28 14:51:36 +01:00
Noraa Junker
2e8ad4827b Fix some spelling issues 2025-10-28 14:43:54 +01:00
Noraa Junker
877626ef45 Added manifest file in 2025-10-28 14:30:41 +01:00
Noraa Junker
e0f72df36c Update ShortcutGuide image 2025-10-28 10:18:40 +01:00
Noraa Junker
552b02d596 Fix spawning window on the right monitor 2025-10-28 00:25:08 +01:00
Noraa Junker
c184acbada Fix xaml styling 2025-10-27 23:42:45 +01:00
Noraa Junker
55038c3c5e Fix missing localization on settings button 2025-10-27 23:42:26 +01:00
Noraa Junker
f537c43139 Added right key visuals and fixed some UI bugs 2025-10-27 23:36:17 +01:00
Noraa Junker
f867323677 Update OOBE string, supress window resizing and fix auto closing when taskbar window opened 2025-10-25 21:01:39 +02:00
Noraa Junker
d58145eb8c add zoomit shortcuts comment 2025-10-25 12:07:15 +02:00
Noraa Junker
486bec0ebd Fix empty windows key 2025-10-18 23:26:53 +02:00
Noraa Junker
e76506dffd Localization 2025-10-18 23:26:16 +02:00
Noraa Junker
841a5c5555 Fixed (un)pinning shortcuts 2025-10-18 23:04:47 +02:00
Noraa Junker
f646e0328e Fix wrong number for Taskbar item 10 2025-10-18 22:06:58 +02:00
Noraa Junker
5054a776dd Fix solution merge error 2025-10-18 22:06:46 +02:00
Noraa Junker
9d480c8e2c Merge conflicts 2025-10-18 21:51:43 +02:00
Niels Laute
d652285a81 [UX] Vertical shortcutguide (#41161)
- Exploring a vertical version for Shortcut Guide 2, to make better use
of the screen real estate
- Cleanup code and improved maintainability

<img width="1391" height="1439" alt="image"
src="https://github.com/user-attachments/assets/7ee3c925-71f1-46ee-83f6-4bc43b69db4c"
/>

<img width="715" height="1065" alt="image"
src="https://github.com/user-attachments/assets/e59684b2-2063-453e-93c7-df770eaa6999"
/>


To do:
- Shortcut visualizations are broken (well.. sometimes!)
- A lot of UX nits

---------

Co-authored-by: Aaron Junker <Aaron.Junker@outlook.com>
2025-10-17 14:39:35 +02:00
Aaron Junker
200afb5c4b merge main 2025-08-20 21:15:49 +02:00
Gordon Lam (SH)
e7582ebd6a Add back empty line which is missing during rebase main 2025-08-19 08:24:08 +08:00
Gordon Lam (SH)
b9c1181d9f Add back missing project because of rebase from main: 2025-08-19 08:16:20 +08:00
Aaron Junker
4aff3418e4 Change display name of File Explorer, hide taskbar indicators on other pages then Windows -> Overview and fix height of Windows -> Overview 2025-08-19 08:09:35 +08:00
Aaron Junker
e53e1b4376 fix xaml styling 2025-08-19 08:09:35 +08:00
Aaron Junker
73f718c233 git messed up 2025-08-19 08:09:34 +08:00
Aaron Junker
0917a64e7d close infotip when link is clicked and remove unneccesairy grid 2025-08-19 08:09:34 +08:00
Aaron Junker
a764bf3e0c Change oobe design 2025-08-19 08:09:34 +08:00
Aaron Junker
4853bd0345 Change some StaticResources to ThemeResources and change style of taskbar indicators 2025-08-19 08:09:34 +08:00
Aaron Junker
dceb1d7730 Fix styling 2025-08-19 08:09:34 +08:00
Aaron Junker
72be09554e Factor out TaskbarIndicator 2025-08-19 08:09:34 +08:00
Aaron Junker
19f95066c3 Fix xaml styling 2025-08-19 08:09:34 +08:00
Aaron Junker
bb16ae1709 Adress some PR comments and fix some bugs 2025-08-19 08:09:34 +08:00
Aaron Junker
dc0877ebe5 Make some adjustants to how the windows key is displayed 2025-08-19 08:09:34 +08:00
Aaron Junker
cd844e3889 Forgot notice.md and CPPProject has some trouble buildinng release x64 2025-08-19 08:09:34 +08:00
Aaron Junker
ac789a7fbe Remove failing test 2025-08-19 08:09:34 +08:00
Aaron Junker
3b7df37ac2 That is a kinda embarrasing error 2025-08-19 08:09:34 +08:00
Aaron Junker
387b7e9795 So something was not right. Hopefully this fixes it. 2025-08-19 08:09:34 +08:00
Aaron Junker
b553addcdd Fix arm64 configuration 2025-08-19 08:09:28 +08:00
Aaron Junker
5c11c751fe Fix xaml styling 2025-08-19 08:05:58 +08:00
Aaron Junker
6d7d5f9cde Fix building in release mode and some other stuff 2025-08-19 08:05:58 +08:00
Aaron Junker
4cb9c53809 Add documentation and only export in tasklist_positions what needs to be exported 2025-08-19 08:05:58 +08:00
Aaron Junker
84d4cbb16d Refactoring, commenting and fixing some little lefrover bugs 2025-08-19 08:05:49 +08:00
Aaron Junker
97cba618da Add explorer shortcuts, fix animation stopping and add an error when index.yml generation fails 2025-08-19 08:05:26 +08:00
Aaron Junker
145247c4fb Add attribution in settings 2025-08-19 08:04:42 +08:00
Aaron Junker
84ab12027b Add welcome screen and update settings and OOBE 2025-08-19 08:04:42 +08:00
Aaron Junker
3458d01d4c Respect excluded apps 2025-08-19 08:04:41 +08:00
Aaron Junker
2e6f80f944 Respect theme selection 2025-08-19 08:04:41 +08:00
Aaron Junker
f8cc513f9c Localization 2025-08-19 08:04:41 +08:00
Aaron Junker
b1d5233622 Fix spelling 2025-08-19 08:04:41 +08:00
Aaron Junker
68b7b4183f Make UI better 2025-08-19 08:04:41 +08:00
Aaron Junker
68a10d0488 Add disclaimers 2025-08-19 08:04:41 +08:00
Aaron Junker
e70ca56e9d Add taskbar launch shortcuts and make powertoys shortcuts empty by default 2025-08-19 08:04:34 +08:00
Aaron Junker
16c4a56ca1 Make settings button work and add settings placeholder 2025-08-19 08:02:30 +08:00
Aaron Junker
0d5c85a00d Add taskbar launch shortcuts and make powertoys shortcuts empty by default 2025-08-19 08:02:29 +08:00
Aaron Junker
509ad636fe Fix spelling 2025-08-19 08:02:29 +08:00
Aaron Junker
26f76105d4 Delete weird file 2025-08-19 08:02:29 +08:00
Aaron Junker
639b29eb8c Fix pinning and unpinning shortcuts 2025-08-19 08:02:29 +08:00
Aaron Junker
bff3874b5f Only display powertoys shortcuts if the modules are enabled 2025-08-19 08:02:29 +08:00
Aaron Junker
eff58e1df5 Fix closing by shortcut add closing by ESC and fix missing files from CPPProject 2025-08-19 08:02:29 +08:00
Aaron Junker
411f4df2c0 Remove legacy shortcut behaviour 2025-08-19 08:02:29 +08:00
Aaron Junker
7dc8c1000b Remove old Shortcut Guide 2025-08-19 08:02:23 +08:00
Aaron Junker
48d8e33375 Refactoring 2025-08-19 08:00:02 +08:00
Aaron Junker
afc27e873f Remove some hosts references and fix close button 2025-08-19 08:00:02 +08:00
Aaron Junker
3302e61d72 Refactoring and localisation 2025-08-19 08:00:02 +08:00
Aaron Junker
e6edca93e7 Add taskbar indicators 2025-08-19 07:59:56 +08:00
Aaron Junker
7acab452d5 Handle errors displaying app and close window automatically on focus change 2025-08-19 07:59:29 +08:00
Aaron Junker
0a07811233 Add keyboard accelerator to the search box 2025-08-19 07:59:29 +08:00
Aaron Junker
9ecf82d2ea Add copying keyboard manifests and other improvements 2025-08-19 07:59:19 +08:00
Aaron Junker
44d12c6e63 Add support for multiple shortcuts 2025-08-19 07:58:42 +08:00
Aaron Junker
6b8a3e65f7 push 2025-08-19 07:58:42 +08:00
Aaron Junker
2b16068a7d Rename YmlInterpreter to ManifestInterpreter 2025-08-19 07:58:42 +08:00
Aaron Junker
440e75184a Fix error messages and read application titles out of index manifest 2025-08-19 07:58:42 +08:00
Aaron Junker
acf510dff5 Fix display on monitor with mouse and move all NaticeMethods to NativeMethods.cs 2025-08-19 07:58:42 +08:00
Aaron Junker
ddd090cc81 Code cleanup 2025-08-19 07:58:42 +08:00
Aaron Junker
2f4766df19 Push 2025-08-19 07:58:42 +08:00
Aaron Junker
6558260c53 Push 2025-08-19 07:58:42 +08:00
Aaron Junker
55b3e15f10 Changed style a little bit 2025-08-19 07:58:42 +08:00
Aaron Junker
69c6475e15 [WIP] Shortcut Guide V2 2025-08-19 07:58:21 +08:00
Aaron Junker
8e7be164a9 Change display name of File Explorer, hide taskbar indicators on other pages then Windows -> Overview and fix height of Windows -> Overview 2025-08-07 11:57:04 +02:00
Aaron Junker
f42b3922c7 fix xaml styling 2025-08-05 10:33:42 +02:00
Aaron Junker
d568d16560 git messed up 2025-08-05 00:06:07 +02:00
Aaron Junker
0abae1d190 close infotip when link is clicked and remove unneccesairy grid 2025-08-04 23:51:18 +02:00
Aaron Junker
271e0c0533 Change oobe design 2025-08-04 23:34:23 +02:00
Aaron Junker
6bd5c4c811 Change some StaticResources to ThemeResources and change style of taskbar indicators 2025-08-03 22:37:40 +02:00
Aaron Junker
a41be807a4 Fix styling 2025-08-03 16:31:57 +02:00
Aaron Junker
e11626550e Factor out TaskbarIndicator 2025-08-03 16:30:59 +02:00
Aaron Junker
7266745124 Fix xaml styling 2025-08-01 17:53:23 +02:00
Aaron Junker
77a5bc2ff5 Adress some PR comments and fix some bugs 2025-08-01 17:51:32 +02:00
Aaron Junker
0b6683eb34 Make some adjustants to how the windows key is displayed 2025-08-01 17:06:54 +02:00
Aaron Junker
3796fdb706 Forgot notice.md and CPPProject has some trouble buildinng release x64 2025-07-30 18:17:26 +02:00
Aaron Junker
2d12932e44 Remove failing test 2025-07-30 17:31:31 +02:00
Aaron Junker
1da76e55bb Merge branch 'feature/shortcutguidev2' of https://github.com/microsoft/PowerToys into feature/shortcutguidev2 2025-07-30 17:21:46 +02:00
Aaron Junker
3c1a6a5b16 That is a kinda embarrasing error 2025-07-30 17:21:37 +02:00
Noraa Junker-Wildi
3b77feb879 Merge branch 'main' into feature/shortcutguidev2 2025-07-30 16:58:28 +02:00
Aaron Junker
7e7bb04d48 So something was not right. Hopefully this fixes it. 2025-07-30 16:50:20 +02:00
Aaron Junker
273b50cb16 Fix arm64 configuration 2025-07-29 18:51:21 +02:00
Aaron Junker
498c8d534f Fix xaml styling 2025-07-29 18:01:23 +02:00
Aaron Junker
0e2f466454 Fix building in release mode and some other stuff 2025-07-29 17:48:28 +02:00
Aaron Junker
1982f2615d Add documentation and only export in tasklist_positions what needs to be exported 2025-07-29 15:37:48 +02:00
Aaron Junker
2f89281178 Refactoring, commenting and fixing some little lefrover bugs 2025-07-28 16:12:36 +02:00
Aaron Junker
56f056e492 Add explorer shortcuts, fix animation stopping and add an error when index.yml generation fails 2025-07-28 14:08:42 +02:00
Aaron Junker
71dd8fe83f Add attribution in settings 2025-07-28 02:07:14 +02:00
Aaron Junker
f9183af53d Add welcome screen and update settings and OOBE 2025-07-28 02:02:55 +02:00
Aaron Junker
0f85f8bad6 Respect excluded apps 2025-07-27 23:48:49 +02:00
Aaron Junker
e0e7bf4df2 Respect theme selection 2025-07-27 22:45:14 +02:00
Aaron Junker
b12fcf6699 Localization 2025-07-27 22:06:15 +02:00
Aaron Junker
2ee02c4bbe Fix spelling 2025-07-27 21:12:12 +02:00
Aaron Junker
a306797d21 Make UI better 2025-07-27 21:11:16 +02:00
Aaron Junker
7e50caa04e Add disclaimers 2025-07-27 20:43:27 +02:00
Aaron Junker
e3b1ec356e commit 2025-07-27 20:30:03 +02:00
Aaron Junker
fa54b49fca Make settings button work and add settings placeholder 2025-07-27 20:29:36 +02:00
Aaron Junker
7e2fc4481d Add taskbar launch shortcuts and make powertoys shortcuts empty by default 2025-07-27 20:15:01 +02:00
Aaron Junker
201a27d2bb Add taskbar launch shortcuts and make powertoys shortcuts empty by default 2025-07-27 20:09:54 +02:00
Aaron Junker
fe3d481407 Fix spelling 2025-07-27 19:48:55 +02:00
Aaron Junker
3475c92f32 Delete weird file 2025-07-27 19:42:18 +02:00
Aaron Junker
82b0ca71fd Fix pinning and unpinning shortcuts 2025-07-27 19:39:43 +02:00
Aaron Junker
3a8431ae9d Only display powertoys shortcuts if the modules are enabled 2025-07-27 18:48:32 +02:00
Aaron Junker
eed6dc6f8d Merge branch 'feature/shortcutguidev2' of https://github.com/microsoft/PowerToys into feature/shortcutguidev2 2025-07-27 18:17:41 +02:00
Aaron Junker
038cd23423 Merge branch 'feature/shortcutguidev2' of https://github.com/microsoft/PowerToys into feature/shortcutguidev2 2025-07-27 18:17:39 +02:00
Aaron Junker
be799ddd82 Merge branch 'feature/shortcutguidev2' of https://github.com/microsoft/PowerToys into feature/shortcutguidev2 2025-07-27 18:00:52 +02:00
Aaron Junker
e26bf2acd6 Merge branch 'feature/shortcutguidev2' of https://github.com/microsoft/PowerToys into feature/shortcutguidev2 2025-07-27 18:00:49 +02:00
Aaron Junker
95e0a20444 Merge branch 'feature/shortcutguidev2' of https://github.com/microsoft/PowerToys into feature/shortcutguidev2 2025-07-27 17:47:27 +02:00
Aaron Junker
3e75fb0c52 Merge main in 2025-07-27 17:46:58 +02:00
Aaron Junker
ba4098960c Merge main in 2025-07-27 17:46:48 +02:00
Aaron Junker
1580279be1 Fix closing by shortcut add closing by ESC and fix missing files from CPPProject 2025-07-27 17:42:41 +02:00
Aaron Junker
07760e4730 Remove legacy shortcut behaviour 2025-07-27 16:59:25 +02:00
Aaron Junker
d73ab4f2d3 Remove old Shortcut Guide 2025-07-27 16:40:44 +02:00
Aaron Junker
a6b761433e Refactoring 2025-06-18 21:05:34 +02:00
Aaron Junker
da77396da5 Remove some hosts references and fix close button 2025-06-15 23:20:26 +02:00
Aaron Junker
46df48684d Refactoring and localisation 2025-06-15 22:13:41 +02:00
Aaron Junker
7596e965ef Add taskbar indicators 2025-06-13 23:37:54 +02:00
Aaron Junker
0b823ea8bd Handle errors displaying app and close window automatically on focus change 2025-06-11 15:41:39 +02:00
Aaron Junker
54d176c4c4 Add keyboard accelerator to the search box 2025-06-11 15:33:57 +02:00
Aaron Junker
569f07268b Add copying keyboard manifests and other improvements 2025-06-11 15:26:34 +02:00
Aaron Junker
7ce5182695 Add support for multiple shortcuts 2025-06-07 02:21:34 +02:00
Aaron Junker
b16b4579fa push 2025-06-06 23:32:40 +02:00
Aaron Junker
a292a92f4d Merge main 2025-06-06 22:20:01 +02:00
Aaron Junker
6952deb4ae Rename YmlInterpreter to ManifestInterpreter 2024-11-10 15:06:36 +01:00
Aaron Junker
da7b789bfe Fix error messages and read application titles out of index manifest 2024-11-10 15:05:34 +01:00
Aaron Junker
a14c458f19 Fix display on monitor with mouse and move all NaticeMethods to NativeMethods.cs 2024-11-04 00:17:43 +01:00
Aaron Junker
22dc870991 Code cleanup 2024-11-04 00:11:16 +01:00
Aaron Junker
d5f5500347 Push 2024-11-03 22:06:38 +01:00
Aaron Junker
c81a423880 Push 2024-11-02 15:10:33 +01:00
Aaron Junker
7a6189ba3e Changed style a little bit 2024-10-14 20:37:55 +02:00
Aaron Junker
03587ae800 [WIP] Shortcut Guide V2 2024-10-14 19:02:22 +02:00
283 changed files with 3258 additions and 6895 deletions

View File

@@ -365,10 +365,7 @@ FILESYSONLY
URLIS
WAITTIMEOUT
DEFAULTTONEAREST
DWRITE
LWIN
VCENTER
VREDRAW
# COM/WinRT interface prefixes and type fragments
BAlt

View File

@@ -105,9 +105,7 @@
^src/common/ManagedCommon/ColorFormatHelper\.cs$
^src/common/notifications/BackgroundActivatorDLL/cpp\.hint$
^src/common/sysinternals/Eula/
^src/modules/cmdpal/Tests/Microsoft\.CommandPalette\.Extensions\.Toolkit\.UnitTests/FuzzyMatcherComparisonTests.cs$
^src/modules/cmdpal/Tests/Microsoft\.CommandPalette\.Extensions\.Toolkit\.UnitTests/FuzzyMatcherDiacriticsTests.cs$
^src/modules/cmdpal/doc/initial-sdk-spec/list-elements-mock-002\.pdn$
^doc/devdocs/modules/cmdpal/initial-sdk-spec/list-elements-mock-002\.pdn$
^src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleMarkdownImagesPage\.cs$
^src/modules/cmdpal/Microsoft\.CmdPal\.UI/Settings/InternalPage\.SampleData\.cs$
^src/modules/cmdpal/Tests/Microsoft\.CmdPal\.Common\.UnitTests/.*\.TestData\.cs$

View File

@@ -1,6 +1,7 @@
AAAAs
abcdefghjkmnpqrstuvxyz
abgr
ABlocked
ABORTIFHUNG
ABOUTBOX
Abug
@@ -10,13 +11,18 @@ ACCESSDENIED
ACCESSTOKEN
acfs
ACIE
AClient
AColumn
ACR
acrt
ACTIVATEAPP
ACTIVATEOPTIONS
activationaction
adaptivecards
ADate
ADDSTRING
ADDUNDORECORD
ADifferent
ADMINS
adml
admx
@@ -30,8 +36,10 @@ AFX
agentskills
AGGREGATABLE
AHK
AHybrid
AIUI
akv
ALarger
ALIGNRIGHT
ALLAPPS
ALLCHILDREN
@@ -43,13 +51,17 @@ ALLOWUNDO
ALLVIEW
ALPHATYPE
altkey
AModifier
amr
ANDSCANS
animatedvisuals
Animnate
ANull
AOC
aocfnapldcnfbofgmbbllojgocaelgdd
AOklab
aot
APeriod
apicontract
apidl
APIENTRY
@@ -63,7 +75,6 @@ APPEXECLINK
appext
apphost
APPLICATIONFRAMEHOST
Applocal
appmanifest
APPMODEL
APPNAME
@@ -76,7 +87,9 @@ appxpackage
APSTUDIO
AQS
Aquadrant
ARandom
ARCHITEW
ARemapped
ARPINSTALLLOCATION
ARPPRODUCTICON
ARRAYSIZE
@@ -87,9 +100,11 @@ ARTIFACTSTAGINGDIRECTORY
asf
Ashcraft
AShortcut
ASingle
ASSOCCHANGED
ASSOCF
ASSOCSTR
ASUS
ASYNCWINDOWPLACEMENT
ASYNCWINDOWPOS
atl
@@ -120,6 +135,7 @@ Badmode
Badparam
bbwe
BCIE
bck
BESTEFFORT
bezelled
bhid
@@ -146,7 +162,9 @@ bluelightreductionstate
BLURBEHIND
BLURREGION
bmi
BNumber
BODGY
BOklab
BOOTSTRAPPERINSTALLFOLDER
Bootstrappers
BOTTOMALIGN
@@ -166,10 +184,11 @@ bugreport
bugreportfile
BUILDARCH
BUILDNUMBER
buildsystems
buildtransitive
builttoroam
BUNDLEINFO
BVal
BValue
byapp
BYCOMMAND
BYPOSITION
@@ -185,13 +204,18 @@ CAPTURECHANGED
CARETBLINKING
carlos
Carlseibert
CAtl
caub
CBN
cch
CCHDEVICENAME
CCHFORMNAME
CCom
CContext
CDeclaration
CDPX
Cds
CElems
CENTERALIGN
cer
certlm
@@ -205,10 +229,12 @@ CHILDACTIVATE
CHILDWINDOW
CHOOSEFONT
chu
Chunghwa
CIBUILD
cidl
CIELCh
cim
CImage
cla
CLASSDC
classguid
@@ -237,6 +263,7 @@ CMIC
CMINVOKECOMMANDINFO
CMINVOKECOMMANDINFOEX
CMN
CMock
CMONITORS
cmph
CNF
@@ -293,6 +320,7 @@ Cowait
cpcontrols
cph
cplusplus
CPower
cpptools
cppvsdbg
cppwinrt
@@ -311,9 +339,14 @@ CROPTOSQUARE
Crossdevice
crt
csdevkit
CSearch
CSettings
cso
CSOT
CSRW
CStyle
cswin
CTest
CTEXT
CTLCOLORSTATIC
CURRENTDIR
@@ -324,7 +357,9 @@ cursorwrap
customaction
CUSTOMACTIONTEST
CUSTOMFORMATPLACEHOLDER
CVal
cvd
CVirtual
CWMO
CXSCREEN
CXSMICON
@@ -337,6 +372,7 @@ Dac
dacl
DAffine
DAFFINETRANSFORM
DArchitectures
datareader
Datasheet
datatracker
@@ -352,6 +388,7 @@ DBT
DCapabilities
DCBA
DCOM
DComposition
DCR
ddc
DDEIf
@@ -368,6 +405,7 @@ DEFAULTICON
defaultlib
DEFAULTONLY
DEFAULTSIZE
defaulttonearest
DEFAULTTONULL
DEFAULTTOPRIMARY
DEFERERASE
@@ -400,7 +438,6 @@ DEVMODE
DEVMODEW
DEVNODES
devpal
devpackages
DEVTYP
dfx
DIALOGEX
@@ -416,6 +453,8 @@ DISPLAYFLAGS
DISPLAYFREQUENCY
displayname
DISPLAYORIENTATION
DISPLAYPORT
diu
divyan
DLGFRAME
dlgmodalframe
@@ -443,9 +482,9 @@ drawingcolor
dreamsofameaningfullife
drivedetectionwarning
DROPFILES
DSPDLOG
DSTINVERT
DString
DSVG
dto
DUMMYUNIONNAME
dumpbin
@@ -471,10 +510,12 @@ DWMWINDOWATTRIBUTE
DWMWINDOWMAXIMIZEDCHANGE
DWORDLONG
dworigin
dwrite
DWRITE
dxgi
Dxva
eab
EAccess
easeofaccess
ecount
edid
@@ -482,6 +523,8 @@ EDITKEYBOARD
EDITSHORTCUTS
EDITTEXT
eep
EFile
EInvalid
eku
emojis
ENABLEDELAYEDEXPANSION
@@ -491,24 +534,28 @@ ENABLETEMPLATE
encodedlaunch
encryptor
ENDSESSION
ENot
ENSUREVISIBLE
ENTERSIZEMOVE
ENTRYW
ENU
environmentvariables
EPO
EProvider
epu
ERASEBKGND
EREOF
EResize
ERRORIMAGE
ERRORTITLE
ESettings
esrp
etd
ETDT
etl
etw
eula
eurochange
eventvwr
evt
EWXFORCE
@@ -544,6 +591,7 @@ FANCYZONESEDITOR
FARPROC
fdw
fdx
FErase
fesf
FFFF
fffffffzzz
@@ -570,13 +618,16 @@ FILESYSPATH
Filetime
FILEVERSION
FILTERMODE
FInc
findfast
findmymouse
FIXEDFILEINFO
FIXEDSYS
flac
flyouts
FMask
fmtid
FNumber
FOF
FOFX
FOLDERID
@@ -589,6 +640,7 @@ formatetc
FORPARSING
foundrylocal
framechanged
FRestore
frm
FROMTOUCH
fsanitize
@@ -628,6 +680,7 @@ gfx
GHND
gitmodules
GMEM
GNumber
googleai
googlegemini
Gotchas
@@ -648,10 +701,12 @@ GSM
gtm
guiddata
GUITHREADINFO
GValue
gwl
GWLP
GWLSTYLE
hangeul
Hann
Hantai
Hanzi
Hardlines
@@ -684,6 +739,7 @@ hgdiobj
HGFE
hglobal
hhk
HHmmssfff
hhx
Hiber
Hiberboot
@@ -723,6 +779,7 @@ HORZSIZE
Hostbackdropbrush
hostfxr
hostsfileeditor
Hostx
hotfixes
hotkeycontrol
HOTKEYF
@@ -730,6 +787,7 @@ hotkeys
hotlight
hotspot
HPAINTBUFFER
HPhysical
HPS
HRAWINPUT
HREDRAW
@@ -740,11 +798,15 @@ HROW
hsb
HSCROLL
hsi
HSpeed
HSync
HTCLIENT
hthumbnail
HTOUCHINPUT
HTTRANSPARENT
hutchinsoniana
HVal
HValue
Hvci
hwb
HWHEEL
@@ -755,6 +817,7 @@ HWNDLAST
HWNDNEXT
HWNDPARENT
HWNDPREV
HWP
hyjiacan
IAI
icf
@@ -836,6 +899,7 @@ INVALIDARG
invalidoperatioexception
invokecommand
ipcmanager
IPREVIEW
ipreviewhandlervisualssetfont
IPTC
irow
@@ -851,8 +915,10 @@ issuecomment
istep
Italicise
ith
ITHUMBNAIL
IUI
IUWP
IVO
IWIC
jeli
jfif
@@ -862,6 +928,7 @@ jjw
jobject
JOBOBJECT
jpe
JPN
jpnime
jrsoftware
Jsons
@@ -869,6 +936,7 @@ jsonval
jxr
Kantai
KBSC
kdc
keybd
KEYBDDATA
KEYBDINPUT
@@ -886,7 +954,6 @@ keynum
keyremaps
keyring
keyvault
kfull
KILLFOCUS
killrunner
kmph
@@ -913,6 +980,7 @@ LEFTTEXT
Lenovo
LError
LEVELID
LExit
LFU
LGD
lhwnd
@@ -952,6 +1020,7 @@ lowlevel
LOWORD
lparam
LPBITMAPINFOHEADER
LPCFHOOKPROC
lpch
LPCITEMIDLIST
LPCLSID
@@ -970,6 +1039,7 @@ LPMONITORINFO
LPOSVERSIONINFOEXW
LPQUERY
lprc
LPrivate
LPSAFEARRAY
lpstr
lpsz
@@ -983,6 +1053,7 @@ LPW
lpwcx
lpwndpl
lquadrant
LReader
LRESULT
LSTATUS
lstrcmp
@@ -990,11 +1061,14 @@ lstrcmpi
lstrcpyn
lstrlen
LTEXT
LTM
LTRREADING
luid
LUMA
lusrmgr
LVal
LVDS
LWA
lwin
LWIN
LZero
MAGTRANSFORM
@@ -1058,10 +1132,13 @@ MINIMIZESTART
MINMAXINFO
minwindef
Mip
Miracast
miracast
mkdn
mlcfg
mmc
mmcexe
MMdd
mmi
mmsys
mobileredirect
@@ -1087,6 +1164,7 @@ mouseutils
MOVESIZEEND
MOVESIZESTART
MRM
MRT
mru
msaccess
MSAL
@@ -1097,6 +1175,8 @@ msdata
msdia
MSDL
MSGFLT
MSHCTX
MSHLFLAGS
msiexec
MSIFASTINSTALL
MSIHANDLE
@@ -1133,6 +1213,7 @@ myorg
myrepo
NAMECHANGE
namespaceanddescendants
Nanjing
nao
NCACTIVATE
ncc
@@ -1158,6 +1239,7 @@ netcpl
netframework
netsetup
netsh
newcolor
NEWDIALOGSTYLE
NEWFILE
NEWFILEHEADER
@@ -1170,6 +1252,7 @@ newrow
nicksnettravels
NIF
nightlight
NLog
NLSTEXT
NMAKE
NNN
@@ -1259,6 +1342,7 @@ OFN
ofs
OICI
OICIIO
oldcolor
olditem
oldpath
oldtheme
@@ -1289,6 +1373,7 @@ OUTOFCONTEXT
Outptr
outputtype
outsettings
outsourced
OVERLAPPEDWINDOW
Oversampling
OVERWRITEPROMPT
@@ -1315,6 +1400,7 @@ PATINVERT
PATPAINT
pbc
pbi
PBlob
PBP
pbrush
pcb
@@ -1325,7 +1411,6 @@ pchast
PCIDLIST
PCTSTR
PCWSTR
pdbs
PDBs
PDEVMODE
PDFs
@@ -1337,6 +1422,7 @@ pdto
pdtobj
pdw
Peb
PElems
Pels
PELSHEIGHT
PELSWIDTH
@@ -1353,6 +1439,7 @@ pguid
phbm
phbmp
phicon
PHL
Photoshop
photoshop
phwnd
@@ -1360,6 +1447,7 @@ pici
pidl
PIDLIST
pii
pinboard
pinfo
pinvoke
pipename
@@ -1384,9 +1472,7 @@ Pokedex
Pomodoro
popups
POPUPWINDOW
portfile
POSITIONITEM
Postbot
POWERBROADCAST
powerdisplay
POWERDISPLAYMODULEINTERFACE
@@ -1462,6 +1548,7 @@ psrm
psrree
pstatstg
pstm
PStr
pstream
pstrm
PSYSTEM
@@ -1472,6 +1559,7 @@ PTCHAR
ptcontrols
ptd
PTOKEN
PToy
ptstr
ptsym
pui
@@ -1482,6 +1570,7 @@ PWSTR
pwsz
pwtd
qdc
QDS
qit
QITAB
QITABENT
@@ -1496,7 +1585,9 @@ quicklinks
quickmask
QUNS
RAII
RAlt
randi
RAquadrant
rasterization
Rasterize
rasterizing
@@ -1514,6 +1605,7 @@ READMODE
READOBJECTS
recents
RECTDESTINATION
rectp
RECTSOURCE
recursesubdirs
recyclebin
@@ -1572,6 +1664,8 @@ RIDEV
RIGHTBUTTON
RIGHTSCROLLBAR
riid
RKey
RNumber
rollups
rop
ROUNDSMALL
@@ -1601,9 +1695,9 @@ SAMESHORTCUTPREVIOUSLYMAPPED
samsung
sancov
SAVEFAILED
scanled
schedtasks
SCID
SCL
Scode
SCREENFONTS
screenruler
@@ -1779,7 +1873,6 @@ STDAPI
stdc
stdcpp
stdcpplatest
stdext
STDMETHODCALLTYPE
STDMETHODIMP
steamapps
@@ -1810,6 +1903,7 @@ sublang
SUBMODULEUPDATE
subresource
sug
suntimes
Superbar
SUPPRESSMSGBOXES
sut
@@ -1817,6 +1911,7 @@ svchost
SVGIn
SVGIO
svgz
SVIDEO
SVSI
SWFO
swp
@@ -1884,6 +1979,7 @@ thickframe
THISCOMPONENT
threadpool
throughs
Tianma
TILEDWINDOW
TILLSON
timedate
@@ -1901,7 +1997,6 @@ TNP
Toggleable
tontrager
Toolhelp
toolsets
toolwindow
TOPDOWNDIB
TOUCHEVENTF
@@ -1934,11 +2029,16 @@ UACUI
UAL
uap
UBR
UBreak
ubrk
UCallback
ucrt
ucrtd
uefi
UError
uesc
UFlags
UHash
UIA
UIDs
UIEx
@@ -1947,6 +2047,8 @@ uitests
UITo
ULONGLONG
Ultrawide
UMax
UMin
ums
uncompilable
UNCPRIORITY
@@ -1965,11 +2067,12 @@ UNORM
unparsable
unremapped
Unsend
Unsubscribes
unsubscribes
untriaged
unvirtualized
unwide
unzoom
UOffset
UOI
UPDATENOW
updown
@@ -1985,6 +2088,7 @@ USEINSTALLERFORTEST
USESHOWWINDOW
USESTDHANDLES
USRDLL
UType
uuidv
uwp
uxt
@@ -1995,16 +2099,17 @@ valuegenerator
VARTYPE
vbcscompiler
vcamp
vcenter
VCENTER
vcgtq
VCINSTALLDIR
vcp
Vcpkg
vcpkg
vcpname
VCRT
vcruntime
vcvars
VDesktop
vdupq
VERBSONLY
VERBW
@@ -2033,6 +2138,7 @@ vorrq
VOS
vpaddlq
vqsubq
vredraw
VREDRAW
vreinterpretq
VSC
@@ -2045,20 +2151,24 @@ VSINSTALLDIR
VSM
vso
vsonline
VSpeed
vstemplate
vstest
VSTHRD
vstprintf
VSTT
vswhere
VSync
Vtbl
WANTNUKEWARNING
WANTPALM
WASDK
wbem
WBounds
Wca
WCE
wcex
WClass
WCRAPI
wcsicmp
wcsncpy
@@ -2141,6 +2251,7 @@ WNDCLASSW
wndproc
wnode
wom
workerw
WORKSPACESEDITOR
WORKSPACESLAUNCHER
WORKSPACESSNAPSHOTTOOL
@@ -2155,6 +2266,7 @@ wpr
wprp
wql
wregex
WReserved
WResize
WRITEOBJECTS
Wrk
@@ -2172,23 +2284,49 @@ Wubi
WUX
Wwanpp
xap
XAxis
XButton
Xbuttondown
xclip
xcopy
XDeployment
xdf
XDimension
XDocument
XElement
xfd
XFile
XIncrement
XLoc
xmp
XNamespace
Xoshiro
XPels
XPixel
XPos
XResource
xsi
XSpeed
XStr
xstyler
XTimer
XUP
XVIRTUALSCREEN
XXL
xxxxxx
YAxis
ycombinator
YDimension
YIncrement
yinle
yinyue
yoko
YPels
YPos
YResolution
YSpeed
YStr
YTimer
YVIRTUALSCREEN
zamora
Zenbook

View File

@@ -163,7 +163,7 @@ configuration:
association: Collaborator
then:
- addReply:
reply: We've identified this issue as a duplicate of an existing one and are closing this thread so discussion stays in one place.<br/><br/>Please see the comment above for the link to the original tracking issue, and feel free to subscribe there for updates.
reply: Hi! We've identified this issue as a duplicate of another one that already exists on this Issue Tracker. This specific instance is being closed in favor of tracking the concern over on the referenced thread. Thanks for your report!
- closeIssue
- removeLabel:
label: Needs-Triage

View File

@@ -9,22 +9,21 @@
*/
const fs = require('node:fs');
const REVIEWER_LOGIN = 'chatasweetie';
const REVIEWER_MENTION = `@${REVIEWER_LOGIN}`;
const COMMENT_MARKER = '<!-- telemetry-event-check -->';
const COMMENT_BODY_WITH_PRIVACY_UPDATE = `${COMMENT_MARKER}
Thank you for contributing to PowerToys. We've detected that this PR might include a new or modified telemetry event. After this PR is merged, please follow these next steps:
THIS IS A TEST | @chatasweetie is testing this functionality
Thanks for contributing to PowerToys. This change might include a new or modified telemetry event, and we want to help make sure you can get your data end to end.
- [ ] Reach out to Jessica (${REVIEWER_MENTION}) to follow up on the next steps: https://aka.ms/pt-telemetry-process
`;
1. Reach out to Jessica (@chatasweetie) to follow up on the next steps to add these telemetry events to our pipelines.`;
const COMMENT_BODY_WITHOUT_PRIVACY_UPDATE = `${COMMENT_MARKER}
Thank you for contributing to PowerToys. We've detected that this PR might include a new or modified telemetry event. Please ensure the following before merging:
THIS IS A TEST | @chatasweetie is testing this functionality
Thanks for contributing to PowerToys. This change might include a new or modified telemetry event, and we want to help make sure you can get your data end to end.
- [ ] Add your telemetry events to [DATA_AND_PRIVACY](https://github.com/microsoft/PowerToys/blob/main/DATA_AND_PRIVACY.md).md within this PR.
1. Make sure to add your telemetry events to DATA_AND_PRIVACY.md.
- [ ] Reach out to Jessica (${REVIEWER_MENTION}) to follow up on the next steps: https://aka.ms/pt-telemetry-process`;
2. Reach out to Jessica (@chatasweetie) to follow up on the next steps to add these telemetry events to our pipelines.`;
const TELEMETRY_PATH_PATTERNS = [
/(^|\/)trace\.(h|hpp|cpp|cs)$/i,
@@ -192,48 +191,6 @@ async function getAllPullFiles(apiBaseUrl, repository, pullNumber) {
return files;
}
async function getPullRequest(apiBaseUrl, repository, pullNumber) {
const url = `${apiBaseUrl}/repos/${repository}/pulls/${pullNumber}`;
const pullRequest = await apiRequest(url);
if (!pullRequest || typeof pullRequest !== 'object') {
throw new Error('Unexpected response while fetching pull request details.');
}
return pullRequest;
}
async function ensureReviewerRequested(apiBaseUrl, repository, pullNumber, pullRequest) {
const authorLogin = String(pullRequest?.user?.login || '').toLowerCase();
const targetReviewer = REVIEWER_LOGIN.toLowerCase();
if (authorLogin === targetReviewer) {
console.log(`Skipping reviewer request: ${REVIEWER_LOGIN} is the PR author.`);
return;
}
const requestedReviewers = Array.isArray(pullRequest?.requested_reviewers)
? pullRequest.requested_reviewers
: [];
const alreadyRequested = requestedReviewers.some(
(reviewer) => String(reviewer?.login || '').toLowerCase() === targetReviewer
);
if (alreadyRequested) {
console.log(`Reviewer ${REVIEWER_LOGIN} is already requested.`);
return;
}
const url = `${apiBaseUrl}/repos/${repository}/pulls/${pullNumber}/requested_reviewers`;
try {
await apiRequest(url, 'POST', { reviewers: [REVIEWER_LOGIN] });
console.log(`Requested reviewer ${REVIEWER_LOGIN}.`);
} catch (error) {
// Reviewer request should not fail the telemetry guidance workflow.
console.warn(
`Unable to request reviewer ${REVIEWER_LOGIN}: ${error instanceof Error ? error.message : String(error)}`
);
}
}
async function findExistingTelemetryComment(apiBaseUrl, repository, pullNumber) {
let page = 1;
@@ -353,16 +310,6 @@ async function main() {
);
}
try {
const pullRequest = await getPullRequest(parsedApiBaseUrl.origin, repository, pullNumber);
await ensureReviewerRequested(parsedApiBaseUrl.origin, repository, pullNumber, pullRequest);
} catch (error) {
console.warn(
'Failed to fetch PR details or request reviewer; continuing to post telemetry guidance comment.'
);
console.warn(error instanceof Error ? error.stack || error.message : error);
}
const commentBody = dataAndPrivacyChanged
? COMMENT_BODY_WITH_PRIVACY_UPDATE
: COMMENT_BODY_WITHOUT_PRIVACY_UPDATE;

5
.gitignore vendored
View File

@@ -370,8 +370,3 @@ installer/*/*.wxs.bk
.squad-workstream
.github/agents/**squad**.md
.github/workflows/**squad**.yml
# vcpkg manifest mode installed packages
vcpkg_installed/
deps/vcpkg/

6
.gitmodules vendored Normal file
View File

@@ -0,0 +1,6 @@
[submodule "deps/spdlog"]
path = deps/spdlog
url = https://github.com/gabime/spdlog.git
[submodule "deps/expected-lite"]
path = deps/expected-lite
url = https://github.com/martinmoene/expected-lite.git

View File

@@ -212,7 +212,6 @@
"WinUI3Apps\\PowerToys.NewPlus.ShellExtension.win10.dll",
"PowerAccent.Core.dll",
"PowerAccent.Common.dll",
"PowerToys.PowerAccent.dll",
"PowerToys.PowerAccent.exe",
"PowerToys.PowerAccentModuleInterface.dll",
@@ -392,7 +391,6 @@
"WinUI3Apps\\Google.Apis.Auth.dll",
"WinUI3Apps\\Google.Apis.Core.dll",
"WinUI3Apps\\Google.GenAI.dll",
"WinUI3Apps\\YamlDotNet.dll",
"boost_regex-vc143-mt-gd-x32-1_87.dll",
"boost_regex-vc143-mt-gd-x64-1_87.dll",

View File

@@ -104,10 +104,6 @@ extends:
# Have msbuild use the release nuget config profile
additionalBuildOptions: /p:RestoreConfigFile="$(Build.SourcesDirectory)\.pipelines\release-nuget.config" /p:EnableCmdPalAOT=true
beforeBuildSteps:
# Install the Terrapin retrieval tool, which replaces vcpkg's download handler
# to redirect it to a safe Microsoft-controlled location
- template: .pipelines/v2/templates/steps-install-terrapin.yml@self
# Sets versions for all PowerToy created DLLs
- pwsh: |-
.pipelines/versionSetting.ps1 -versionNumber '${{ parameters.versionNumber }}' -DevEnvironment ''
@@ -144,10 +140,6 @@ extends:
signCertName: $(SigningSignCertName)
useManagedIdentity: $(SigningUseManagedIdentity)
clientId: $(SigningOriginalClientId)
beforeBuildSteps:
# Install the Terrapin retrieval tool, which replaces vcpkg's download handler
# to redirect it to a safe Microsoft-controlled location
- template: .pipelines/v2/templates/steps-install-terrapin.yml@self
- stage: Publish
displayName: Publish

View File

@@ -270,34 +270,6 @@ jobs:
parameters:
directory: $(build.sourcesdirectory)\src\modules\cmdpal
# --- vcpkg detection + binary cache --------------------------------------
# PowerToys consumes spdlog (and, over time, other native deps) via vcpkg in
# manifest mode. steps-install-vcpkg.yml prefers the vcpkg shipped with
# Visual Studio (Microsoft.VisualStudio.Component.Vcpkg) and falls back to a
# fresh clone of microsoft/vcpkg into deps/vcpkg if VS doesn't have it.
# Either way it sets the VCPKG_ROOT pipeline variable; MSBuild integration
# is wired globally from Cpp.Build.props (with vcpkg.targets in
# Cpp.Build.targets) using the three-tier VcpkgRoot fallback
# (env var > VS-shipped > deps/vcpkg runtime clone).
#
# Vcpkg's MSBuild integration runs `vcpkg install` once per project, so the
# binary cache below saves ~3-5 minutes per triplet on cache hits.
- template: .\steps-install-vcpkg.yml
parameters:
useVSPreview: ${{ parameters.useVSPreview }}
- ${{ if eq(parameters.enablePackageCaching, true) }}:
- task: Cache@2
displayName: 'Cache vcpkg binary archives'
inputs:
# Key on the inputs vcpkg uses to compute its package ABI: the manifest,
# configuration, every overlay-port file, and the agent OS.
key: '"vcpkg" | "$(Agent.OS)" | vcpkg.json | vcpkg-configuration.json | deps/vcpkg-overlays/**'
restoreKeys: |
"vcpkg" | "$(Agent.OS)"
"vcpkg"
path: $(LOCALAPPDATA)\vcpkg\archives
- ${{ parameters.beforeBuildSteps }}

View File

@@ -15,9 +15,6 @@ parameters:
- name: signingIdentity
type: object
default: {}
- name: beforeBuildSteps
type: stepList
default: []
jobs:
- job: "BuildSDK"
@@ -48,8 +45,6 @@ jobs:
parameters:
directory: $(build.sourcesdirectory)\src\modules\cmdpal
- ${{ parameters.beforeBuildSteps }}
- pwsh: |-
& "$(build.sourcesdirectory)\src\modules\cmdpal\extensionsdk\nuget\BuildSDKHelper.ps1" -Configuration "Release" -BuildStep "build" -IsAzurePipelineBuild
displayName: Build SDK

View File

@@ -1,6 +0,0 @@
steps:
- pwsh: |-
nuget install -source "https://microsoft.pkgs.visualstudio.com/Dart/_packaging/PowerToysDependencies/nuget/v3/index.json" TerrapinRetrievalTool -Prerelease -OutputDirectory _trt -Config "$(Build.SourcesDirectory)\.pipelines\release-nuget.config"
$TerrapinRetrievalToolPath = (Get-Item _trt\TerrapinRetrievalTool.*\win-x64\TerrapinRetrievalTool.exe).FullName
Write-Host "##vso[task.setvariable variable=X_VCPKG_ASSET_SOURCES]x-script,${TerrapinRetrievalToolPath} -b https://vcpkg.storage.devpackages.microsoft.io/artifacts/ -a true -u None -p {url} -s {sha512} -d {dst};x-block-origin"
displayName: Set up the Terrapin Retrieval Tool (vcpkg cache)

View File

@@ -1,41 +0,0 @@
# Adapted from microsoft/terminal build/pipelines/templates-v2/steps-install-vcpkg.yml.
#
# Detects vcpkg from (in order):
# 1. The Visual Studio installation (Microsoft.VisualStudio.Component.Vcpkg,
# declared in the repo-root .vsconfig).
# 2. A local clone at deps/vcpkg, cloned and bootstrapped on demand.
#
# Sets the pipeline-scoped VCPKG_ROOT variable; the rest of the build
# resolves vcpkg through it (see the three-tier VcpkgRoot fallback in
# Cpp.Build.props). No repo-level vcpkg submodule required.
parameters:
- name: useVSPreview
type: boolean
default: false
steps:
- pwsh: |-
# vswhere -prerelease is opt-in via the useVSPreview parameter so CI on
# stable VS doesn't accidentally pick up a Preview install when both
# are present. Matches the existing useVSPreview plumbing for
# verifyAndSetLatestVCToolsVersion.ps1.
$vswhereArgs = @('-latest', '-requires', 'Microsoft.VisualStudio.Component.Vcpkg', '-property', 'installationPath')
$useVSPreview = '${{ parameters.useVSPreview }}' -eq 'True'
if ($useVSPreview) { $vswhereArgs = @('-prerelease') + $vswhereArgs }
$VsInstallRoot = & 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe' @vswhereArgs
If ([String]::IsNullOrEmpty($VsInstallRoot)) {
Remove-Item -Recurse -Force deps/vcpkg -ErrorAction:Ignore
git clone https://github.com/microsoft/vcpkg deps/vcpkg
if ($LASTEXITCODE -ne 0) { throw "git clone vcpkg failed (exit $LASTEXITCODE)" }
Push-Location deps/vcpkg
& ./bootstrap-vcpkg.bat -disableMetrics
if ($LASTEXITCODE -ne 0) { Pop-Location; throw "bootstrap-vcpkg failed (exit $LASTEXITCODE)" }
$VcpkgRoot = $PWD
Pop-Location
Write-Host "Using vcpkg from local checkout ($VcpkgRoot)"
} Else {
$VcpkgRoot = Join-Path $VsInstallRoot 'VC\vcpkg'
Write-Host "Using vcpkg from Visual Studio installation ($VcpkgRoot)"
}
Write-Host "##vso[task.setvariable variable=VCPKG_ROOT]$VcpkgRoot"
displayName: Detect VS vcpkg or bootstrap locally

View File

@@ -48,11 +48,6 @@ foreach ($csprojFile in $csprojFilesArray) {
continue
}
# The PowerAccent.Common project does not target WinRT, so skip it
if ($csprojFile -like '*PowerAccent.Common.csproj') {
continue
}
$importExists = Test-ImportSharedCsWinRTProps -filePath $csprojFile
if (!$importExists) {
Write-Output "$csprojFile need to import 'Common.Dotnet.CsWinRT.props'."

View File

@@ -18,7 +18,6 @@
"Microsoft.VisualStudio.Component.VC.ATL.ARM64.Spectre",
"Microsoft.VisualStudio.Component.VC.ATL",
"Microsoft.VisualStudio.Component.VC.ATL.Spectre",
"Microsoft.VisualStudio.Component.Vcpkg",
"Microsoft.VisualStudio.ComponentGroup.WindowsAppSDK.Cs"
]
}

View File

@@ -39,8 +39,7 @@
<PropertyGroup>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
<PreferredToolArchitecture Condition="'$(PROCESSOR_ARCHITECTURE)' == 'ARM64' or '$(PROCESSOR_ARCHITEW6432)' == 'ARM64'">arm64</PreferredToolArchitecture>
<!-- vcpkg.targets is imported via Cpp.Build.targets after Microsoft.Cpp.targets. -->
<ForceImportAfterCppTargets>$(MSBuildThisFileDirectory)Cpp.Build.targets</ForceImportAfterCppTargets>
<VcpkgEnabled>false</VcpkgEnabled>
<ReplaceWildcardsInProjectItems>true</ReplaceWildcardsInProjectItems>
<ExternalIncludePath>$(MSBuildThisFileDirectory)deps;$(MSBuildThisFileDirectory)packages;$(ExternalIncludePath)</ExternalIncludePath>
<!-- Enable control flow guard for C++ projects that don't consume any C++ files -->
@@ -122,48 +121,6 @@
<SpectreMitigation>Spectre</SpectreMitigation>
</PropertyGroup>
<!--
vcpkg integration. Set globally and loaded before Microsoft.Cpp.props (via
ForceImportBeforeCppProps) so that vcpkg.props' ClCompile hook is in place
before the C++ targets run. VcpkgRoot is resolved via the same three-tier
fallback used by microsoft/terminal (env var → VS-shipped → deps/vcpkg).
-->
<PropertyGroup Label="vcpkg">
<VcpkgEnabled>true</VcpkgEnabled>
<VcpkgEnableManifest>true</VcpkgEnableManifest>
<VcpkgManifestEnabled>true</VcpkgManifestEnabled>
<VcpkgManifestRoot>$(MSBuildThisFileDirectory)</VcpkgManifestRoot>
<VcpkgOSTarget>windows</VcpkgOSTarget>
<VcpkgUseStatic>true</VcpkgUseStatic>
<!--
Force VcpkgConfiguration to follow $(Configuration). Without this,
vcpkg.props infers VcpkgConfiguration from $(UseDebugLibraries), which
Microsoft.Cpp.Default.props has already defaulted to 'false' by the
time vcpkg.props is imported here (the PowerToys-wide Debug override
below runs LATER). That would silently link the Release-built spdlog
into Debug consumers and trigger LNK2038 (MT/MTd, _ITERATOR_DEBUG_LEVEL).
-->
<VcpkgConfiguration>$(Configuration)</VcpkgConfiguration>
<!-- vcpkg validates triplets case-sensitively; PowerToys uses ARM64 capital-case. -->
<VcpkgPlatformTarget Condition="'$(Platform)' == 'ARM64'">arm64</VcpkgPlatformTarget>
<VcpkgApplocalDeps>false</VcpkgApplocalDeps>
<VcpkgInstalledDir>$(MSBuildThisFileDirectory)vcpkg_installed\$(Platform)\</VcpkgInstalledDir>
<VcpkgRoot Condition="'$(VcpkgRoot)' == ''">$(VCPKG_ROOT)</VcpkgRoot>
<VcpkgRoot Condition="'$(VcpkgRoot)' == '' and '$(VsInstallRoot)' != ''">$(VsInstallRoot)\VC\vcpkg</VcpkgRoot>
<VcpkgRoot Condition="'$(VcpkgRoot)' == '' or !Exists('$(VcpkgRoot)\vcpkg.exe')">$(MSBuildThisFileDirectory)deps\vcpkg</VcpkgRoot>
<CAExcludePath>$(CAExcludePath);$(VcpkgInstalledDir)</CAExcludePath>
<VCPkgLocalAppDataDisabled>true</VCPkgLocalAppDataDisabled>
</PropertyGroup>
<!-- Fail fast with an actionable message instead of opaque C1083 spdlog/spdlog.h errors. -->
<Target Name="PowerToysEnsureVcpkgAvailable"
BeforeTargets="PrepareForBuild"
Condition="'$(MSBuildProjectExtension)' == '.vcxproj' and '$(VcpkgEnabled)' == 'true' and !Exists('$(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg.props')">
<Error Text="PowerToys requires the 'vcpkg' Visual Studio component, but it was not found.%0A%0AOpen the Visual Studio Installer, click Modify on your VS install, search for 'vcpkg', enable 'C++ vcpkg package manager', and click Modify. (Visual Studio will also prompt you to install missing .vsconfig components when you open PowerToys.slnx.)%0A%0AIf you have vcpkg installed elsewhere, set the VCPKG_ROOT environment variable to its root before building.%0A%0ASearched: '$(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg.props'" />
</Target>
<Import Project="$(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg.props"
Condition="'$(MSBuildProjectExtension)' == '.vcxproj' and Exists('$(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg.props')" />
<!-- Debug/Release props -->
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<!--
PowerToys global C++ post-targets. Wired in via
<ForceImportAfterCppTargets> in Cpp.Build.props so MSBuild loads this
file AFTER Microsoft.Cpp.targets for every .vcxproj.
Conditionally imports vcpkg.targets to hook ClCompile into vcpkg's
VcpkgInstallManifestDependencies target so spdlog headers are
auto-discovered on the include path and spdlog.lib is auto-linked.
vcpkg.props is imported in Cpp.Build.props (before Microsoft.Cpp.props);
vcpkg.targets needs the matching "after" hook here.
-->
<Import Project="$(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg.targets"
Condition="'$(MSBuildProjectExtension)' == '.vcxproj' and '$(VcpkgEnabled)' == 'true' and Exists('$(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg.targets')" />
</Project>

View File

@@ -41,21 +41,21 @@
<PackageVersion Include="MessagePack" Version="3.1.3" />
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.102" />
<PackageVersion Include="Microsoft.CommandPalette.Extensions" Version="0.9.260303001" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="10.0.8" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="10.0.7" />
<!-- Including Microsoft.Bcl.AsyncInterfaces to force version, since it's used by Microsoft.SemanticKernel. -->
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.8" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.7" />
<PackageVersion Include="Microsoft.Graphics.Win2D" Version="1.3.2" />
<PackageVersion Include="Microsoft.Windows.CppWinRT" Version="2.0.250303.1" />
<PackageVersion Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="3.1.16" />
<PackageVersion Include="Microsoft.Extensions.AI" Version="10.2.0" />
<PackageVersion Include="Microsoft.Extensions.AI.OpenAI" Version="10.0.1-preview.1.25571.5" />
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="10.0.7" />
<PackageVersion Include="Microsoft.AI.Foundry.Local" Version="0.3.0" />
<PackageVersion Include="Microsoft.SemanticKernel" Version="1.71.0" />
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.OpenAI" Version="1.71.0" />
@@ -66,9 +66,9 @@
<PackageVersion Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.2" />
<PackageVersion Include="Microsoft.Web.WebView2" Version="1.0.3719.77" />
<!-- 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="10.0.8" />
<PackageVersion Include="Microsoft.Win32.SystemEvents" Version="10.0.7" />
<PackageVersion Include="Microsoft.WindowsPackageManager.ComInterop" Version="1.10.340" />
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="10.0.8" />
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="10.0.7" />
<PackageVersion Include="Microsoft.Windows.CsWin32" Version="0.3.269" />
<!-- 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. -->
<!--
@@ -106,28 +106,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="10.0.8" />
<PackageVersion Include="System.CodeDom" Version="10.0.7" />
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
<PackageVersion Include="System.ComponentModel.Composition" Version="10.0.8" />
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="10.0.8" />
<PackageVersion Include="System.Data.OleDb" Version="10.0.8" />
<PackageVersion Include="System.ComponentModel.Composition" Version="10.0.7" />
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="10.0.7" />
<PackageVersion Include="System.Data.OleDb" Version="10.0.7" />
<!-- 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="10.0.8" />
<PackageVersion Include="System.Diagnostics.EventLog" Version="10.0.7" />
<!-- 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="10.0.8" />
<PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="10.0.7" />
<PackageVersion Include="System.ClientModel" Version="1.8.1" />
<PackageVersion Include="System.Drawing.Common" Version="10.0.8" />
<PackageVersion Include="System.Drawing.Common" Version="10.0.7" />
<PackageVersion Include="System.IO.Abstractions" Version="22.0.13" />
<PackageVersion Include="System.IO.Abstractions.TestingHelpers" Version="22.0.13" />
<PackageVersion Include="System.Management" Version="10.0.8" />
<PackageVersion Include="System.Management" Version="10.0.7" />
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
<PackageVersion Include="System.Numerics.Tensors" Version="10.0.2" />
<PackageVersion Include="System.Private.Uri" Version="4.3.2" />
<PackageVersion Include="System.Reactive" Version="6.0.1" />
<PackageVersion Include="System.Runtime.Caching" Version="10.0.8" />
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="10.0.8" />
<PackageVersion Include="System.Text.Encoding.CodePages" Version="10.0.8" />
<PackageVersion Include="System.Text.Json" Version="10.0.8" />
<PackageVersion Include="System.Runtime.Caching" Version="10.0.7" />
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="10.0.7" />
<PackageVersion Include="System.Text.Encoding.CodePages" Version="10.0.7" />
<PackageVersion Include="System.Text.Json" Version="10.0.7" />
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
<PackageVersion Include="ToolGood.Words.Pinyin" Version="3.1.0.3" />
<PackageVersion Include="UnicodeInformation" Version="2.6.0" />

View File

@@ -57,7 +57,6 @@
<Project Path="src/common/UnitTests-CommonLib/UnitTests-CommonLib.vcxproj" Id="1a066c63-64b3-45f8-92fe-664e1cce8077" />
<Project Path="src/common/UnitTests-CommonUtils/UnitTests-CommonUtils.vcxproj" Id="8b5cfb38-ccba-40a8-ad7a-89c57b070884" />
<Project Path="src/common/updating/updating.vcxproj" Id="17da04df-e393-4397-9cf0-84dabe11032e" />
<Project Path="src/common/updating/UnitTests/UpdatingUnitTests.vcxproj" Id="a1b2c3d4-e5f6-7890-abcd-ef1234567890" />
<Project Path="src/common/version/version.vcxproj" Id="cc6e41ac-8174-4e8a-8d22-85dd7f4851df" />
</Folder>
<Folder Name="/common/interop/">
@@ -68,7 +67,10 @@
<Project Path="src/common/interop/PowerToys.Interop.vcxproj" Id="f055103b-f80b-4d0c-bf48-057c55620033" />
</Folder>
<Folder Name="/common/log/">
<Project Path="src/common/logger/logger.vcxproj" Id="d9b8fc84-322a-4f9f-bbb9-20915c47ddfd" />
<Project Path="src/common/logger/logger.vcxproj" Id="d9b8fc84-322a-4f9f-bbb9-20915c47ddfd">
<BuildDependency Project="src/logging/logging.vcxproj" />
</Project>
<Project Path="src/logging/logging.vcxproj" Id="7e1e3f13-2bd6-3f75-a6a7-873a2b55c60f" />
</Folder>
<Folder Name="/common/notifications/">
<Project Path="src/common/notifications/BackgroundActivator/BackgroundActivator.vcxproj" Id="0b593a6c-4143-4337-860e-db5710fb87db" />
@@ -799,14 +801,6 @@
<Project Path="src/modules/peek/peek/peek.vcxproj" Id="a1425b53-3d61-4679-8623-e64a0d3d0a48" />
</Folder>
<Folder Name="/modules/PowerAccent/">
<Project Path="src/modules/poweraccent/PowerAccent.Common.UnitTests/PowerAccent.Common.UnitTests.csproj">
<Platform Solution="*|ARM64" Project="ARM64" />
<Platform Solution="*|x64" Project="x64" />
</Project>
<Project Path="src/modules/poweraccent/PowerAccent.Common/PowerAccent.Common.csproj">
<Platform Solution="*|ARM64" Project="ARM64" />
<Platform Solution="*|x64" Project="x64" />
</Project>
<Project Path="src/modules/poweraccent/PowerAccent.Core/PowerAccent.Core.csproj">
<Platform Solution="*|ARM64" Project="ARM64" />
<Platform Solution="*|x64" Project="x64" />
@@ -1004,10 +998,6 @@
<Platform Solution="*|ARM64" Project="ARM64" />
<Platform Solution="*|x64" Project="x64" />
</Project>
<Project Path="src/modules/ShortcutGuide/ShortcutGuide.UnitTests/ShortcutGuide.UnitTests.csproj">
<Platform Solution="*|ARM64" Project="ARM64" />
<Platform Solution="*|x64" Project="x64" />
</Project>
<Project Path="src/modules/ShortcutGuide/ShortcutGuideModuleInterface/ShortcutGuideModuleInterface.vcxproj" Id="e487304a-b1fb-4e6b-8e70-014051af5b99" />
</Folder>
<Folder Name="/modules/Workspaces/">
@@ -1143,5 +1133,3 @@
<Project Path="src/Update/PowerToys.Update.vcxproj" Id="44ce9ae1-4390-42c5-bacc-0fd6b40aa203" />
<Project Path="tools/project_template/ModuleTemplate/ModuleTemplateCompileTest.vcxproj" Id="64a80062-4d8b-4229-8a38-dfa1d7497749" />
</Solution>

1
deps/expected-lite vendored Submodule

Submodule deps/expected-lite added at 95b9cb015f

7
deps/expected.props vendored Normal file
View File

@@ -0,0 +1,7 @@
<Project>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)expected-lite\include\nonstd\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
</Project>

1
deps/spdlog vendored Submodule

Submodule deps/spdlog added at 616866fcf4

View File

@@ -0,0 +1,94 @@
// spdlog-msvc-fix.h
//
// Workaround for MSVC 14.51 (compiler version 19.51, _MSC_VER >= 1951) removing
// stdext::checked_array_iterator. Force-included for all spdlog consumers via
// deps/spdlog.props, because spdlog v1.8.5's bundled fmt format.h(357) still
// references this type inside #if defined(_SECURE_SCL) && _SECURE_SCL -- a
// branch entered in Debug builds where _ITERATOR_DEBUG_LEVEL > 0.
//
// On MSVC 14.50 and earlier, the type still exists in <iterator>, so this shim
// is a no-op via the _MSC_VER guard. On MSVC 14.51+, it provides a minimal
// pointer-backed substitute that satisfies the bundled fmt's usage:
//
// template <typename T> using checked_ptr = stdext::checked_array_iterator<T*>;
// template <typename T> checked_ptr<T> make_checked(T* p, size_t size) {
// return {p, size};
// }
// ... return make_checked(get_data(c) + size, n);
//
// When deps/spdlog is bumped past v1.14 (which ships fmt 10.2 and drops this
// dependency), this shim and its <ForcedIncludeFiles> entry in deps/spdlog.props
// can be deleted.
#pragma once
#if defined(__cplusplus) && defined(_MSC_VER) && _MSC_VER >= 1951
#include <cstddef>
#include <iterator>
#include <type_traits>
namespace stdext
{
template <typename _Ptr>
class checked_array_iterator
{
_Ptr _Myarray = nullptr;
std::size_t _Mysize = 0;
std::size_t _Myindex = 0;
public:
using iterator_category = std::random_access_iterator_tag;
using value_type = std::remove_cv_t<std::remove_pointer_t<_Ptr>>;
using difference_type = std::ptrdiff_t;
using pointer = _Ptr;
using reference = std::remove_pointer_t<_Ptr>&;
constexpr checked_array_iterator() = default;
constexpr checked_array_iterator(_Ptr arr, std::size_t size, std::size_t idx = 0) noexcept
: _Myarray(arr), _Mysize(size), _Myindex(idx)
{
}
constexpr reference operator*() const noexcept { return _Myarray[_Myindex]; }
constexpr pointer operator->() const noexcept { return _Myarray + _Myindex; }
constexpr reference operator[](difference_type n) const noexcept
{
return _Myarray[_Myindex + static_cast<std::size_t>(n)];
}
constexpr checked_array_iterator& operator++() noexcept { ++_Myindex; return *this; }
constexpr checked_array_iterator operator++(int) noexcept { auto t = *this; ++_Myindex; return t; }
constexpr checked_array_iterator& operator--() noexcept { --_Myindex; return *this; }
constexpr checked_array_iterator operator--(int) noexcept { auto t = *this; --_Myindex; return t; }
constexpr checked_array_iterator& operator+=(difference_type n) noexcept
{
_Myindex = static_cast<std::size_t>(static_cast<difference_type>(_Myindex) + n);
return *this;
}
constexpr checked_array_iterator& operator-=(difference_type n) noexcept
{
_Myindex = static_cast<std::size_t>(static_cast<difference_type>(_Myindex) - n);
return *this;
}
friend constexpr checked_array_iterator operator+(checked_array_iterator it, difference_type n) noexcept { it += n; return it; }
friend constexpr checked_array_iterator operator+(difference_type n, checked_array_iterator it) noexcept { return it + n; }
friend constexpr checked_array_iterator operator-(checked_array_iterator it, difference_type n) noexcept { it -= n; return it; }
friend constexpr difference_type operator-(checked_array_iterator a, checked_array_iterator b) noexcept
{
return static_cast<difference_type>(a._Myindex) - static_cast<difference_type>(b._Myindex);
}
friend constexpr bool operator==(checked_array_iterator a, checked_array_iterator b) noexcept { return a._Myindex == b._Myindex; }
friend constexpr bool operator!=(checked_array_iterator a, checked_array_iterator b) noexcept { return !(a == b); }
friend constexpr bool operator<(checked_array_iterator a, checked_array_iterator b) noexcept { return a._Myindex < b._Myindex; }
friend constexpr bool operator>(checked_array_iterator a, checked_array_iterator b) noexcept { return b < a; }
friend constexpr bool operator<=(checked_array_iterator a, checked_array_iterator b) noexcept { return !(b < a); }
friend constexpr bool operator>=(checked_array_iterator a, checked_array_iterator b) noexcept { return !(a < b); }
};
} // namespace stdext
#endif // __cplusplus && _MSC_VER >= 1951

19
deps/spdlog.props vendored
View File

@@ -1,14 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<!--
SPDLOG_* preprocessor defines for spdlog consumers. The actual vcpkg
integration (VcpkgEnabled, VcpkgRoot, triplet, manifest install) lives
in Cpp.Build.props; this file just carries the defines that match how
the pre-vcpkg in-tree build was configured.
-->
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>SPDLOG_WCHAR_TO_UTF8_SUPPORT;SPDLOG_COMPILED_LIB;SPDLOG_WCHAR_FILENAMES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)spdlog\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>SPDLOG_WCHAR_TO_UTF8_SUPPORT;SPDLOG_COMPILED_LIB;SPDLOG_WCHAR_FILENAMES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ForcedIncludeFiles>$(MSBuildThisFileDirectory)spdlog-msvc-fix\include\spdlog-msvc-fix.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
</ClCompile>
</ItemDefinitionGroup>
</Project>

View File

@@ -1,16 +0,0 @@
--- a/include/spdlog/fmt/bundled/format.h
+++ b/include/spdlog/fmt/bundled/format.h
@@ -354,7 +354,12 @@ inline typename Container::value_type* get_data(Container& c) {
return c.data();
}
-#if defined(_SECURE_SCL) && _SECURE_SCL
+// PowerToys: stdext::checked_array_iterator was deprecated in VS 2019 16.10
+// and removed entirely in MSVC 14.51 (compiler 19.51, _MSC_VER >= 1951;
+// see microsoft/STL STL4043). Skip the broken branch on those toolsets so the
+// pointer-based fallback below is used instead. Drop this guard once
+// deps/spdlog is bumped past v1.14 (which ships fmt 10.2 and removes this code).
+#if defined(_SECURE_SCL) && _SECURE_SCL && (!defined(_MSC_VER) || _MSC_VER < 1951)
// Make a checked iterator to avoid MSVC warnings.
template <typename T> using checked_ptr = stdext::checked_array_iterator<T*>;
template <typename T> checked_ptr<T> make_checked(T* p, size_t size) {

View File

@@ -1,43 +0,0 @@
# PowerToys overlay port for spdlog.
#
# Pinned to the same git commit that the deleted deps/spdlog submodule pointed
# at, so this is a 1:1 submodule->vcpkg migration with no version change
# (per the maintainer guidance: convert one submodule at a time, atomic
# commit, don't also bump the version).
#
# A single hunk patch works around MSVC 14.51 STL4043 (removal of
# stdext::checked_array_iterator) in spdlog's bundled fmt 7. Drop this overlay
# (and switch to upstream vcpkg's spdlog port) once PowerToys bumps spdlog
# past v1.14, which ships fmt 10.2 and removes the affected code path.
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO gabime/spdlog
REF 616866fcf40340ea25a8f218369bad810ef58e72
SHA512 2076c527c7768627e6856b2f7ef663b185fd6251894cffd9299203d00f3d2de5696461060442dd72b96c9d3f0fd27f7f63ad2edfdf295e9b06c5fac6d6212faf
HEAD_REF v1.x
PATCHES
msvc-14.51-stdext-checked-array-iterator.patch
)
vcpkg_cmake_configure(
SOURCE_PATH "${SOURCE_PATH}"
OPTIONS
-DSPDLOG_BUILD_EXAMPLE=OFF
-DSPDLOG_BUILD_TESTS=OFF
-DSPDLOG_BUILD_BENCH=OFF
-DSPDLOG_FMT_EXTERNAL=OFF
-DSPDLOG_WCHAR_SUPPORT=ON
-DSPDLOG_WCHAR_FILENAMES=ON
-DSPDLOG_NO_EXCEPTIONS=OFF
-DSPDLOG_BUILD_SHARED=OFF
)
vcpkg_cmake_install()
vcpkg_cmake_config_fixup(PACKAGE_NAME spdlog CONFIG_PATH lib/cmake/spdlog)
vcpkg_fixup_pkgconfig()
vcpkg_copy_pdbs()
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include")
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE")

View File

@@ -1,18 +0,0 @@
{
"name": "spdlog",
"version-string": "1.8.5-pt-616866fc",
"port-version": 0,
"description": "Very fast, header-only/compiled, C++ logging library. PowerToys overlay pinned to gabime/spdlog@616866fc (the exact submodule commit before this migration), with a single-hunk patch that works around MSVC 14.51 removing stdext::checked_array_iterator (STL4043).",
"homepage": "https://github.com/gabime/spdlog",
"license": "MIT",
"dependencies": [
{
"name": "vcpkg-cmake",
"host": true
},
{
"name": "vcpkg-cmake-config",
"host": true
}
]
}

View File

@@ -97,10 +97,6 @@ The Shell Process Debugging Tool is a Visual Studio extension that helps debug m
- Check Event Viewer for application crashes related to `PowerToys.Settings.exe`
- Crash dumps can be obtained from Event Viewer
### Debugging Command Palette
Command Palette can be easily debugged using the solution filter in `src/modules/cmdpal/Command Palette.slnf`. This will open Command Palette as its own Visual Studio solution that can be run and debugged directly in Visual Studio without the need for the Shell Process Debugging Tool.
## Troubleshooting Build Errors
### Missing Image Files or Corrupted Build State

View File

Before

Width:  |  Height:  |  Size: 497 KiB

After

Width:  |  Height:  |  Size: 497 KiB

View File

Before

Width:  |  Height:  |  Size: 276 KiB

After

Width:  |  Height:  |  Size: 276 KiB

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

View File

Before

Width:  |  Height:  |  Size: 269 KiB

After

Width:  |  Height:  |  Size: 269 KiB

View File

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

Before

Width:  |  Height:  |  Size: 228 KiB

After

Width:  |  Height:  |  Size: 228 KiB

View File

Before

Width:  |  Height:  |  Size: 491 KiB

After

Width:  |  Height:  |  Size: 491 KiB

View File

Before

Width:  |  Height:  |  Size: 706 KiB

After

Width:  |  Height:  |  Size: 706 KiB

View File

Before

Width:  |  Height:  |  Size: 408 KiB

After

Width:  |  Height:  |  Size: 408 KiB

View File

Before

Width:  |  Height:  |  Size: 384 KiB

After

Width:  |  Height:  |  Size: 384 KiB

View File

Before

Width:  |  Height:  |  Size: 493 KiB

After

Width:  |  Height:  |  Size: 493 KiB

View File

Before

Width:  |  Height:  |  Size: 492 KiB

After

Width:  |  Height:  |  Size: 492 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

View File

Before

Width:  |  Height:  |  Size: 311 KiB

After

Width:  |  Height:  |  Size: 311 KiB

View File

Before

Width:  |  Height:  |  Size: 297 KiB

After

Width:  |  Height:  |  Size: 297 KiB

View File

Before

Width:  |  Height:  |  Size: 284 KiB

After

Width:  |  Height:  |  Size: 284 KiB

View File

Before

Width:  |  Height:  |  Size: 225 KiB

After

Width:  |  Height:  |  Size: 225 KiB

View File

Before

Width:  |  Height:  |  Size: 111 KiB

After

Width:  |  Height:  |  Size: 111 KiB

View File

Before

Width:  |  Height:  |  Size: 890 KiB

After

Width:  |  Height:  |  Size: 890 KiB

View File

Before

Width:  |  Height:  |  Size: 858 KiB

After

Width:  |  Height:  |  Size: 858 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 1.5 MiB

View File

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -87,7 +87,7 @@ Per Application/Package one or more Keyboard manifests can be declared. Every ma
<details>
<summary><b>WindowFilter</b> - The filter of window processes to which the shortcuts apply to</summary>
This field declares for which process name the shortcuts should be shown (To rephrase: For which processes the shortcut will have an effect if pressed). The value can be either an exact process executable name, for example `explorer.exe` or `chrome.exe`, or a single asterisk (`*`) to apply to any process. No other wildcard patterns are supported by this specification.
This field declares for which process name the shortcuts should be showed (To rephrase: For which processes the shortcut will have an effect if pressed). You can use an asterisk to leave out a certain part. For example `*.PowerToys.*.exe` targets all PowerToys processes and `*` apply to any process.
</details>
@@ -195,18 +195,10 @@ Special sections start with an identifier enclosed between `<` and `>`. This dec
A string array of all the keys that need to be pressed. If a number is supplied, it should be read as a [KeyCode](https://learn.microsoft.com/windows/win32/inputdev/virtual-key-codes) and displayed accordingly (based on the Keyboard Layout of the user).
**Literal digit keys**:
Because a bare number is interpreted as a virtual-key code, a literal digit key must be authored using the `<N>` notation (the digit enclosed between `<` and `>`), where `N` is `0``9`. For example, `<9>` represents the literal `9` key (as in the "switch to the last tab" shortcut), not the virtual-key code `9` (which is `Tab`). The interpreter strips the brackets and displays just the digit.
This applies only to a single literal digit. A range such as `1 - 8` is a free-form label, not a key, and is supplied verbatim (the brackets would only be trimmed from the ends, so `<1> - <8>` would not render as intended).
**Special keys**:
Special keys are enclosed between `<` and `>` and correspond to a key that should be displayed in a certain way. If the interpreter of the manifest file can't understand the content, the brackets should be left out.
By convention these tokens are written as double-quoted strings in the YAML (for example `"<Enter>"` and `"<9>"`), matching the quoting used for punctuation key values. YAML treats the quoted and unquoted forms identically, so quoting is for consistency rather than a strict requirement for bracketed tokens.
|Name|Description|
|----|-----------|
|`<Office>`| Corresponds to the Office key on some Windows keyboards |

View File

@@ -79,4 +79,3 @@ Below are community created plugins that target a website or software. They are
| [Linear](https://github.com/vednig/powertoys-linear) | [vednig](https://github.com/vednig) | Create Linear Issues directly from Powertoys Run |
| [PerplexitySearchShortcut](https://github.com/0x6f677548/PowerToys-Run-PerplexitySearchShortcut) | [0x6f677548](https://github.com/0x6f677548) | Search Perplexity |
| [SpeedTest](https://github.com/ruslanlap/PowerToysRun-SpeedTest) | [ruslanlap](https://github.com/ruslanlap) | One-command internet speed tests with real-time results, modern UI, and shareable links. |
| [DiskAnalyzer](https://github.com/thetsaw/PowerToys.Plugin) | [thetsaw](https://github.com/thetsaw) | Scan folders, find the largest files, and view drive space usage with visual progress bars. |

View File

@@ -8,6 +8,9 @@
</Project>
<Project Path="../src/common/Telemetry/EtwTrace/EtwTrace.vcxproj" Id="8f021b46-362b-485c-bfba-ccf83e820cbd" />
<Project Path="../src/common/version/version.vcxproj" Id="cc6e41ac-8174-4e8a-8d22-85dd7f4851df" />
<Project Path="../src/logging/logging.vcxproj" Id="7e1e3f13-2bd6-3f75-a6a7-873a2b55c60f">
<Build Solution="Debug|ARM64" Project="false" />
</Project>
<Project Path="PowerToysSetupCustomActionsVNext/PowerToysSetupCustomActionsVNext.vcxproj" Id="b3a354b0-1e54-4b55-a962-fb5af9330c19">
<Build Solution="Debug|ARM64" Project="false" />
</Project>

View File

@@ -4,23 +4,15 @@
<?define ShortcutGuideAssetsFiles=?>
<?define ShortcutGuideAssetsFilesPath=$(var.BinDir)WinUI3Apps\Assets\ShortcutGuide\?>
<?define ShortcutGuideManifestsFiles=?>
<?define ShortcutGuideManifestsFilesPath=$(var.BinDir)WinUI3Apps\Assets\ShortcutGuide\Manifests\?>
<Fragment>
<DirectoryRef Id="WinUI3AppsAssetsFolder">
<Directory Id="ShortcutGuideAssetsFolder" Name="ShortcutGuide">
<Directory Id="ShortcutGuideManifestsFolder" Name="Manifests" />
</Directory>
<Directory Id="ShortcutGuideAssetsFolder" Name="ShortcutGuide" />
</DirectoryRef>
<DirectoryRef Id="ShortcutGuideAssetsFolder" FileSource="$(var.ShortcutGuideAssetsFilesPath)">
<!-- Generated by generateFileComponents.ps1 -->
<!--ShortcutGuideAssetsFiles_Component_Def-->
</DirectoryRef>
<DirectoryRef Id="ShortcutGuideManifestsFolder" FileSource="$(var.ShortcutGuideManifestsFilesPath)">
<!-- Generated by generateFileComponents.ps1 -->
<!--ShortcutGuideManifestsFiles_Component_Def-->
</DirectoryRef>
<!-- Shortcut guide -->
<ComponentGroup Id="ShortcutGuideComponentGroup" >
@@ -30,12 +22,6 @@
</RegistryKey>
<RemoveFolder Id="RemoveFolderShortcutGuideAssetsInstallFolder" Directory="ShortcutGuideAssetsFolder" On="uninstall"/>
</Component>
<Component Id="RemoveShortcutGuideManifestsFolder" Guid="F47E2C3A-8D91-4B6F-A2E5-9C8D7F6A1B3E" Directory="ShortcutGuideManifestsFolder" >
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
<RegistryValue Type="string" Name="RemoveShortcutGuideManifestsFolder" Value="" KeyPath="yes"/>
</RegistryKey>
<RemoveFolder Id="RemoveFolderShortcutGuideManifestsInstallFolder" Directory="ShortcutGuideManifestsFolder" On="uninstall"/>
</Component>
</ComponentGroup>
</Fragment>

View File

@@ -28,7 +28,7 @@ Function Generate-FileList() {
$fileExclusionList = @("*.pdb", "*.lastcodeanalysissucceeded", "createdump.exe", "powertoys.exe")
$fileInclusionList = @("*.dll", "*.exe", "*.json", "*.msix", "*.png", "*.gif", "*.ico", "*.cur", "*.svg", "index.html", "reg.js", "gitignore.js", "srt.js", "monacoSpecialLanguages.js", "customTokenThemeRules.js", "*.pri", "*.yml")
$fileInclusionList = @("*.dll", "*.exe", "*.json", "*.msix", "*.png", "*.gif", "*.ico", "*.cur", "*.svg", "index.html", "reg.js", "gitignore.js", "srt.js", "monacoSpecialLanguages.js", "customTokenThemeRules.js", "*.pri")
# MFC DLLs leak into the output via WindowsAppSDKSelfContained but no PowerToys binary imports them.
# Verified with dumpbin /dependents across all 2176 binaries — zero consumers.
@@ -112,8 +112,6 @@ Function Generate-FileComponents() {
foreach ($file in $fileList) {
$fileTmp = $file -replace "-", "_"
$fileTmp = $fileTmp -replace "[^A-Za-z0-9_.]", "_"
if ($fileTmp -match "^[^A-Za-z_]") { $fileTmp = "_$fileTmp" }
$componentDefs +=
@"
<File Id="$($fileListName)_File_$($fileTmp)" Source="`$(var.$($fileListName)Path)\$($file)" />`r`n
@@ -399,24 +397,8 @@ Generate-FileComponents -fileListName "ValueGeneratorImagesCmpFiles" -wxsFilePat
## Plugins
#ShortcutGuide
# Ensure manifest yml files are in the build output (the Build target's CopyToOutputDirectory
# may not run reliably under -graph mode in solution builds).
$sgManifestsSrc = "$PSScriptRoot..\..\..\src\modules\ShortcutGuide\ShortcutGuide.Ui\Assets\ShortcutGuide\Manifests"
$sgManifestsDst = "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\ShortcutGuide\Manifests"
Write-Host "ShortcutGuide manifests: src=$sgManifestsSrc exists=$(Test-Path $sgManifestsSrc)"
Write-Host "ShortcutGuide manifests: dst=$sgManifestsDst exists=$(Test-Path $sgManifestsDst)"
if (Test-Path $sgManifestsSrc) {
New-Item -Path $sgManifestsDst -ItemType Directory -Force | Out-Null
Copy-Item "$sgManifestsSrc\*.yml" -Destination $sgManifestsDst -Force
$copied = (Get-ChildItem "$sgManifestsDst\*.yml" -ErrorAction SilentlyContinue).Count
Write-Host "ShortcutGuide manifests: copied $copied yml files to build output"
} else {
Write-Host "WARNING: ShortcutGuide manifest source not found at $sgManifestsSrc"
}
Generate-FileList -fileDepsJson "" -fileListName ShortcutGuideAssetsFiles -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\ShortcutGuide\"
Generate-FileComponents -fileListName "ShortcutGuideAssetsFiles" -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs
Generate-FileList -fileDepsJson "" -fileListName ShortcutGuideManifestsFiles -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\ShortcutGuide\Manifests\"
Generate-FileComponents -fileListName "ShortcutGuideManifestsFiles" -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs
Generate-FileComponents -fileListName "ShortcutGuideAssetsFiles" -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs -regroot $registryroot
#Settings
Generate-FileList -fileDepsJson "" -fileListName SettingsV2AssetsFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Settings\"

View File

@@ -14,6 +14,7 @@
<PropertyGroup Label="Configuration">
</PropertyGroup>
<Import Project="$(RepoRoot)deps\expected.props" />
<PropertyGroup>
<ConfigurationType>Application</ConfigurationType>
</PropertyGroup>

View File

@@ -14,8 +14,6 @@
#include <common/updating/updating.h>
#include <common/updating/updateState.h>
#include <common/updating/installer.h>
#include <common/updating/configBackup.h>
#include <common/updating/updateLifecycle.h>
#include <common/utils/elevation.h>
#include <common/utils/HttpClient.h>
@@ -23,8 +21,6 @@
#include <common/utils/resources.h>
#include <common/utils/timeutil.h>
#include <wil/resource.h>
#include <common/SettingsAPI/settings_helpers.h>
#include <common/logger/logger.h>
@@ -40,59 +36,17 @@ using namespace cmdArg;
namespace fs = std::filesystem;
void CleanupStaleTempUpdaters()
{
// Remove orphaned PowerToys.Update.*.exe files from previous runs
try
{
std::error_code ec;
const auto tempDir = fs::temp_directory_path();
for (const auto& entry : fs::directory_iterator(tempDir, ec))
{
if (ec)
{
break;
}
if (!entry.is_regular_file())
{
continue;
}
const auto filename = entry.path().filename().wstring();
if (filename.starts_with(L"PowerToys.Update.") && filename.ends_with(L".exe"))
{
// Skip our own file (current PID)
const auto ownFilename = L"PowerToys.Update." + std::to_wstring(GetCurrentProcessId()) + L".exe";
if (filename == ownFilename)
{
continue;
}
fs::remove(entry.path(), ec);
// Failure to delete is expected if another updater is still running
}
}
}
catch (...)
{
// Best-effort cleanup; don't block the update
}
}
std::optional<fs::path> CopySelfToTempDir()
{
CleanupStaleTempUpdaters();
std::error_code error;
auto dst_path = fs::temp_directory_path() / (L"PowerToys.Update." + std::to_wstring(GetCurrentProcessId()) + L".exe");
auto dst_path = fs::temp_directory_path() / "PowerToys.Update.exe";
fs::copy_file(get_module_filename(), dst_path, fs::copy_options::overwrite_existing, error);
if (error)
{
return std::nullopt;
}
return dst_path;
return std::move(dst_path);
}
std::optional<fs::path> ObtainInstaller(bool& isUpToDate)
@@ -103,9 +57,34 @@ std::optional<fs::path> ObtainInstaller(bool& isUpToDate)
auto state = UpdateState::read();
// Handle readyToInstall first — the installer is already on disk,
// so we don't need a GitHub API call (which may fail if offline).
if (state.state == UpdateState::readyToInstall)
const auto new_version_info = std::move(get_github_version_info_async()).get();
if (std::holds_alternative<version_up_to_date>(*new_version_info))
{
isUpToDate = true;
Logger::error("Invoked with -update_now argument, but no update was available");
return std::nullopt;
}
if (state.state == UpdateState::readyToDownload || state.state == UpdateState::errorDownloading)
{
if (!new_version_info)
{
Logger::error(L"Couldn't obtain github version info: {}", new_version_info.error());
return std::nullopt;
}
// Cleanup old updates before downloading the latest
updating::cleanup_updates();
auto downloaded_installer = std::move(download_new_version_async(std::get<new_version_download_info>(*new_version_info))).get();
if (!downloaded_installer)
{
Logger::error("Couldn't download new installer");
}
return downloaded_installer;
}
else if (state.state == UpdateState::readyToInstall)
{
fs::path installer{ get_pending_updates_path() / state.downloadedInstallerFilename };
if (fs::is_regular_file(installer))
@@ -118,44 +97,12 @@ std::optional<fs::path> ObtainInstaller(bool& isUpToDate)
return std::nullopt;
}
}
if (state.state == UpdateState::upToDate)
else if (state.state == UpdateState::upToDate)
{
isUpToDate = true;
return std::nullopt;
}
const auto new_version_info = std::move(get_github_version_info_async()).get();
// Check for error BEFORE dereferencing — the old code crashed here
// when GitHub API was unreachable (new_version_info held an error string).
if (!new_version_info)
{
Logger::error(L"Couldn't obtain github version info: {}", new_version_info.error());
return std::nullopt;
}
if (std::holds_alternative<version_up_to_date>(*new_version_info))
{
isUpToDate = true;
Logger::error("Invoked with -update_now argument, but no update was available");
return std::nullopt;
}
if (state.state == UpdateState::readyToDownload || state.state == UpdateState::errorDownloading)
{
// Cleanup old updates before downloading the latest
updating::cleanup_updates();
auto downloaded_installer = std::move(download_new_version_async(std::get<new_version_download_info>(*new_version_info))).get();
if (!downloaded_installer)
{
Logger::error("Couldn't download new installer");
}
return downloaded_installer;
}
Logger::error("Invoked with -update_now argument, but update state was invalid");
return std::nullopt;
}
@@ -169,32 +116,13 @@ bool InstallNewVersionStage1(fs::path installer)
if (pt_main_window != nullptr)
{
// Get the process that owns the tray window so we can wait for it to exit
DWORD ptProcessId = 0;
GetWindowThreadProcessId(pt_main_window, &ptProcessId);
// Use SendMessageTimeoutW to avoid blocking indefinitely if the
// tray window thread is hung or unresponsive.
DWORD_PTR result = 0;
SendMessageTimeoutW(pt_main_window, WM_CLOSE, 0, 0, SMTO_ABORTIFHUNG, 5000, &result);
// Wait for PT to actually exit before launching installer.
// Without this, the installer may find PT files locked.
if (ptProcessId != 0)
{
wil::unique_handle ptProcess{ OpenProcess(SYNCHRONIZE, FALSE, ptProcessId) };
if (ptProcess)
{
WaitForSingleObject(ptProcess.get(), 10000); // 10 second timeout
}
}
SendMessageW(pt_main_window, WM_CLOSE, 0, 0);
}
// Pass the install directory so Stage 2 can relaunch PowerToys after install
const std::wstring installDir = get_module_folderpath();
std::wstring arguments = updating::BuildStage2Arguments(
UPDATE_NOW_LAUNCH_STAGE2, installer, fs::path(installDir));
std::wstring arguments{ UPDATE_NOW_LAUNCH_STAGE2 };
arguments += L" \"";
arguments += installer.c_str();
arguments += L"\"";
SHELLEXECUTEINFOW sei{ sizeof(sei) };
sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC };
sei.lpFile = copy_in_temp->c_str();
@@ -262,16 +190,9 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
LPWSTR* args = CommandLineToArgvW(GetCommandLineW(), &nArgs);
if (!args || nArgs < 2)
{
if (args)
{
LocalFree(args);
}
return 1;
}
// D3 fix: ensure args is freed on all exit paths
auto freeArgs = wil::scope_exit([&] { LocalFree(args); });
std::wstring_view action{ args[1] };
std::filesystem::path logFilePath(PTSettingsHelper::get_root_save_folder_location());
@@ -280,11 +201,6 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
if (action == UPDATE_NOW_LAUNCH_STAGE1)
{
// Backup config files before the update to protect against corruption
Logger::info("Backing up config files before update");
auto backupResult = updating::BackupConfigFiles(fs::path(PTSettingsHelper::get_root_save_folder_location()));
Logger::info("Config backup complete: {} files backed up, {} errors", backupResult.filesBackedUp, backupResult.errors);
bool isUpToDate = false;
auto installerPath = ObtainInstaller(isUpToDate);
bool failed = !installerPath.has_value();
@@ -301,12 +217,6 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
}
else if (action == UPDATE_NOW_LAUNCH_STAGE2)
{
if (nArgs < 3)
{
Logger::error("Stage 2 invoked without installer path argument");
return 1;
}
using namespace std::string_view_literals;
const bool failed = !InstallNewVersionStage2(args[2]);
if (failed)
@@ -317,39 +227,6 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
state.state = UpdateState::errorDownloading;
});
}
// Always check for corrupted configs after Stage 2, regardless
// of install success/failure. A failed install may still corrupt configs.
Logger::info("Checking for corrupted config files after update");
auto restoreResult = updating::RestoreCorruptedConfigs(fs::path(PTSettingsHelper::get_root_save_folder_location()));
Logger::info("Config restore check complete: {}/{} files restored, {} errors",
restoreResult.filesRestored, restoreResult.filesChecked, restoreResult.errors);
if (!failed)
{
// Relaunch PowerToys from the install directory
if (updating::CanRelaunchAfterUpdate(nArgs))
{
std::wstring ptExePath = updating::BuildPowerToysExePath(args[3]);
Logger::info(L"Relaunching PowerToys after update: {}", ptExePath);
SHELLEXECUTEINFOW sei{ sizeof(sei) };
sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC };
sei.lpFile = ptExePath.c_str();
sei.nShow = SW_SHOWNORMAL;
sei.lpParameters = UPDATE_REPORT_SUCCESS;
if (!ShellExecuteExW(&sei))
{
Logger::error(L"Failed to relaunch PowerToys after update");
}
}
else
{
Logger::warn("Install directory not provided to Stage 2 - cannot relaunch PowerToys");
}
}
return failed;
}

View File

@@ -14,6 +14,7 @@
<PropertyGroup Label="Configuration">
</PropertyGroup>
<Import Project="$(RepoRoot)deps\expected.props" />
<PropertyGroup>
<ConfigurationType>Application</ConfigurationType>
</PropertyGroup>

View File

@@ -27,7 +27,7 @@
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>..\;..\utils;..\Telemetry;..\..\;..\..\..\deps\;..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.260126.7\include;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\;..\utils;..\Telemetry;..\..\;..\..\..\deps\;..\..\..\deps\spdlog\include;..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.260126.7\include;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp23</LanguageStandard>
<PreprocessorDefinitions>SPDLOG_WCHAR_TO_UTF8_SUPPORT;SPDLOG_HEADER_ONLY;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>

View File

@@ -70,6 +70,9 @@
</ClCompile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\logging\logging.vcxproj">
<Project>{7e1e3f13-2bd6-3f75-a6a7-873a2b55c60f}</Project>
</ProjectReference>
<ProjectReference Include="..\version\version.vcxproj">
<Project>{cc6e41ac-8174-4e8a-8d22-85dd7f4851df}</Project>
</ProjectReference>

View File

@@ -1,679 +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.
#include "pch.h"
#include <algorithm>
#include <filesystem>
#include <fstream>
#include <iterator>
#include <string>
#include <vector>
#include <common/updating/configBackup.h>
#include <common/updating/updateLifecycle.h>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace fs = std::filesystem;
namespace UpdatingUnitTests
{
// Helper to create a temp directory for test isolation.
// Each instance gets a unique subdirectory to prevent test interference.
class TempDir
{
public:
TempDir()
{
wchar_t tempPath[MAX_PATH + 1];
GetTempPathW(MAX_PATH, tempPath);
static std::atomic<int> counter{0};
m_path = fs::path(tempPath) / (L"PowerToysUpdateTests_" + std::to_wstring(counter++));
// Ensure clean state
std::error_code ec;
fs::remove_all(m_path, ec);
fs::create_directories(m_path, ec);
}
~TempDir()
{
std::error_code ec;
fs::remove_all(m_path, ec);
}
const fs::path& path() const { return m_path; }
// Write a file with the given content
void WriteFile(const fs::path& relativePath, const std::string& content)
{
auto fullPath = m_path / relativePath;
fs::create_directories(fullPath.parent_path());
std::ofstream file(fullPath, std::ios::binary);
file.write(content.data(), content.size());
}
// Write a file with raw bytes (including null bytes for corruption testing)
void WriteFileBytes(const fs::path& relativePath, const std::vector<char>& bytes)
{
auto fullPath = m_path / relativePath;
fs::create_directories(fullPath.parent_path());
std::ofstream file(fullPath, std::ios::binary);
file.write(bytes.data(), bytes.size());
}
// Read file content as string
std::string ReadFile(const fs::path& relativePath)
{
auto fullPath = m_path / relativePath;
std::ifstream file(fullPath, std::ios::binary);
return std::string(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
}
bool FileExists(const fs::path& relativePath)
{
return fs::exists(m_path / relativePath);
}
private:
fs::path m_path;
};
TEST_CLASS(IsJsonFileCorruptedTests)
{
public:
// Tests IsJsonFileCorrupted: valid JSON with no null bytes returns false.
// Covers: configBackup.h IsJsonFileCorrupted — happy path, full file scan.
TEST_METHOD(CleanJsonFileIsNotCorrupted)
{
TempDir dir;
dir.WriteFile(L"settings.json", R"({"theme":"dark","startup":true})");
Assert::IsFalse(updating::IsJsonFileCorrupted(dir.path() / L"settings.json"));
}
// Tests IsJsonFileCorrupted: zero-length file returns false (empty is not corrupted).
// Covers: configBackup.h IsJsonFileCorrupted — file.read returns 0 bytes immediately.
TEST_METHOD(EmptyFileIsNotCorrupted)
{
TempDir dir;
dir.WriteFile(L"empty.json", "");
Assert::IsFalse(updating::IsJsonFileCorrupted(dir.path() / L"empty.json"));
}
// Tests IsJsonFileCorrupted: file containing embedded null bytes returns true.
// Covers: configBackup.h IsJsonFileCorrupted — null byte detection within buffer.
TEST_METHOD(FileWithNullBytesIsCorrupted)
{
TempDir dir;
std::vector<char> corrupted = { '{', '"', 'a', '"', ':', '\0', '\0', '\0', '}' };
dir.WriteFileBytes(L"corrupted.json", corrupted);
Assert::IsTrue(updating::IsJsonFileCorrupted(dir.path() / L"corrupted.json"));
}
// Tests IsJsonFileCorrupted: file entirely filled with 0x00 bytes returns true.
// Reproduces the exact bug from #46179 where installer zeroed out JSON files.
// Covers: configBackup.h IsJsonFileCorrupted — first byte is null.
TEST_METHOD(FileFilledWithNullBytesIsCorrupted)
{
TempDir dir;
std::vector<char> allNulls(1024, '\0');
dir.WriteFileBytes(L"workspaces.json", allNulls);
Assert::IsTrue(updating::IsJsonFileCorrupted(dir.path() / L"workspaces.json"));
}
// Tests IsJsonFileCorrupted: path that does not exist returns false.
// Covers: configBackup.h IsJsonFileCorrupted — file.is_open() check.
TEST_METHOD(NonExistentFileIsNotCorrupted)
{
TempDir dir;
Assert::IsFalse(updating::IsJsonFileCorrupted(dir.path() / L"missing.json"));
}
// Tests IsJsonFileCorrupted: file larger than the 4096-byte read chunk
// with no null bytes returns false.
// Covers: configBackup.h IsJsonFileCorrupted — multi-chunk while loop.
TEST_METHOD(LargeCleanFileIsNotCorrupted)
{
TempDir dir;
std::string largeContent(8192, 'x');
dir.WriteFile(L"large.json", largeContent);
Assert::IsFalse(updating::IsJsonFileCorrupted(dir.path() / L"large.json"));
}
// Tests IsJsonFileCorrupted: null byte placed after the first 4096-byte
// chunk boundary is still detected.
// Covers: configBackup.h IsJsonFileCorrupted — second chunk scan.
TEST_METHOD(NullByteAtEndOfLargeFileIsDetected)
{
TempDir dir;
std::string content(5000, 'x');
content[4999] = '\0';
std::vector<char> bytes(content.begin(), content.end());
dir.WriteFileBytes(L"sneaky.json", bytes);
Assert::IsTrue(updating::IsJsonFileCorrupted(dir.path() / L"sneaky.json"));
}
};
TEST_CLASS(BackupConfigFilesTests)
{
public:
// Tests BackupConfigFiles: root-level .json files are copied to ConfigBackup.
// Covers: configBackup.h BackupConfigFiles — root directory_iterator,
// is_regular_file && extension == ".json" branch.
// Setup: Two root-level JSON files.
TEST_METHOD(BackupCopiesRootJsonFiles)
{
TempDir dir;
dir.WriteFile(L"settings.json", R"({"theme":"dark"})");
dir.WriteFile(L"UpdateState.json", R"({"state":0})");
updating::BackupConfigFiles(dir.path());
Assert::IsTrue(dir.FileExists(L"ConfigBackup\\settings.json"));
Assert::IsTrue(dir.FileExists(L"ConfigBackup\\UpdateState.json"));
Assert::AreEqual(std::string(R"({"theme":"dark"})"), dir.ReadFile(L"ConfigBackup\\settings.json"));
}
// Tests BackupConfigFiles: .json files inside module subdirectories are
// copied to ConfigBackup/<module>/.
// Covers: configBackup.h BackupConfigFiles — is_directory branch,
// module directory_iterator with extension filter.
// Setup: Root JSON + two module directories with JSON files.
TEST_METHOD(BackupCopiesModuleJsonFiles)
{
TempDir dir;
dir.WriteFile(L"settings.json", R"({"theme":"dark"})");
dir.WriteFile(L"FancyZones\\settings.json", R"({"zones":[]})");
dir.WriteFile(L"Workspaces\\workspaces.json", R"({"workspaces":[]})");
updating::BackupConfigFiles(dir.path());
Assert::IsTrue(dir.FileExists(L"ConfigBackup\\FancyZones\\settings.json"));
Assert::IsTrue(dir.FileExists(L"ConfigBackup\\Workspaces\\workspaces.json"));
Assert::AreEqual(std::string(R"({"zones":[]})"),
dir.ReadFile(L"ConfigBackup\\FancyZones\\settings.json"));
}
// Tests BackupConfigFiles: non-.json files at root level are not copied.
// Covers: configBackup.h BackupConfigFiles — extension filter excludes .log.
// Setup: One JSON file + one .log file at root.
TEST_METHOD(BackupSkipsNonJsonFiles)
{
TempDir dir;
dir.WriteFile(L"settings.json", R"({"theme":"dark"})");
dir.WriteFile(L"debug.log", "log data");
updating::BackupConfigFiles(dir.path());
Assert::IsTrue(dir.FileExists(L"ConfigBackup\\settings.json"));
Assert::IsFalse(dir.FileExists(L"ConfigBackup\\debug.log"));
}
// Tests BackupConfigFiles: the "Updates" directory is explicitly skipped.
// Covers: configBackup.h BackupConfigFiles — dirName == L"Updates" continue.
// Setup: Root JSON + Updates directory containing a file.
TEST_METHOD(BackupSkipsUpdatesDirectory)
{
TempDir dir;
dir.WriteFile(L"settings.json", R"({"theme":"dark"})");
dir.WriteFile(L"Updates\\installer.exe", "fake exe");
updating::BackupConfigFiles(dir.path());
Assert::IsFalse(dir.FileExists(L"ConfigBackup\\Updates"));
}
// Tests BackupConfigFiles: running backup twice overwrites the previous
// backup with current file content.
// Covers: configBackup.h BackupConfigFiles — fs::remove_all(backupDir) +
// copy_options::overwrite_existing.
// Setup: Backup, modify original, backup again.
TEST_METHOD(BackupOverwritesPreviousBackup)
{
TempDir dir;
dir.WriteFile(L"settings.json", R"({"version":1})");
updating::BackupConfigFiles(dir.path());
// Update the original
dir.WriteFile(L"settings.json", R"({"version":2})");
updating::BackupConfigFiles(dir.path());
Assert::AreEqual(std::string(R"({"version":2})"), dir.ReadFile(L"ConfigBackup\\settings.json"));
}
// Tests BackupConfigFiles: non-.json files inside module subdirectories
// (e.g., FancyZones/zones.dat) should NOT be backed up.
// Covers: configBackup.h BackupConfigFiles — extension filter in module loop.
TEST_METHOD(BackupSkipsNonJsonFilesInModuleDirs)
{
TempDir dir;
dir.WriteFile(L"settings.json", R"({})");
dir.WriteFile(L"FancyZones\\settings.json", R"({"zones":[]})");
dir.WriteFile(L"FancyZones\\zones.dat", "binary data");
updating::BackupConfigFiles(dir.path());
Assert::IsTrue(dir.FileExists(L"ConfigBackup\\FancyZones\\settings.json"));
Assert::IsFalse(dir.FileExists(L"ConfigBackup\\FancyZones\\zones.dat"));
}
// Tests BackupConfigFiles: empty root directory with no files produces
// an empty ConfigBackup dir without errors.
// Covers: configBackup.h BackupConfigFiles — empty directory_iterator.
TEST_METHOD(BackupEmptyRootDirSucceeds)
{
TempDir dir;
// Root dir exists but has no files
updating::BackupConfigFiles(dir.path());
Assert::IsTrue(dir.FileExists(L"ConfigBackup"));
}
};
TEST_CLASS(RestoreCorruptedConfigsTests)
{
public:
// Tests RestoreCorruptedConfigs: corrupted root-level JSON file is restored
// from the good backup copy.
// Covers: configBackup.h RestoreCorruptedConfigs — root file restore branch,
// fs::exists + IsJsonFileCorrupted + backup integrity check.
// Setup: Good file -> backup -> corrupt original -> restore.
TEST_METHOD(RestoreFixesCorruptedRootFile)
{
TempDir dir;
const std::string goodContent = R"({"theme":"dark"})";
dir.WriteFile(L"settings.json", goodContent);
// Backup
updating::BackupConfigFiles(dir.path());
// Corrupt the original
std::vector<char> corrupted(goodContent.size(), '\0');
dir.WriteFileBytes(L"settings.json", corrupted);
Assert::IsTrue(updating::IsJsonFileCorrupted(dir.path() / L"settings.json"));
// Restore
updating::RestoreCorruptedConfigs(dir.path());
Assert::IsFalse(updating::IsJsonFileCorrupted(dir.path() / L"settings.json"));
Assert::AreEqual(goodContent, dir.ReadFile(L"settings.json"));
}
// Tests RestoreCorruptedConfigs: corrupted module-level JSON file is restored
// from the good backup copy.
// Covers: configBackup.h RestoreCorruptedConfigs — module directory branch,
// moduleBackupEntry restore with integrity check.
// Setup: Module file + root file -> backup -> corrupt module file -> restore.
TEST_METHOD(RestoreFixesCorruptedModuleFile)
{
TempDir dir;
const std::string goodContent = R"({"workspaces":[]})";
dir.WriteFile(L"Workspaces\\workspaces.json", goodContent);
dir.WriteFile(L"settings.json", R"({})");
updating::BackupConfigFiles(dir.path());
// Corrupt the module file
std::vector<char> corrupted(goodContent.size(), '\0');
dir.WriteFileBytes(L"Workspaces\\workspaces.json", corrupted);
updating::RestoreCorruptedConfigs(dir.path());
Assert::AreEqual(goodContent, dir.ReadFile(L"Workspaces\\workspaces.json"));
}
// Tests RestoreCorruptedConfigs: clean (non-corrupted) files are NOT
// overwritten by backup — preserves user changes made after backup.
// Covers: configBackup.h RestoreCorruptedConfigs — IsJsonFileCorrupted
// returns false, copy_file is skipped.
// Setup: File -> backup -> modify (but keep valid) -> restore.
TEST_METHOD(RestoreLeavesCleanFilesUntouched)
{
TempDir dir;
dir.WriteFile(L"settings.json", R"({"version":1})");
updating::BackupConfigFiles(dir.path());
// Modify original (but keep it clean JSON)
dir.WriteFile(L"settings.json", R"({"version":2})");
updating::RestoreCorruptedConfigs(dir.path());
// Should NOT have been restored since it's not corrupted
Assert::AreEqual(std::string(R"({"version":2})"), dir.ReadFile(L"settings.json"));
}
// Tests RestoreCorruptedConfigs: when no ConfigBackup directory exists,
// restore silently does nothing (no crash, no data loss).
// Covers: configBackup.h RestoreCorruptedConfigs — !fs::exists(backupDir)
// early return.
// Setup: File with no prior backup.
TEST_METHOD(RestoreHandlesMissingBackupDirectory)
{
TempDir dir;
dir.WriteFile(L"settings.json", R"({"theme":"dark"})");
// No backup was created - restore should silently do nothing
updating::RestoreCorruptedConfigs(dir.path());
Assert::AreEqual(std::string(R"({"theme":"dark"})"), dir.ReadFile(L"settings.json"));
}
// Tests RestoreCorruptedConfigs: end-to-end scenario with multiple modules,
// some corrupted and some clean, verifying selective restore.
// Covers: configBackup.h RestoreCorruptedConfigs — both root and module
// branches, selective restore based on corruption status.
// Setup: 4 modules -> backup -> corrupt 2 -> restore -> verify all 4.
TEST_METHOD(FullBackupAndRestoreRoundTrip)
{
TempDir dir;
// Set up a realistic config structure
dir.WriteFile(L"settings.json", R"({"startup":true,"theme":"dark"})");
dir.WriteFile(L"FancyZones\\settings.json", R"({"zones":[{"id":1}]})");
dir.WriteFile(L"Workspaces\\workspaces.json", R"({"workspaces":[{"name":"dev"}]})");
dir.WriteFile(L"KeyboardManager\\default.json", R"({"remaps":[]})");
// Backup
updating::BackupConfigFiles(dir.path());
// Corrupt some files (simulating #46179 scenario)
dir.WriteFileBytes(L"Workspaces\\workspaces.json", std::vector<char>(100, '\0'));
dir.WriteFileBytes(L"settings.json", std::vector<char>(50, '\0'));
// Leave FancyZones and KBM clean
// Restore
updating::RestoreCorruptedConfigs(dir.path());
// Corrupted files should be restored
Assert::AreEqual(std::string(R"({"startup":true,"theme":"dark"})"), dir.ReadFile(L"settings.json"));
Assert::AreEqual(std::string(R"({"workspaces":[{"name":"dev"}]})"), dir.ReadFile(L"Workspaces\\workspaces.json"));
// Clean files should be unchanged
Assert::AreEqual(std::string(R"({"zones":[{"id":1}]})"), dir.ReadFile(L"FancyZones\\settings.json"));
Assert::AreEqual(std::string(R"({"remaps":[]})"), dir.ReadFile(L"KeyboardManager\\default.json"));
}
// Tests RestoreCorruptedConfigs: when the original file has been deleted
// (not corrupted), restore should NOT recreate it from backup. The installer
// may have intentionally removed obsolete config files.
// Covers: configBackup.h RestoreCorruptedConfigs — fs::exists guard.
TEST_METHOD(RestoreSkipsDeletedOriginals)
{
TempDir dir;
dir.WriteFile(L"obsolete.json", R"({"old":true})");
updating::BackupConfigFiles(dir.path());
// Installer deletes the file
std::error_code ec;
fs::remove(dir.path() / L"obsolete.json", ec);
updating::RestoreCorruptedConfigs(dir.path());
// Should NOT be recreated
Assert::IsFalse(dir.FileExists(L"obsolete.json"));
}
// Tests RestoreCorruptedConfigs: when the backup file itself is corrupted
// (e.g., disk error during backup), restore should NOT copy corrupted
// backup over the original — that would make things worse.
// Covers: configBackup.h RestoreCorruptedConfigs — backup integrity check (B2 fix).
TEST_METHOD(RestoreSkipsCorruptedBackup)
{
TempDir dir;
dir.WriteFile(L"settings.json", R"({"theme":"dark"})");
updating::BackupConfigFiles(dir.path());
// Corrupt BOTH the original AND the backup
std::vector<char> nulls(50, '\0');
dir.WriteFileBytes(L"settings.json", nulls);
dir.WriteFileBytes(L"ConfigBackup\\settings.json", nulls);
updating::RestoreCorruptedConfigs(dir.path());
// Original should still be corrupted — we don't restore from bad backup
Assert::IsTrue(updating::IsJsonFileCorrupted(dir.path() / L"settings.json"));
}
};
// Simulates what actually happens during a PowerToys upgrade:
// 1. User has settings from normal use
// 2. Updater backs up before install (Stage 1)
// 3. Installer runs and corrupts some files (simulated)
// 4. Updater restores corrupted files (Stage 2)
// 5. PT relaunches and finds working configs
TEST_CLASS(UpgradeSimulationTests)
{
public:
// Tests full upgrade simulation: backup -> installer corrupts files -> restore.
// Verifies that corrupted files are restored and clean files are untouched.
// Covers: configBackup.h BackupConfigFiles + RestoreCorruptedConfigs —
// end-to-end with 5 modules, 2 corrupted, 3 clean.
// Setup: Realistic config structure with multiple modules.
TEST_METHOD(SimulateUpgradeWithCorruption)
{
TempDir dir;
// === User's real config state before upgrade ===
dir.WriteFile(L"settings.json",
R"({"startup":true,"theme":"dark","run_elevated":false,"download_updates_automatically":true})");
dir.WriteFile(L"FancyZones\\settings.json",
R"({"zones":[{"id":1,"rect":{"x":0,"y":0,"w":960,"h":1080}}]})");
dir.WriteFile(L"Workspaces\\workspaces.json",
R"({"workspaces":[{"name":"dev","apps":["code","terminal"]}]})");
dir.WriteFile(L"KeyboardManager\\default.json",
R"({"remapKeys":{"inProcess":[{"original":"0x41","new":"0x42"}]}})");
dir.WriteFile(L"MouseWithoutBorders\\settings.json",
R"({"machineKey":"abc123","connectToAll":true})");
// Non-JSON files that should be left alone
dir.WriteFile(L"update.log", "2026-04-11 update started");
// === Stage 1: Backup before killing PT ===
updating::BackupConfigFiles(dir.path());
// Verify backup was created correctly
Assert::IsTrue(dir.FileExists(L"ConfigBackup\\settings.json"));
Assert::IsTrue(dir.FileExists(L"ConfigBackup\\FancyZones\\settings.json"));
Assert::IsTrue(dir.FileExists(L"ConfigBackup\\Workspaces\\workspaces.json"));
Assert::IsTrue(dir.FileExists(L"ConfigBackup\\KeyboardManager\\default.json"));
Assert::IsTrue(dir.FileExists(L"ConfigBackup\\MouseWithoutBorders\\settings.json"));
Assert::IsFalse(dir.FileExists(L"ConfigBackup\\update.log"));
// === Installer runs: some files get corrupted (the #46179 scenario) ===
// Workspaces JSON filled with null bytes
dir.WriteFileBytes(L"Workspaces\\workspaces.json", std::vector<char>(512, '\0'));
// Main settings partially corrupted (null bytes injected)
std::vector<char> partialCorrupt = { '{', '"', 's', '\0', '\0', '\0', '\0', '}' };
dir.WriteFileBytes(L"settings.json", partialCorrupt);
// FancyZones, KBM, and MWB survive the install fine
// (this is realistic - not all files get corrupted)
// === Stage 2: Restore after install completes ===
updating::RestoreCorruptedConfigs(dir.path());
// === Verify: PT relaunches and finds working configs ===
// Corrupted files should be restored from backup
Assert::IsFalse(updating::IsJsonFileCorrupted(dir.path() / L"settings.json"));
Assert::IsFalse(updating::IsJsonFileCorrupted(dir.path() / L"Workspaces\\workspaces.json"));
Assert::AreEqual(
std::string(R"({"startup":true,"theme":"dark","run_elevated":false,"download_updates_automatically":true})"),
dir.ReadFile(L"settings.json"));
Assert::AreEqual(
std::string(R"({"workspaces":[{"name":"dev","apps":["code","terminal"]}]})"),
dir.ReadFile(L"Workspaces\\workspaces.json"));
// Clean files should be untouched (not overwritten with backup)
Assert::AreEqual(
std::string(R"({"zones":[{"id":1,"rect":{"x":0,"y":0,"w":960,"h":1080}}]})"),
dir.ReadFile(L"FancyZones\\settings.json"));
Assert::AreEqual(
std::string(R"({"remapKeys":{"inProcess":[{"original":"0x41","new":"0x42"}]}})"),
dir.ReadFile(L"KeyboardManager\\default.json"));
Assert::AreEqual(
std::string(R"({"machineKey":"abc123","connectToAll":true})"),
dir.ReadFile(L"MouseWithoutBorders\\settings.json"));
}
// Tests upgrade from an old version that has fewer modules than the new version.
// Verifies that new module configs (created by the installer) are not touched
// by restore, while corrupted old configs are restored.
// Covers: configBackup.h RestoreCorruptedConfigs — module dir in root that
// has no corresponding backup entry.
// Setup: Old version with 1 module -> backup -> new installer adds module -> corrupt old -> restore.
TEST_METHOD(SimulateUpgradeFromVeryOldVersion)
{
TempDir dir;
// Old version had fewer modules - only settings.json
dir.WriteFile(L"settings.json", R"({"theme":"dark","powertoys_version":"v0.60.0"})");
// Backup
updating::BackupConfigFiles(dir.path());
// New installer creates new module dirs that didn't exist before
dir.WriteFile(L"NewModule\\settings.json", R"({"enabled":true})");
// Old settings get corrupted during upgrade
dir.WriteFileBytes(L"settings.json", std::vector<char>(100, '\0'));
// Restore
updating::RestoreCorruptedConfigs(dir.path());
// Old settings restored
Assert::AreEqual(
std::string(R"({"theme":"dark","powertoys_version":"v0.60.0"})"),
dir.ReadFile(L"settings.json"));
// New module settings untouched (no backup existed for them)
Assert::AreEqual(
std::string(R"({"enabled":true})"),
dir.ReadFile(L"NewModule\\settings.json"));
}
};
// Tests for the update lifecycle: argument passing between Stage 1 and Stage 2,
// relaunch path construction, and the handoff that was broken in #42004/#43011/#44071.
TEST_CLASS(UpdateLifecycleTests)
{
public:
// Tests BuildStage2Arguments: output contains the stage 2 flag, installer path,
// and install directory — all three components needed for Stage 2.
// Covers: updateLifecycle.h BuildStage2Arguments — concatenation logic.
// Setup: Typical paths with spaces (Program Files).
TEST_METHOD(BuildStage2ArgumentsContainsInstallerAndInstallDir)
{
const auto args = updating::BuildStage2Arguments(
L"-update_now_stage_2",
L"C:\\Users\\test\\AppData\\Local\\PowerToys\\Updates\\powertoyssetup-x64.exe",
L"C:\\Program Files\\PowerToys");
// Must contain the stage 2 flag
Assert::IsTrue(args.find(L"-update_now_stage_2") != std::wstring::npos);
// Must contain the installer path (quoted)
Assert::IsTrue(args.find(L"powertoyssetup-x64.exe") != std::wstring::npos);
// Must contain the install directory (quoted) — this was MISSING before our fix
Assert::IsTrue(args.find(L"C:\\Program Files\\PowerToys") != std::wstring::npos);
}
// Tests BuildStage2Arguments: both paths are wrapped in double quotes to
// survive CommandLineToArgvW parsing when paths contain spaces.
// Covers: updateLifecycle.h BuildStage2Arguments — quote wrapping.
// Setup: Installer path with spaces.
TEST_METHOD(BuildStage2ArgumentsQuotesBothPaths)
{
const auto args = updating::BuildStage2Arguments(
L"-update_now_stage_2",
L"C:\\path with spaces\\installer.exe",
L"C:\\Program Files\\PowerToys");
// Count quotes — should have 4 (open/close for each path)
size_t quoteCount = std::count(args.begin(), args.end(), L'"');
Assert::AreEqual(size_t{ 4 }, quoteCount);
}
// Tests BuildPowerToysExePath: appends "PowerToys.exe" to the install dir.
// Covers: updateLifecycle.h BuildPowerToysExePath — fs::path / operator.
// Setup: Standard install path without trailing backslash.
TEST_METHOD(BuildPowerToysExePathAppendsExeName)
{
const auto path = updating::BuildPowerToysExePath(L"C:\\Program Files\\PowerToys");
Assert::AreEqual(std::wstring(L"C:\\Program Files\\PowerToys\\PowerToys.exe"), path);
}
// Tests BuildPowerToysExePath: trailing backslash does not produce double
// backslash (e.g., "...PowerToys\\PowerToys.exe").
// Covers: updateLifecycle.h BuildPowerToysExePath — fs::path normalizes separators.
// Setup: Install path with trailing backslash.
TEST_METHOD(BuildPowerToysExePathHandlesTrailingBackslash)
{
const auto path = updating::BuildPowerToysExePath(L"C:\\Program Files\\PowerToys\\");
Assert::AreEqual(std::wstring(L"C:\\Program Files\\PowerToys\\PowerToys.exe"), path);
}
// Tests BuildPowerToysExePath: empty string produces just "PowerToys.exe".
// Covers: updateLifecycle.h BuildPowerToysExePath — fs::path with empty input.
// Setup: Empty install directory string.
TEST_METHOD(BuildPowerToysExePathHandlesEmptyString)
{
const auto path = updating::BuildPowerToysExePath(L"");
Assert::AreEqual(std::wstring(L"PowerToys.exe"), path);
}
// Tests CanRelaunchAfterUpdate: returns true when Stage 2 receives
// the install directory (argCount >= 4), false otherwise.
// This is the gate that prevents relaunch when using an old Stage 1
// that didn't pass the install dir (#42004/#43011/#44071).
// Covers: updateLifecycle.h CanRelaunchAfterUpdate.
TEST_METHOD(CanRelaunchReflectsArgCount)
{
// Old Stage 1 (pre-fix): only passed action + installer = 3 args
Assert::IsFalse(updating::CanRelaunchAfterUpdate(0));
Assert::IsFalse(updating::CanRelaunchAfterUpdate(1));
Assert::IsFalse(updating::CanRelaunchAfterUpdate(2));
Assert::IsFalse(updating::CanRelaunchAfterUpdate(3));
// New Stage 1 (post-fix): passes action + installer + installDir = 4 args
Assert::IsTrue(updating::CanRelaunchAfterUpdate(4));
Assert::IsTrue(updating::CanRelaunchAfterUpdate(5));
}
// Tests BuildStage2Arguments + CommandLineToArgvW round-trip: the exact
// scenario where Stage 1 builds args and Windows parses them in Stage 2.
// Verifies quoting is correct so paths with spaces survive the round trip.
// Covers: updateLifecycle.h BuildStage2Arguments — quote correctness.
// Setup: Realistic paths with spaces and version numbers.
TEST_METHOD(Stage2ArgumentsCanBeRoundTrippedThroughCommandLineToArgvW)
{
const std::wstring installerPath = L"C:\\Users\\test user\\AppData\\Local\\PowerToys\\Updates\\powertoyssetup-0.86.0-x64.exe";
const std::wstring installDir = L"C:\\Program Files\\PowerToys";
const auto args = updating::BuildStage2Arguments(L"-update_now_stage_2", installerPath, installDir);
// Simulate what Windows does: prepend a fake exe name and parse
std::wstring commandLine = L"PowerToys.Update.exe " + args;
int argc = 0;
LPWSTR* argv = CommandLineToArgvW(commandLine.c_str(), &argc);
Assert::IsNotNull(argv);
Assert::AreEqual(4, argc);
Assert::AreEqual(std::wstring(L"-update_now_stage_2"), std::wstring(argv[1]));
Assert::AreEqual(installerPath, std::wstring(argv[2]));
Assert::AreEqual(installDir, std::wstring(argv[3]));
LocalFree(argv);
}
};
}

View File

@@ -1,45 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>UpdatingUnitTests</RootNamespace>
<ProjectSubType>NativeUnitTestProject</ProjectSubType>
<ProjectName>Updating.UnitTests</ProjectName>
</PropertyGroup>
<PropertyGroup Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\tests\UpdatingUnitTests\</OutDir>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>..\;..\..\;..\..\..\;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="UpdatingTests.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(UsePrecompiledHeaders)' != 'false'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

View File

@@ -1,5 +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.
#include "pch.h"

View File

@@ -1,17 +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.
#ifndef PCH_H
#define PCH_H
#include <atomic>
#include <Windows.h>
// Suppressing 26466 - Don't use static_cast downcasts - in CppUnitTest.h
#pragma warning(push)
#pragma warning(disable : 26466)
#include "CppUnitTest.h"
#pragma warning(pop)
#endif //PCH_H

View File

@@ -1,228 +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.
#pragma once
#include <filesystem>
#include <fstream>
#include <string>
namespace updating
{
namespace fs = std::filesystem;
struct BackupResult
{
int filesBackedUp{ 0 };
int errors{ 0 };
};
struct RestoreResult
{
int filesRestored{ 0 };
int filesChecked{ 0 };
int errors{ 0 };
};
// Check if a JSON file is corrupted (contains null bytes, as seen in #46179)
inline bool IsJsonFileCorrupted(const fs::path& filePath)
{
try
{
std::ifstream file(filePath, std::ios::binary);
if (!file.is_open())
{
return false;
}
constexpr size_t c_readChunkSize{ 4096 };
char buffer[c_readChunkSize];
while (file.read(buffer, c_readChunkSize) || file.gcount() > 0)
{
const auto bytesRead = file.gcount();
for (std::streamsize i = 0; i < bytesRead; ++i)
{
if (buffer[i] == '\0')
{
return true;
}
}
}
return false;
}
catch (...)
{
return true;
}
}
// Backup all JSON config files before update to protect against corruption (#46179)
inline BackupResult BackupConfigFiles(const fs::path& rootPath)
{
BackupResult result{};
try
{
const fs::path backupDir = rootPath / L"ConfigBackup";
std::error_code ec;
fs::remove_all(backupDir, ec);
fs::create_directories(backupDir, ec);
if (ec)
{
result.errors++;
return result;
}
for (const auto& entry : fs::directory_iterator(rootPath, ec))
{
if (ec)
{
result.errors++;
break;
}
if (entry.is_regular_file() && entry.path().extension() == L".json")
{
std::error_code copyEc;
fs::copy_file(entry.path(), backupDir / entry.path().filename(), fs::copy_options::overwrite_existing, copyEc);
if (copyEc)
{
result.errors++;
}
else
{
result.filesBackedUp++;
}
}
else if (entry.is_directory())
{
const auto dirName = entry.path().filename().wstring();
if (dirName == L"ConfigBackup" || dirName == L"Updates")
{
continue;
}
const auto moduleBackup = backupDir / entry.path().filename();
fs::create_directories(moduleBackup, ec);
std::error_code moduleEc;
for (const auto& moduleEntry : fs::directory_iterator(entry.path(), moduleEc))
{
if (moduleEc)
{
result.errors++;
break;
}
if (moduleEntry.is_regular_file() && moduleEntry.path().extension() == L".json")
{
std::error_code copyEc;
fs::copy_file(moduleEntry.path(), moduleBackup / moduleEntry.path().filename(), fs::copy_options::overwrite_existing, copyEc);
if (copyEc)
{
result.errors++;
}
else
{
result.filesBackedUp++;
}
}
}
}
}
}
catch (...)
{
result.errors++;
}
return result;
}
// Restore JSON configs from backup if corruption is detected after update.
// Cleans up the backup directory afterward.
inline RestoreResult RestoreCorruptedConfigs(const fs::path& rootPath)
{
RestoreResult result{};
try
{
const fs::path backupDir = rootPath / L"ConfigBackup";
if (!fs::exists(backupDir))
{
return result;
}
std::error_code ec;
for (const auto& backupEntry : fs::directory_iterator(backupDir, ec))
{
if (ec)
{
result.errors++;
break;
}
if (backupEntry.is_regular_file() && backupEntry.path().extension() == L".json")
{
const auto originalPath = rootPath / backupEntry.path().filename();
result.filesChecked++;
if (fs::exists(originalPath) && IsJsonFileCorrupted(originalPath) && !IsJsonFileCorrupted(backupEntry.path()))
{
std::error_code copyEc;
fs::copy_file(backupEntry.path(), originalPath, fs::copy_options::overwrite_existing, copyEc);
if (copyEc)
{
result.errors++;
}
else
{
result.filesRestored++;
}
}
}
else if (backupEntry.is_directory())
{
const auto moduleDir = rootPath / backupEntry.path().filename();
std::error_code moduleEc;
for (const auto& moduleBackupEntry : fs::directory_iterator(backupEntry.path(), moduleEc))
{
if (moduleEc)
{
result.errors++;
break;
}
if (moduleBackupEntry.is_regular_file() && moduleBackupEntry.path().extension() == L".json")
{
const auto originalModulePath = moduleDir / moduleBackupEntry.path().filename();
result.filesChecked++;
if (fs::exists(originalModulePath) && IsJsonFileCorrupted(originalModulePath) && !IsJsonFileCorrupted(moduleBackupEntry.path()))
{
std::error_code copyEc;
fs::copy_file(moduleBackupEntry.path(), originalModulePath, fs::copy_options::overwrite_existing, copyEc);
if (copyEc)
{
result.errors++;
}
else
{
result.filesRestored++;
}
}
}
}
}
}
// Clean up backup directory after restore check
fs::remove_all(backupDir, ec);
}
catch (...)
{
result.errors++;
}
return result;
}
}

View File

@@ -24,6 +24,8 @@
#include <regex>
#include <charconv>
#include <expected.hpp>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.ApplicationModel.h>

View File

@@ -1,47 +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.
#pragma once
#include <filesystem>
#include <string>
namespace updating
{
namespace fs = std::filesystem;
// Build the command-line arguments for Stage 2.
// Stage 1 passes the installer path and the PT install directory
// so Stage 2 can run the installer and relaunch PowerToys afterward.
// Note: paths containing embedded double-quote characters are not supported.
// This is safe because install paths come from get_module_folderpath().
inline std::wstring BuildStage2Arguments(
const std::wstring& stage2Flag,
const fs::path& installerPath,
const fs::path& installDir)
{
std::wstring arguments{ stage2Flag };
arguments += L" \"";
arguments += installerPath.c_str();
arguments += L"\" \"";
arguments += installDir.c_str();
arguments += L"\"";
return arguments;
}
// Build the full path to PowerToys.exe from the install directory.
// Used by Stage 2 to relaunch PT after a successful update.
inline std::wstring BuildPowerToysExePath(const std::wstring& installDir)
{
return (std::filesystem::path(installDir) / L"PowerToys.exe").wstring();
}
// Determine whether Stage 2 has enough information to relaunch PT.
// Returns true if the install directory argument was provided.
inline bool CanRelaunchAfterUpdate(int argCount)
{
// args[0]=exe, args[1]=action, args[2]=installer, args[3]=installDir
return argCount >= 4;
}
}

View File

@@ -87,7 +87,11 @@ namespace updating
// If the current version starts with 0.0.*, it means we're on a local build from a farm and shouldn't check for updates.
if constexpr (VERSION_MAJOR == 0 && VERSION_MINOR == 0)
{
#if USE_STD_EXPECTED
co_return std::unexpected(LOCAL_BUILD_ERROR);
#else
co_return nonstd::make_unexpected(LOCAL_BUILD_ERROR);
#endif
}
try
@@ -139,7 +143,11 @@ namespace updating
catch (...)
{
}
#if USE_STD_EXPECTED
co_return std::unexpected(NETWORK_ERROR);
#else
co_return nonstd::make_unexpected(NETWORK_ERROR);
#endif
}
#pragma warning(pop)

View File

@@ -5,7 +5,14 @@
#include <filesystem>
#include <variant>
#include <winrt/Windows.Foundation.h>
//#if __MSVC_VERSION__ >= 1933 // MSVC begin to support std::unexpected in 19.33
#if __has_include(<expected> ) // use the same way with excepted-lite to detect std::unexcepted, as using it as backup
#include <expected>
#define USE_STD_EXPECTED 1
#else
#include <expected.hpp>
#define USE_STD_EXPECTED 0
#endif
#include <common/version/helper.h>
#include <wil/coroutine.h>
@@ -24,7 +31,12 @@ namespace updating
std::wstring installer_filename;
};
using github_version_info = std::variant<new_version_download_info, version_up_to_date>;
#if USE_STD_EXPECTED
using github_version_result = std::expected<github_version_info, std::wstring>;
#else
using github_version_result = nonstd::expected<github_version_info, std::wstring>;
#endif
wil::task<github_version_result> get_github_version_info_async(bool prerelease = false);
wil::task<std::optional<std::filesystem::path>> download_new_version_async(new_version_download_info new_version);

View File

@@ -9,6 +9,7 @@
<ProjectName>ApplicationUpdate</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="..\..\..\deps\expected.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>

164
src/logging/logging.vcxproj Normal file
View File

@@ -0,0 +1,164 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<ProjectName>spdlog</ProjectName>
</PropertyGroup>
<Import Project="$(RepoRoot)deps\spdlog.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<OutDir>$(RepoRoot)$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
<DebugInformationFormat>None</DebugInformationFormat>
<ExceptionHandling>Sync</ExceptionHandling>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<WarningLevel>Level4</WarningLevel>
<PreprocessorDefinitions>WIN32;_WINDOWS;SPDLOG_COMPILED_LIB;SPDLOG_WCHAR_FILENAMES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ObjectFileName>$(IntDir)</ObjectFileName>
<FunctionLevelLinking>true</FunctionLevelLinking>
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration>
</ClCompile>
<Lib>
<AdditionalOptions>%(AdditionalOptions)</AdditionalOptions>
</Lib>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="$(RepoRoot)deps\spdlog\src\spdlog.cpp" />
<ClCompile Include="$(RepoRoot)deps\spdlog\src\stdout_sinks.cpp" />
<ClCompile Include="$(RepoRoot)deps\spdlog\src\color_sinks.cpp" />
<ClCompile Include="$(RepoRoot)deps\spdlog\src\file_sinks.cpp" />
<ClCompile Include="$(RepoRoot)deps\spdlog\src\async.cpp" />
<ClCompile Include="$(RepoRoot)deps\spdlog\src\cfg.cpp" />
<ClCompile Include="$(RepoRoot)deps\spdlog\src\fmt.cpp" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\async.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\async_logger-inl.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\async_logger.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\common-inl.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\common.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\formatter.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\fwd.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\logger-inl.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\logger.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\pattern_formatter-inl.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\pattern_formatter.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\spdlog-inl.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\spdlog.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\stopwatch.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\tweakme.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\version.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\backtracer-inl.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\backtracer.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\circular_q.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\console_globals.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\file_helper-inl.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\file_helper.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\fmt_helper.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\log_msg-inl.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\log_msg.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\log_msg_buffer-inl.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\log_msg_buffer.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\mpmc_blocking_q.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\null_mutex.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\os-inl.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\os.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\periodic_worker-inl.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\periodic_worker.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\registry-inl.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\registry.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\synchronous_factory.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\tcp_client-windows.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\tcp_client.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\thread_pool-inl.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\thread_pool.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\details\windows_include.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\android_sink.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\ansicolor_sink-inl.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\ansicolor_sink.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\base_sink-inl.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\base_sink.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\basic_file_sink-inl.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\basic_file_sink.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\daily_file_sink.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\dist_sink.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\dup_filter_sink.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\msvc_sink.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\null_sink.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\ostream_sink.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\ringbuffer_sink.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\rotating_file_sink-inl.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\rotating_file_sink.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\sink-inl.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\sink.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\stdout_color_sinks-inl.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\stdout_color_sinks.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\stdout_sinks-inl.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\stdout_sinks.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\syslog_sink.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\systemd_sink.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\tcp_sink.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\win_eventlog_sink.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\wincolor_sink-inl.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\sinks\wincolor_sink.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\fmt\bin_to_hex.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\fmt\chrono.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\fmt\fmt.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\fmt\ostr.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\fmt\bundled\chrono.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\fmt\bundled\color.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\fmt\bundled\compile.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\fmt\bundled\core.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\fmt\bundled\format-inl.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\fmt\bundled\format.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\fmt\bundled\locale.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\fmt\bundled\os.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\fmt\bundled\ostream.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\fmt\bundled\posix.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\fmt\bundled\printf.h" />
<ClInclude Include="$(RepoRoot)deps\spdlog\include\spdlog\fmt\bundled\ranges.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,122 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="$(ProjectDir)..\..\deps\spdlog\src\spdlog.cpp" />
<ClCompile Include="$(ProjectDir)..\..\deps\spdlog\src\stdout_sinks.cpp" />
<ClCompile Include="$(ProjectDir)..\..\deps\spdlog\src\color_sinks.cpp" />
<ClCompile Include="$(ProjectDir)..\..\deps\spdlog\src\file_sinks.cpp" />
<ClCompile Include="$(ProjectDir)..\..\deps\spdlog\src\async.cpp" />
<ClCompile Include="$(ProjectDir)..\..\deps\spdlog\src\cfg.cpp" />
<ClCompile Include="$(ProjectDir)..\..\deps\spdlog\src\fmt.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\async.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\async_logger-inl.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\async_logger.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\common-inl.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\common.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\formatter.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\fwd.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\logger-inl.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\logger.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\pattern_formatter-inl.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\pattern_formatter.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\spdlog-inl.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\spdlog.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\stopwatch.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\tweakme.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\version.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\backtracer-inl.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\backtracer.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\circular_q.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\console_globals.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\file_helper-inl.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\file_helper.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\fmt_helper.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\log_msg-inl.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\log_msg.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\log_msg_buffer-inl.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\log_msg_buffer.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\mpmc_blocking_q.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\null_mutex.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\os-inl.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\os.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\periodic_worker-inl.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\periodic_worker.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\registry-inl.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\registry.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\synchronous_factory.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\tcp_client-windows.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\tcp_client.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\thread_pool-inl.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\thread_pool.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\details\windows_include.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\android_sink.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\ansicolor_sink-inl.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\ansicolor_sink.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\base_sink-inl.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\base_sink.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\basic_file_sink-inl.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\basic_file_sink.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\daily_file_sink.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\dist_sink.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\dup_filter_sink.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\msvc_sink.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\null_sink.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\ostream_sink.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\ringbuffer_sink.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\rotating_file_sink-inl.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\rotating_file_sink.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\sink-inl.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\sink.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\stdout_color_sinks-inl.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\stdout_color_sinks.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\stdout_sinks-inl.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\stdout_sinks.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\syslog_sink.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\systemd_sink.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\tcp_sink.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\win_eventlog_sink.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\wincolor_sink-inl.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\sinks\wincolor_sink.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\fmt\bin_to_hex.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\fmt\chrono.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\fmt\fmt.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\fmt\ostr.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\fmt\bundled\chrono.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\fmt\bundled\color.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\fmt\bundled\compile.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\fmt\bundled\core.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\fmt\bundled\format-inl.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\fmt\bundled\format.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\fmt\bundled\locale.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\fmt\bundled\os.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\fmt\bundled\ostream.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\fmt\bundled\posix.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\fmt\bundled\printf.h" />
<ClInclude Include="$(ProjectDir)..\..\deps\spdlog\include\spdlog\fmt\bundled\ranges.h" />
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{CDF4BA23-560C-3A6F-8D1C-2F5ACA434329}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\spdlog">
<UniqueIdentifier>{EFFE8123-D806-3145-8ABC-B48562A6C8F2}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\spdlog\details">
<UniqueIdentifier>{C546A431-88F1-390F-B0F0-D9CAC274B7F5}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\spdlog\fmt">
<UniqueIdentifier>{08320F28-6D0D-3217-B0B3-A98758C02C97}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\spdlog\fmt\bundled">
<UniqueIdentifier>{C856528D-4506-3A62-B279-CBB4558CB61D}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\spdlog\sinks">
<UniqueIdentifier>{A5EE33C4-AB64-38F0-BF4A-CCD02FFAB715}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{8B480F42-A230-3344-A387-2D050CFF7D9C}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

View File

@@ -2,8 +2,6 @@
// 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.Text;
using AdvancedPaste.Helpers;
using Windows.ApplicationModel.DataTransfer;
@@ -15,26 +13,15 @@ namespace AdvancedPaste.FuzzTests
{
public static void FuzzToJsonFromXmlOrCsv(ReadOnlySpan<byte> input)
{
// Decode the input bytes as UTF-8 text. `ReadOnlySpan<byte>.ToString()`
// returns the type name (e.g. "System.ReadOnlySpan<Byte>[N]") rather
// than the bytes, so an explicit decode is required to actually exercise
// the helper with the provided input.
string text = Encoding.UTF8.GetString(input);
var dataPackage = new DataPackage();
dataPackage.SetText(text);
// Use GetAwaiter().GetResult() so any thrown exception surfaces with its
// original type. `Task.Run(...).Result` wraps thrown exceptions in an
// AggregateException, which would prevent the
// `when (ex is ArgumentException)` filter below from matching.
try
{
_ = Task.Run(async () => await JsonHelper.ToJsonFromXmlOrCsvAsync(dataPackage.GetView())).GetAwaiter().GetResult();
var dataPackage = new DataPackage();
dataPackage.SetText(input.ToString());
_ = Task.Run(async () => await JsonHelper.ToJsonFromXmlOrCsvAsync(dataPackage.GetView())).Result;
}
catch (Exception ex) when (ex is ArgumentException)
{
// It's important to filter out any *expected* exceptions from our code here.
// This is an example. It's important to filter out any *expected* exceptions from our code here.
// However, catching all exceptions is considered an anti-pattern because it may suppress legitimate
// issues, such as a NullReferenceException thrown by our code. In this case, we still re-throw
// the exception, as the ToJsonFromXmlOrCsvAsync method is not expected to throw any exceptions.

View File

@@ -57,21 +57,7 @@ namespace AdvancedPaste.Helpers
return string.Empty;
}
string text;
try
{
text = await clipboardData.GetTextAsync();
}
catch (Exception ex)
{
// GetTextAsync goes through WinRT/COM and can fail for reasons outside
// our control (e.g. clipboard contention, malformed payloads from other
// apps). The contract for this helper is that it does not throw — any
// failure to read clipboard text should be treated as "no text".
Logger.LogError("Failed reading text from clipboard", ex);
return string.Empty;
}
var text = await clipboardData.GetTextAsync();
string jsonText = string.Empty;
// If the text is already JSON, return it

View File

@@ -28,12 +28,7 @@ namespace ipc
try
{
m_stream = std::ofstream(path, std::ios::binary);
if (!m_stream.is_open())
{
return E_FAIL;
}
m_stream = std::ofstream(path);
return S_OK;
}
catch (...)

View File

@@ -61,7 +61,7 @@ namespace winrt::PowerToys::FileLocksmithLib::Interop::implementation
com_array<hstring> NativeMethods::ReadPathsFromFile()
{
std::ifstream stream(paths_file(), std::ios::binary);
std::ifstream stream(paths_file());
std::vector<std::wstring> result_cpp;
std::wstring line;
@@ -98,7 +98,7 @@ namespace winrt::PowerToys::FileLocksmithLib::Interop::implementation
bool NativeMethods::StartAsElevated(array_view<hstring const> paths)
{
std::ofstream stream(paths_file(), std::ios::binary);
std::ofstream stream(paths_file());
const WCHAR newline = L'\n';
for (uint32_t i = 0; i < paths.size(); i++)

View File

@@ -84,6 +84,7 @@
..\..\..\common;
..\..\..\common\logger;
..\..\..\common\utils;
..\..\..\..\deps\spdlog\include;
%(AdditionalIncludeDirectories)
</AdditionalIncludeDirectories>
</ClCompile>

View File

@@ -63,6 +63,7 @@
$(RepoRoot)src\common\SettingsAPI;
$(RepoRoot)src\common\Telemetry;
$(RepoRoot)src\;
..\..\..\..\deps\spdlog\include;
./;
%(AdditionalIncludeDirectories)
</AdditionalIncludeDirectories>

View File

@@ -10,11 +10,12 @@
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
namespace MouseWithoutBorders.Core;
internal enum SeverityLevel
namespace MouseWithoutBorders.Class
{
Information,
Warning,
Error,
internal class SeverityLevel
{
internal static readonly SeverityLevel Information = new SeverityLevel();
internal static readonly SeverityLevel Error = new SeverityLevel();
internal static readonly SeverityLevel Warning = new SeverityLevel();
}
}

View File

@@ -196,6 +196,11 @@ internal static class Encryption
return (uint)((hashValue[0] << 23) + (hashValue[1] << 16) + (hashValue[^1] << 8) + hashValue[2]);
}
internal static string GetDebugInfo(string st)
{
return string.IsNullOrEmpty(st) ? st : ((byte)(Common.GetBytesU(st).Sum(value => value) % 256)).ToString(CultureInfo.InvariantCulture);
}
internal static string CreateDefaultKey()
{
return CreateRandomKey();

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