From a5b9cc77ec2e00b6e336d3e0fae182179a49a297 Mon Sep 17 00:00:00 2001 From: Gleb Khmyznikov Date: Mon, 8 Dec 2025 18:41:48 -0800 Subject: [PATCH] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 73e379238bcefa2f10ab7da4791af830467fc3c2 Author: leileizhang Date: Tue Dec 9 10:13:48 2025 +0800 Add FancyZones CLI for command-line layout management (#44078) ## Summary of the Pull Request Adds a new command-line interface (CLI) tool for FancyZones, enabling users and automation scripts to manage window layouts without the GUI. **Commands:** | Command | Aliases | Description | |---------|---------|-------------| | `help` | | Displays general help information for all commands | | `open-editor` | `editor`, `e` | Launch FancyZones layout editor | | `get-monitors` | `monitors`, `m` | List all monitors and their properties | | `get-layouts` | `layouts`, `ls` | List all available layouts with ASCII art preview | | `get-active-layout` | `active`, `a` | Show currently active layout | | `set-layout ` | `set`, `s` | Apply layout by UUID or template name | | `open-settings` | `settings` | Open FancyZones settings page | | `get-hotkeys` | `hotkeys`, `hk` | List all layout hotkeys | | `set-hotkey ` | `shk` | Assign hotkey (0-9) to custom layout | | `remove-hotkey ` | `rhk` | Remove hotkey assignment | **Key Capabilities:** - ASCII art visualization of layouts (grid, focus, priority-grid, canvas) - Support for both template layouts and custom layouts - Monitor-specific layout targeting (`--monitor N` or `--all`) - Real-time notification to FancyZones via Windows messages - Native AOT compilation support for fast startup ### Example Usage ```bash # List all layouts with visual previews FancyZonesCLI.exe ls # Apply "columns" template to all monitors FancyZonesCLI.exe s columns --all # Set custom layout on monitor 2 FancyZonesCLI.exe s {uuid} --monitor 2 # Assign hotkey Win+Ctrl+Alt+3 to a layout FancyZonesCLI.exe shk 3 {uuid} ``` https://github.com/user-attachments/assets/2b141399-a4ca-4f64-8750-f123b7e0fea7 ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 4710b816b40b70216563e533de53a5db7a41337b Author: Dave Rayment Date: Mon Dec 8 21:01:56 2025 +0000 [CmdPal] Optimise MainListPage's results display by merging already-sorted lists (#44126) ## Summary of the Pull Request This PR replaces the current LINQ-based results compilation query of combining, sorting and filtering the four result sources with a 3-way merge operation plus a final append. It provides a performance increase as well as a significant reduction in allocations. ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **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 The existing code: 1. Limits the number of apps returned to a pre-defined maximum. 2. Sorts the apps list. 3. Appends filtered items, scored fallback items and the apps list together. 4. Sorts the three lists based on their score. 5. Appends the non-scored fallback items, with empty items excluded. 6. Selects just the `Item` from each. 7. Creates an array from the enumerable. ```csharp if (_filteredApps?.Count > 0) { limitedApps = _filteredApps.OrderByDescending(s => s.Score).Take(_appResultLimit).ToList(); } var items = Enumerable.Empty>() .Concat(_filteredItems is not null ? _filteredItems : []) .Concat(_scoredFallbackItems is not null ? _scoredFallbackItems : []) .Concat(limitedApps) .OrderByDescending(o => o.Score) // Add fallback items post-sort so they are always at the end of the list // and eventually ordered based on user preference .Concat(_fallbackItems is not null ? _fallbackItems.Where(w => !string.IsNullOrEmpty(w.Item.Title)) : []) .Select(s => s.Item) .ToArray(); ``` We can exploit the fact that each of the three 'scored' lists are pre-ordered, and replace the query with a 3-way merge and final append of the non-scored fallback items. By pre-sizing the results array we can avoid all the extra allocations of the LINQ-based solution. ### Proof of pre-ordering In `UpdateSearchText`, each of the lists is defined by calling `ListHelpers.FilterListWithScores`: ```csharp // Produce a list of everything that matches the current filter. _filteredItems = [.. ListHelpers.FilterListWithScores(newFilteredItems ?? [], SearchText, scoreItem)]; ``` ```csharp _scoredFallbackItems = ListHelpers.FilterListWithScores(newFallbacksForScoring ?? [], SearchText, scoreItem); ``` ```csharp var scoredApps = ListHelpers.FilterListWithScores(newApps, SearchText, scoreItem); ... _filteredApps = [.. scoredApps]; ``` In `FilterListWithScores`, the results are ordered by score: ```csharp var scores = items .Select(li => new Scored() { Item = li, Score = scoreFunction(query, li) }) .Where(score => score.Score > 0) .OrderByDescending(score => score.Score); ``` (This also makes the existing `OrderByDescending()` for `_filteredApps` before the LINQ query redundant.) ### K-way merge Since the results are pre-sorted, we can do a direct merge in linear time. This is what the new `MainListPageResultFactory`'s `Create` achieves. As the lists may be different sizes, the routine does a 3-way merge, followed by a 2-way merge and a single list drain to finish. Each element is only visited once. ### Benchmarks A separate benchmark project is [here](https://github.com/daverayment/MainListBench), written with Benchmark.net. The project compares the current LINQ-based solution against: 1. An Array-based algorithm which pre-assigns a results array and still sorts the 3 scored sets of results. This shows a naive non-LINQ solution which is still _O(n log n)_ because of the sort. 2. The k-way merge, which is described above. _O(n)_ for both time and space complexity. 3. A heap merge algorithm, which uses a priority queue instead of tracking each of the lists separately. (This is _O(n log k)_ in terms of time complexity and _O(n + k)_ for space.) Care is taken to ensure stable sorting of items. When preparing the benchmark data, items with identical scores are assigned to confirm each algorithm performs identically to the LINQ `OrderBy` approach, which performs a stable sort. Results show that the merge performs best in terms of both runtime performance and allocations, sometimes by a significant margin. Compared to the LINQ approach, merge runs 400%+ faster and with at most ~20% of the allocations: image image See here for all charts and raw stats from the run: https://docs.google.com/spreadsheets/d/1y2mmWe8dfpbLxF_eqPbEGvaItmqp6HLfSp-rw99hzWg/edit?usp=sharing ### Cons 1. Existing performance is not currently an issue. This could be seen as a premature optimisation. 2. The new code introduces an inherent contract between the results compilation routine and the lists, i.e. that they must be sorted. This PR was really for research and learning more about CmdPal (and a bit of algorithm practice because it's Advent of Code time), so please feel free to reject if you feel the cons outweigh the pros. ## Validation Steps Performed - Added unit tests to exercise the new code, which confirm that the specific ordering is preserved, and the filtering and pre-trimming of the apps list is performed as before. - Existing non-UI unit tests run. NB: I _could not_ run any UI Tests on my system and just got an early bail-out each time. - Manual testing in (non-AOT) Release mode. commit b8a0163419f0800153e40a0e26ba77a4b453c74d Author: Sam Rueby Date: Mon Dec 8 13:13:33 2025 -0500 CmdPal: Arrow keys move logical grid pages (#43870) ## Summary of the Pull Request ## PR Checklist - [X] Closes: #41939 - [X] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed Before ![Before](https://github.com/user-attachments/assets/49853e8d-9113-425c-8230-e49fb9b8d640) After ![After](https://github.com/user-attachments/assets/a4597fe6-6503-4502-99cf-350425f5ef51) I noticed the double "active" line around the items when the ListPage is focused. I was unable to find where that is defined. Ideally, the black-border would go away. I tested with AOT turned on. The behavior accounts for suggestions. If the SearchBar is focused and there is a suggestion, right-arrow will [continue] to complete the suggestion. commit 06fcbdac400d6856f9e771a98828505b83152571 Author: Gordon Lam <73506701+yeelam-gordon@users.noreply.github.com> Date: Mon Dec 8 18:52:33 2025 +0800 Update WinAppSDK to 1.8.3 (#44146) ## Summary of the Pull Request This pull request updates several dependencies to newer versions in the `Directory.Packages.props` file. The main focus is on upgrading the Microsoft Windows App SDK packages to ensure the project uses the latest features and bug fixes. Dependency version updates: * Upgraded `Microsoft.WindowsAppSDK`, `Microsoft.WindowsAppSDK.Foundation`, `Microsoft.WindowsAppSDK.AI`, and `Microsoft.WindowsAppSDK.Runtime` to their latest respective versions, replacing previous 1.8.25* releases with newer builds. commit d515c67def98da77f9335f997bac7520538c2103 Author: leileizhang Date: Mon Dec 8 13:34:33 2025 +0800 Improve install scope detection to prevent mixed user/machine installations (#43931) ## Summary of the Pull Request The old implementation checked `HKLM\Software\Classes\powertoys\InstallScope` first. If this key existed (even as a remnant from incomplete uninstall), it would immediately return `PerMachine` without validating the actual installation. ### Fix - Uses Windows standard Uninstall registry (most reliable source of truth) - Identifies PowerToys Bundle by exact `BundleUpgradeCode` GUID match - MSI component entries (always in HKLM) are automatically ignored since they don't have `BundleUpgradeCode` - Checks HKCU first, then HKLM, properly handling the fact that Bundle location reflects true install scope ## PR Checklist - [x] Closes: #43696 - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 9439b6df41a94c36b7a1152404afaa6cbb7deed0 Author: Noraa Junker Date: Mon Dec 8 04:55:51 2025 +0100 [Settings] Create a global static instance of SettingsUtils (#44064) ## Summary of the Pull Request SettingsUtils is initialized multiple times over the whole solution. This creates one singeltone instance (with the default settings), so it only has to be initialized once (and improve performance a bit with that) ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit a37add8f0865588f13ffe02cc9cebad5a84b71f9 Author: 舰队的偶像-岛风酱! Date: Mon Dec 8 11:14:00 2025 +0800 feat(cmdpal): add pinyin support for Chinese input method (#39354) ## Summary of the Pull Request - Add ToolGood.Words.Pinyin package to support pinyin conversion - Implement pinyin matching in StringMatcher class - Update project dependencies and Directory.Packages.props ## PR Checklist - [x] **Closes:** #38417 #39343 - [ ] **Communication:** I've discussed this with core contributors already. If 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 I've completed a rough implementation of pinyin support, but since I'm currently unsure where to add the toggle for pinyin support, this feature is enabled by default for now. https://github.com/user-attachments/assets/59df0180-05ad-4b4a-a858-29aa15e40fd2 ## Validation Steps Performed --------- Signed-off-by: 舰队的偶像-岛风酱! Co-authored-by: Yu Leng commit 60deec68150e2b5abf13ad29a0fa26d3f9473035 Author: Gordon Lam <73506701+yeelam-gordon@users.noreply.github.com> Date: Mon Dec 8 09:52:55 2025 +0800 Using centralized package management for vcxproj (#43920) ## Summary of the Pull Request This pull request updates the build system for several native and managed projects, modernizing NuGet package management and improving code analysis configuration. The main changes involve switching from legacy `packages.config` and manual `.props`/`.targets` imports to PackageReference style for native projects, updating package versions, and streamlining code analysis settings. **Build system modernization and package management:** * Migrated native projects (`PowerToys.MeasureToolCore.vcxproj`, `FindMyMouse.vcxproj`) from legacy `packages.config` and manual `.props`/`.targets` imports to NuGet PackageReference style, simplifying dependency management and build configuration. This includes removing the `packages.config` file and related import/error logic, and introducing `PackageReference` items for required packages. [[1]](diffhunk://#diff-76320b3a74a9241df46edb536ba0f817d7150ddf76bb0fe677e2b276f8bae95aL3-R18) [[2]](diffhunk://#diff-76320b3a74a9241df46edb536ba0f817d7150ddf76bb0fe677e2b276f8bae95aR41-L41) [[3]](diffhunk://#diff-76320b3a74a9241df46edb536ba0f817d7150ddf76bb0fe677e2b276f8bae95aL145-R153) [[4]](diffhunk://#diff-d3a7d80ebbca915b42727633451e769ed2306b418ef3d82b3b04fd5f79560f17L1-L17) [[5]](diffhunk://#diff-0f27869c4e90c8fd2c81f5688c58da99afcc9e5767e69ef7938265dbb6928e0fL3-R13) * Updated the centralized package versions in `Directory.Packages.props`, adding new entries for `boost`, `boost_regex-vc143`, `Microsoft.Windows.ImplementationLibrary`, and `Microsoft.WindowsAppSDK.Foundation` to support the new build system and dependencies. [[1]](diffhunk://#diff-5baf5f9e448ad54ab25a091adee0da05d4d228481c9200518fcb1b53a65d4156R10-R11) [[2]](diffhunk://#diff-5baf5f9e448ad54ab25a091adee0da05d4d228481c9200518fcb1b53a65d4156R74-R77) **Code analysis improvements:** * Added configuration to both native and managed projects (`PowerToys.MeasureToolCore.vcxproj`, `MeasureToolUI.csproj`) to suppress specific warnings (81010002) and exclude NuGet cache files from code analysis, reducing noise and improving build performance. [[1]](diffhunk://#diff-76320b3a74a9241df46edb536ba0f817d7150ddf76bb0fe677e2b276f8bae95aL3-R18) [[2]](diffhunk://#diff-4f2b49a1a5cc7da36ee6d5044792ef681fd0ea5bea12db9ebd4c3090680d4b07R6-R11) **Project reference and output handling:** * Updated the managed project (`MeasureToolUI.csproj`) to handle native project outputs more robustly, ensuring the WinMD and DLL files are available at runtime and configuring the project reference to avoid assembly reference issues. **Compiler configuration:** * Enhanced C++ compiler settings in `Cpp.Build.props` to treat angle-bracket includes as external, disable warnings and analysis for external headers, and optimize build performance. commit 7e791f2815dbfc84319d14faf9bedf30f7bb9fde Author: Dave Rayment Date: Mon Dec 8 01:45:46 2025 +0000 [ImageResizer] Fix Fill mode not cropping image when Shrink Only was engaged and scale was 1 (#43855) ## Summary of the Pull Request This PR fixes an Image Resizer issue where **Fill** mode operations were silently aborted when **Shrink Only** was enabled (the default) and scale was 1.0 on one dimension, resulting in files that were renamed according to the intended target size but which actually contained the original, unmodified image. This also fixes a latent bug regarding square images and the **Ignore Orientation** setting, and improves the readability of the core `Transform` method. ## PR Checklist - [x] Closes: #43772 - [ ] **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 ### Fix **Shrink Only** logic preventing the correct cropping of images **Issue:** When using **Fill** mode, the scaling factor is calculated based on the larger dimension to ensure the image fills the target box. In scenarios where one dimension matches the target and the other overflows (e.g. shrinking a 100x100 pixel image to 50x100), the calculated scale factor is `1.0`. The previous `ShrinkOnly` logic included this: ```csharp if (_settings.ShrinkOnly && _settings.SelectedSize.Unit != ResizeUnit.Percent && (scaleX >= 1 || scaleY >= 1)) { return source; } ``` This correctly prevents `ShrinkOnly` operations from returning upscaled result images, but it also exits too early for cases where the user is cropping the image across one dimension only, leaving the other at scale 1. Effectively, the later cropping code is never run and instead of returning the cropped image, the original is returned. The _intended_ target dimensions are correct, which results in the filename parts not matching the resulting image size. **Fix:** The logic has been split between upscaling and cropping, so: 1. If the scale on either dimension is > `1.0`, return the source (explicitly preventing upscaling for **Shrink Only** mode). 2. If the scale is <= `1.0` then check if the original dimensions exceed the target dimensions. If a crop is required, proceed with it even if the scale is exactly `1.0`. ### Fix for square images triggering orientation swap **Issue:** The "Ignore Orientation" check in the original code used a compound boolean check: ```csharp (originalWidth < originalHeight != width < height) ``` This clever but less than readable statement detects orientation mismatches. The section also includes a logic issue. When the original image was square, `originalWidth < originalHeight` evaluated to `false`, treating it as Landscape. If the target dimensions were Portrait, the logic detected a mismatch and swapped the target dimensions incorrectly, which would crop the height instead of the width. 'Fortunately' this bug was masked by the first bug, as the crop code would never be reached anyway. **Fix:** The orientation detection routine was refactored to explicitly check for Landscape vs. Portrait states. Square images are now naturally excluded, as they have neither Landscape nor Portrait orientations. This now prevents the dimensions from being swapped. ### Refactoring/readability The main `Transform` method has been cleaned up: - Replaced widespread use of `var` with `double` and `int` for dimension and scale calculations. - Replaced the non-obvious XOR orientation check (`a < b != c < d`) with named booleans (`isInputLandscape`, `isTargetPortrait` etc.) to make the intent more self-documenting. - New and expanded comments throughout. ## Validation Steps Performed Three new unit tests have been added to `ResizeOperationTests.cs` to cover the **Fill** mode edge cases: 1. `TransformHonorsFillWithShrinkOnlyWhenCropRequired`: Verifies than an image requiring a crop but no scaling is processed correctly (tests that the original bug report is resolved). 2. `TransformHonorsFillWithShrinkOnlyWhenUpscaleAttempted`: Confirms that when `ShrinkOnly` is set, any upscaling operations are still blocked. 3. `TransformHonorsFillWithShrinkOnlyWhenNoChangeRequired`: Verifies that the system returns the source if neither scaling nor cropping is required. I also manually verified the bug fix with a test 4000 x 6000 pixel source file with 1920 x `Auto` **Fill** mode and **Shrink Only** settings, mirroring the original user's settings, and their source and target dimensions. commit 2b0ecc2979b6bbe0c017045199ea10873caedd65 Author: Noraa Junker Date: Sun Dec 7 19:36:05 2025 +0100 Quick accent character set fixes (#43504) ## Summary of the Pull Request * Fix double uppercase theta character * Fix some redundant special symbols ## PR Checklist - [x] Closes: #43457 #43137 #41570 - [ ] **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 commit 45cf3de15d8ea159fb2426eb2b186a6af2c5c082 Author: Jiří Polášek Date: Sun Dec 7 10:18:02 2025 +0100 CmdPal: Fix a line-break in RDC extension error toasts (#44129) ## Summary of the Pull Request This PR fixes a line break in the RDC extension toast message, replacing unescaped \r with a new line (\r in the XML is not recognized as a new line escape sequence). ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit bf8c5485017cdd62cba2c963f88ba67a55bc3beb Author: Jiří Polášek Date: Sun Dec 7 10:10:45 2025 +0100 CmdPal: Make text of text Settings button on Command Bar localizable (#44128) ## Summary of the Pull Request See title ## PR Checklist - [x] Closes: #44108 - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 121c6c07124d81903373a5f64fc1654042440d90 Author: Carlos Rafael Ramirez Date: Sun Dec 7 02:54:10 2025 +0100 Add RGB hex color preview to Advanced Paste clipboard history (#43990) ## Summary of the Pull Request This pull request adds support for recognizing and displaying clipboard items that are valid RGB hex color codes (such as `#FFBFAB` or `#abc`) in the Advanced Paste module. It introduces logic to detect hex color strings, converts them to color values, and updates the UI to show a color preview for these items. The changes also include comprehensive unit tests for the new functionality. ## PR Checklist - [x] Closes: #43538 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **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 **Clipboard color detection and conversion:** * Added `ClipboardItemHelper.IsRgbHexColor` method using a compiled regex to identify valid hex color strings in clipboard text. [[1]](diffhunk://#diff-7429196ad30cd0bce57b102669da4dc13d43a09579e99ceac7cc0f7dc101cd2bR62-R86) [[2]](diffhunk://#diff-7429196ad30cd0bce57b102669da4dc13d43a09579e99ceac7cc0f7dc101cd2bR112-R114) * Introduced `HexColorConverterHelper.ConvertHexColorToRgb` utility to convert hex color strings to `Windows.UI.Color`, handling both 3-digit and 6-digit formats. **UI enhancements for color previews:** * Updated `ClipboardHistoryItemPreviewControl` to include a color preview grid that displays an ellipse filled with the detected color and the color code as text, using the new `HexColorToBrushConverter`. [[1]](diffhunk://#diff-2ed6014d4c17037b9cd0ab397e40b9069b1e7fe47a700673f34e8217d78124d5R29-R48) [[2]](diffhunk://#diff-2ed6014d4c17037b9cd0ab397e40b9069b1e7fe47a700673f34e8217d78124d5R14) [[3]](diffhunk://#diff-0c26c92697f6bb38fa40160fc8b18f0876ddc8d828a510034411001aa2e05063R1-R28) * Modified logic in `ClipboardHistoryItemPreviewControl.xaml.cs` to ensure color previews are shown only for detected color items and to adjust visibility of text and glyph previews accordingly. **Unit tests for color detection and conversion:** * Added unit tests for hex color conversion (`HexColorToColorConverterTests.cs`) and color detection logic (`ClipboardItemHelperTests.cs`) to verify correct behavior for valid, invalid, and edge-case inputs. [[1]](diffhunk://#diff-d81d997d5fb414f1563c31c38681113aaa9c847ef05bb77662d30bd1310d6b8eR1-R61) [[2]](diffhunk://#diff-185e8954ca6f061bf5d60d0c61ac6cfd87bd1a48ebda11a8172e3496a050fe85R1-R36) ## Validation Steps Performed * Copied to the clipboard a color encoded text like: #FFBFAB * Opened Advanced Paste and noticed the color: image --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: crramirez <8397379+crramirez@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> commit e68526b8d8fce059a0ccd1026a6d6e9780efa808 Author: Jiří Polášek Date: Fri Dec 5 23:32:24 2025 +0100 CmdPal: Add configuration option for Escape key behavior (#43354) ## Summary of the Pull Request This PR adds a new option to the **General** page in **Settings**: Escape key behavior — a dropdown with the following choices: - Clear search first, then go back - Current behavior. - If the search box contains text, it is cleared; otherwise goes back. - On the home page, CmdPal is dismissed. - Go back - Leaves the search text intact. - If the page is not transient, the search text reappears when returning. - On the home page, CmdPal is dismissed. - Hide window and go home (Always dismiss) - Immediately dismisses CmdPal and navigates to the home page. - Ignores the **Go home when activated** setting. - Search text is cleared. - Hide window - Just hides the window. - Intended to be used with #43355. This implementation preserves existing behavior, except for **Always dismiss**, which always forces navigation to the home page. ## Pictures? Pictures! image ## PR Checklist - [x] Closes: #38311 - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 995a699de77110570c9b1172792a5def3b82be36 Author: ruslanlap <106077551+ruslanlap@users.noreply.github.com> Date: Fri Dec 5 18:21:01 2025 +0200 [PowerToysRun][Docs] Add QuickAI plugin to third-party plugins list (#43238) Adds QuickAI plugin to the third-party plugins documentation. QuickAI is an AI-powered assistance plugin that provides instant, smart responses from multiple providers (Groq, Together, Fireworks, OpenRouter, Cohere) directly in PowerToys Run. Repository: https://github.com/ruslanlap/PowerToysRun-QuickAi --------- Co-authored-by: Niels Laute commit 5f6df35d8d741066734a0fe446c94dfc64890072 Author: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri Dec 5 10:20:33 2025 -0600 Add semantic headings to Dashboard page for accessibility (#42438) ## Summary Fixes #37668 by adding proper semantic heading structure to the Dashboard (Home) page, enabling screen reader users to navigate the page efficiently using heading shortcuts. ## Problem The Dashboard page lacked semantic heading elements, making it difficult for users of assistive technologies to understand the page structure and navigate between sections. When using screen readers with heading navigation (H key in scan mode), no headings were announced, violating WCAG 2.2 Success Criterion 1.3.1 (Info and Relationships). ## Solution Added `AutomationProperties.HeadingLevel` attributes to provide proper heading hierarchy: 1. **Dashboard Title** - Marked as Level 1 (H1) heading - Added `AutomationProperties.HeadingLevel="1"` to the "Home" page title - Follows the same pattern as `SettingsPageControl.xaml` 2. **Card Titles** - Marked as Level 2 (H2) headings - Added `AutomationProperties.HeadingLevel="Level2"` to the Card component - Applies to all card sections: "Quick Access", "Shortcuts Overview", and "Utilities" - Follows the same pattern as `SettingsGroup.xaml` ## Resulting Structure ``` H1: Home (Dashboard Title) ├─ H2: Quick Access ├─ H2: Shortcuts Overview └─ H2: Utilities ``` ## Impact - Screen reader users can now use heading navigation (H key) to jump between sections on the Dashboard page - Provides proper document structure that follows WCAG 2.2 Level A guidelines - No visual or functional changes - only accessibility metadata added - Consistent with existing accessibility patterns used throughout the Settings UI ## Testing - Changes follow existing patterns in `SettingsPageControl.xaml` (Level 1) and `SettingsGroup.xaml` (Level 2) - Only XAML accessibility attributes added - no code logic changes - Minimal, surgical changes: 2 lines across 2 files ## References - Issue: #37668 - WCAG 2.2: [Success Criterion 1.3.1 - Info and Relationships](https://www.w3.org/WAI/WCAG22/Understanding/info-and-relationships)
Original prompt > > ---- > > *This section details on the original issue you should resolve* > > No Heading Defined on the Home Page. > ### Microsoft PowerToys version > > v0.94.2 > > ### Installation method > > PowerToys auto-update > > ### Area(s) with issue? > > New+ > > ### Steps to reproduce > > **Repro Steps:** > > 1. Open the Power Toys. > 2. Now Select Home from the left navigation pane. > 3. Now Turn on narrator and turn on scan mode. > 4. Now use Quick navigation H key for headings. > 5. Observe the issue. > > ### ✔️ Expected Behavior > > The home page should contain at least one semantic heading (typically an

) that describes the main topic or purpose of the page. > > ### ❌ Actual Behavior > > The home page does not contain any semantic heading tags (e.g.,

,

, etc.). While text may be visually styled to look like headings, no actual heading elements are present in the page’s HTML structure. > > ### Additional Information > > **User Impact:** > Users of screen readers and other assistive technologies rely on headings to understand the structure of the page and navigate efficiently. > > **WCAG Reference:** > https://www.w3.org/WAI/WCAG22/Understanding/info-and-relationships > > **Attachments:** > > https://github.com/user-attachments/assets/5140b50c-67fc-40d5-bf80-40e2a2bb7782 > > ### Other Software > > _No response_ > > ## Comments on the Issue (you are @copilot in this section) > > > >

Fixes microsoft/PowerToys#42421 --- 💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: niels9001 <9866362+niels9001@users.noreply.github.com> Co-authored-by: Niels Laute commit cffdecbc1b6f614a2fc49a0c67db6d8f0c98bca4 Author: Noraa Junker Date: Fri Dec 5 14:55:45 2025 +0100 Add documentation of bot commands and fix some devdocs (#43399) ## Summary of the Pull Request * Fixes location of `style.md` file * Deletes duplicated `localization.md` file * Adds documentation about the bot commands. * Adds links to aka.ms link docs and the new document ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Dev docs:** Added/updated commit a4d8405957197c19fef0735978a52c49f4d3a5eb Author: Noraa Junker Date: Fri Dec 5 14:54:13 2025 +0100 Fix dpi issues in Quick Accent (#43314) ## Summary of the Pull Request ## PR Checklist - [x] Closes: #40865 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit cdf66a70e9f0ccc53aa2ef016039dcc140a30a7a Author: Niels Laute Date: Fri Dec 5 14:33:59 2025 +0100 [AdvancedPaste] Fix outdated string in Settings (#44099) Updating and removing outdated strings. Updated string: image commit 9dcddfd4b811207b04ae274e1e12fbd0eeb8d29c Author: Valentin Arthur Thomas <64769541+warquys@users.noreply.github.com> Date: Fri Dec 5 11:57:01 2025 +0100 Quotation mark (#30481) ## Add Quotation mark Add local quotation based on ~~VK_OEM_7(0xDE)~~ VK_OEM_COMMA(0xBC) key. Not all quotes have been added, only `‟ „ ” « » ‚ , ‘ ’ › ‹ '「 」 《 》 『 』〈 〉″ ‴ ⁗` Why not added : - ` ⹂ ⌜ ⌝ ❛ ❜ ❝ ❞ 🙶 🙷 🙸 ' 「 」 ` its redundant and would make too much and not readable. - ` ﹁ ﹂ ﹃ ﹄ ` I did not put them because there use for horizontal text ## PR Checklist - [x] Closes: https://github.com/microsoft/PowerToys/issues/29371 https://github.com/microsoft/PowerToys/issues/24832 - [ ] **Communication:** I've discussed this with core contributors already. If 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 (None) - [ ] [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 This PR is currently a draft, I still need to know if adding language-related keyboard management is a good idea or specifying the use of a gobal key to make it easier to manage all the keyboards in one. Some languages ​​can use different keyboards, I think this would become problematic if the keyboard does not match the key used by default. However, using a universal key can also pose an issue to finding the key. that remains to be discussed ## Validation Steps Performed commit 503bcbdf2d44d2002293bc35c23846e7d572c58c Author: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri Dec 5 07:33:37 2025 +0100 Restore missing "Quick access" menu item in tray icon context menu (#42676) ## Summary Restores the "Quick access" menu item that was accidentally removed from the PowerToys tray icon context menu. ## Issue Fixes #[issue_number] The "Quick access" menu item was missing from the tray icon's right-click context menu, preventing users from accessing this feature via the tray menu. **Expected menu:** ![Expected menu](https://github.com/user-attachments/assets/805b1436-5a08-42e7-a34d-b9848fd9a235) **Actual menu (before this fix):** ![Actual menu](https://github.com/user-attachments/assets/7584035d-e893-4f73-acc3-84d789e31e81) ## Changes - Added the missing `MENUITEM "Quick access\tLeft-click", ID_QUICK_ACCESS_MENU_COMMAND` entry as the first menu item in the `ID_TRAY_MENU` definition in `src/runner/runner.base.rc` ## Details The menu item was accidentally removed in commit f5797a065a5c2c448fd2b1780bd1353d712103c3. This PR restores it to its correct position as the first item in the tray menu. All supporting code was already in place: - The resource ID `ID_QUICK_ACCESS_MENU_COMMAND` (40006) is defined in `resource.base.h` - The resource string `QUICK_ACCESS_MENU_TEXT` is defined in `Resources.resx` - The menu command handler in `tray_icon.cpp` opens the Quick Access flyout window - The localization code updates the menu text at runtime ## Testing - ✅ Verified the menu item syntax is correct and matches existing patterns - ✅ Confirmed all supporting resource IDs and handler code exist - ✅ CI build verification pending After this fix, the tray menu will correctly display: 1. Quick access (Left-click) 2. Settings (Double-click) 3. Documentation 4. Report Bug 5. Close
Original prompt > > ---- > > *This section details on the original issue you should resolve* > > Quick Access missing in tray menu > ### Microsoft PowerToys version > > 0.95.0 > > ### Installation method > > PowerToys auto-update > > ### Area(s) with issue? > > System tray interaction > > ### Steps to reproduce > > 1. Right click the tray icon > 2. Look at the list of items which can be selected > 3. Notice that the "Quick access" is missing > > Expected menu ("Exit" is now "Close" I took this image from initial implementation): > > Image > > Actual menu right now: > > Image > > ### ✔️ Expected Behavior > > The "Quick access" menu item should be there > > ### ❌ Actual Behavior > > The menu item is missing > > ### Additional Information > > Windows 10 Pro 22H2 19045.6332 > > (Also it is the same on my other computers) > > ### Other Software > > _No response_ > > restore > > MENUITEM "Quick access\tLeft-click", ID_QUICK_ACCESS_MENU_COMMAND > > as first menu item of ID_TRAY_MENU MENU in src/runner/runner.base.rc > > ## Comments on the Issue (you are @copilot in this section) > > > @niels9001 > @davidegiacometti is this a regression from the PR where we updated the string names? > @davidegiacometti > Hi @niels9001 > I just realized that the menu was missing in https://github.com/microsoft/PowerToys/pull/40714 screenshots, but the regression was caused by https://github.com/microsoft/PowerToys/commit/f5797a065a5c2c448fd2b1780bd1353d712103c3. > Unfortunately, many of the `.rc` files in the PT codebase have UTF16-LE encoding and GitHub doesn't show diff. > >
Fixes microsoft/PowerToys#42618 --- 💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click [here](https://survey3.medallia.com/?EAHeSx-AP01bZqG0Ld9QLQ) to start the survey. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: davidegiacometti <25966642+davidegiacometti@users.noreply.github.com> commit 52f25619373ccb9af0fa0fbc7da916297ecac897 Author: Jiří Polášek Date: Wed Dec 3 17:16:25 2025 +0100 CmdPal: Find app for WinGet package (#43943) ## Summary of the Pull Request This PR introduces a bit of dark magic to resolve the correct installed app for a given WinGet package: - Packaged apps: matched using their package family name. - Everything else: matched using the product code (GUID) and heuristic registry lookup. - The registry rarely stores the executable path directly, so the logic compares install locations with known apps. - It attempts to pick the best candidate while avoiding uninstallers. - It’s not science — let’s call it `#666666` magic. - MSI API support was removed because it's too slow for this scenario. - If no reliable match is found, the command is skipped for now. The future plan is to redirect the user to the list of installed apps and search by display name, but that needs some supporting infrastructure first. - The command order for WinGet list entries was updated: **Install / Uninstall** is now the primary action, ensuring a stable UI since this command is always available. ## PR Checklist - [x] Closes: #43671 - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit dc30f3fd8e7e5481ecef0514e4c79279fd8f058d Author: Dustin L. Howett Date: Wed Dec 3 03:59:46 2025 -0600 build: move main and setup to SLNX (#43478) Closes #37100 This does not migrate the rest of the solutions (why do we have so many?) Not migrated: - TemplateCmdPalExtension.sln - FancyZonesEditor.sln - BugReportTool.sln - CleanUp_tool.sln - FancyZones_DrawLayoutTest.sln - FancyZones_zonable_tester.sln - FancyZone_HitTest.sln - MonitorReportTool.sln - PowerToyTemplate.sln - StylesReportTool.sln --------- Co-authored-by: vanzue commit 8f9a2c32cc07a9a5186767f3605bd7a9d4b3834a Author: Jessica Dene Earley-Cha <12740421+chatasweetie@users.noreply.github.com> Date: Tue Dec 2 09:59:57 2025 -0800 add missing powertoys events (#44016) ## Summary of the Pull Request This added missing telemetry events from modules that were not listed in DATA_AND_PRIVACY ## PR Checklist - [ ] Closes: #xxx - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected commit bcd1583bb7fb1357325b0fcca2eb57189369e896 Author: moooyo <42196638+moooyo@users.noreply.github.com> Date: Tue Dec 2 16:31:02 2025 +0800 [AOT] Refactor SettingsLib/SettingsUI for Native AOT compatibility (#42644) ## Summary of the Pull Request Key Changes: 1. Settings.UI.Library: - Added SettingsSerializationContext.cs with comprehensive JsonSerializable attributes for all settings types - Updated BasePTModuleSettings.ToJsonString() to use AOT-compatible serialization - Updated SettingsUtils.GetFile() to use AOT-compatible deserialization - Modified all ToString() methods in Properties classes to use SettingsSerializationContext - Converted struct fields to properties in SunTimes and MouseWithoutBordersProperties for serialization compatibility 2. Settings.UI: - Fixed namespace alias in SourceGenerationContextContext.cs to avoid conflicts For any future developers who discover incorrect settings resolution, please follow up my changes to add your setting type into JsonSerilizerContext. ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed Co-authored-by: Yu Leng commit b075a021dfacd6bf3d3d2b500a000b7e2d19cd59 Author: Carlos Zamora Date: Mon Dec 1 22:09:08 2025 -0800 Bump our telemetry package version (#44015) Data collection is still hard. This just makes it so that the build pipeline uses the updated PowerToys telemetry NuGet package. The updated package switches us over to use a diagnostic data provider group for compliance with some new regulations (i.e. DMA and EU Data Act). commit 9e43c23216762d34c931f3751930b3bbc4018a39 Author: Michael Clayton Date: Tue Dec 2 02:43:08 2025 +0000 Ready for Review - [Mouse Without Borders] - refactoring "Common" classes (Part 6 of 7) (#43208) ## Summary of the Pull Request **Part 6** of a [slow-running 7-part refactor](https://github.com/microsoft/PowerToys/issues/35155#issuecomment-2583334110) of the giant "Common" class in Mouse Without Borders into individual classes with tighter private scope. In this PR: * Extract the "Common" code from the following files: * ```Common.Encryption.cs```-> ```Core/Encryption.cs``` * ```Common.Package.cs``` -> ```Core/.cs``` * ```Common.ShutdownWithPowerToys.cs``` -> ```Core/ShutdownWithPowerToys.cs``` * ```Common.VK.cs``` -> ```Core/VK.cs```, ```Core/WM.cs``` * ```Common.WinAPI.cs``` -> ```Core/WinAPI.cs``` * Update references to the types in the new locations * Update unit test to verify functionality has only changed in an expected way ## PR Checklist - [x] Partially addresses #35155 - [x] **Communication:** I've discussed this with core contributors already. If work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end user facing strings can be localized - no changes in this PR - [x] **Dev docs:** Added/updated - no changes in this PR - [x] **New binaries:** Added on the required places - no changes in this PR - [ ] [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) - [x] **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 - no changes in this PR ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed ### Run manual tests from [Test Checklist Template](https://github.com/microsoft/PowerToys/blob/5bc7201ae2b75b53d3a4bc35119c867ecf71c5f6/doc/releases/tests-checklist-template.md#mouse-without-borders): * Install PowerToys on two PCs in the same local network: - [x] Verify that PowerToys is properly installed on both PCs. - [x] Configure Windows Firewall Rules - ```netsh advfirewall firewall add rule name="PowerToys.MouseWithoutBorders - mc" dir=in action=allow program="C:\src\mc\PowerToys\x64\Debug\PowerToys.exe" enable=yes remoteip=any profile=any protocol=tcp``` * Setup Connection: - [x] Open MWB's settings on the first PC and click the "New Key" button. Verify that a new security key is generated. - [x] Copy the generated security key and paste it in the corresponding input field in the settings of MWB on the second PC. Also enter the name of the first PC in the required field. - [x] Press "Connect" and verify that the machine layout now includes two PC tiles, each displaying their respective PC names. * Verify Connection Status: - [x] Ensure that the border of the remote PC turns green, indicating a successful connection. - [x] Enter an incorrect security key and verify that the border of the remote PC turns red, indicating a failed connection. * Test Remote Mouse/Keyboard Control: - [x] With the PCs connected, test the mouse/keyboard control from one PC to another. Verify that the mouse/keyboard inputs are correctly registered on the other PC. - [ ] Test remote mouse/keyboard control across all four PCs, if available. Verify that inputs are correctly registered on each connected PC when the mouse is active there. - unable to test - only 2 machines available * Test Remote Control with Elevated Apps: - note - the main PowerToys.exe must be running as a **non**-admin for these tests - [x] Open an elevated app on one of the PCs. Verify that without "Use Service" enabled, PowerToys does not control the elevated app. - [x] Enable "Use Service" in MWB's settings (need to run PowerToys.exe as admin to enable "Use Service", then restart PowerToys.exe as non-admin). Verify that PowerToys can now control the elevated app remotely. Verify that MWB processes are running as LocalSystem, while the MWB helper process is running non-elevated. - ```get-process -Name "PowerToys.MouseWithoutBorders*" -IncludeUserName | format-table Id, ProcessName, UserName``` - [x] Process: ```PowerToys.MouseWithoutBorders.exe``` - running as ```SYSTEM``` - [x] Process: ```PowerToys.MouseWithoutBorders.Helper.exe``` - running as current user - ```get-service -Name "PowerToys.*" | ft Status, Name, UserName; get-ciminstance -Class "Win32_Service" -Filter "Name like 'PowerToys%'" | ft ProcessId, Name``` - [x] Service: ```PowerToys.MWB.Service``` - running as ```Local System``` - [x] Toggle "Use Service" again, verify that each time you do that, the MWB processes are restarted. - [x] Run PowerToys elevated on one of the machines, verify that you can control elevated apps remotely now on that machine. * Test Module Enable Status: - [x] For all combinations of "Use Service"/"Run PowerToys as admin", try enabling/disabling MWB module and verify that it's indeed being toggled using task manager. * Test Disconnection/Reconnection: - [x] Disconnect one of the PCs from network. Verify that the machine layout updates to reflect the disconnection. - [x] Do the same, but now by exiting PowerToys. - [ ] Start PowerToys again, verify that the PCs are reconnected. * Test Various Local Network Conditions: - [ ] Test MWB performance under various network conditions (e.g., low bandwidth, high latency). Verify that the tool maintains a stable connection and functions correctly. * Clipboard Sharing: - [x] Copy some text on one PC and verify that the same text can be pasted on another PC. - [x] Use the screenshot key and Win+Shift+S to take a screenshot on one PC and verify that the screenshot can be pasted on another PC. - [x] Copy a file in Windows Explorer and verify that the file can be pasted on another PC. Make sure the file size is below 100MB. - [x] Try to copy multiple files and directories and verify that it's not possible (only the first selected file is being copied). * Drag and Drop: - [ ] Drag a file from Windows Explorer on one PC, cross the screen border onto another PC, and release it there. Verify that the file is copied to the other PC. Make sure the file size is below 100MB. - [ ] While dragging the file, verify that a corresponding icon is displayed under the mouse cursor. - [ ] Without moving the mouse from one PC to the target PC, press CTRL+ALT+F1/2/3/4 hotkey to switch to the target PC directly and verify that file sharing/dropping is not working. * Lock and Unlock with "Use Service" Enabled: - [x] Enable "Use Service" in MWB's settings. - [x] Lock a remote PC using Win+L, move the mouse to it remotely, and try to unlock it. Verify that you can unlock the remote PC. - [x] Disable "Use Service" in MWB's settings, lock the remote PC, move the mouse to it remotely, and try to unlock it. Verify that you can't unlock the remote PC. * Test Settings: - [ ] Change the rest of available settings on MWB page and verify that each setting works as described. ### Group Policy Tests See https://learn.microsoft.com/en-us/windows/powertoys/grouppolicy - [ ] Install *.admx / *.adml and check settings behave as expected - [ ] I'll expand the list of settings here when I get this far :-) - [ ] HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys - [x] ConfigureEnabledUtilityMouseWithoutBorders - [x] ```[missing]``` - "Activation -> Enable Mouse Without Borders" enabled, with GPO warning hidden - ```reg delete HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v ConfigureEnabledUtilityMouseWithoutBorders /f``` - [x] ```0``` - "Activation -> Enable Mouse Without Borders" set to "off" and disabled, with GPO warning visible - ```reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v ConfigureEnabledUtilityMouseWithoutBorders /t REG_DWORD /d 0 /f``` - [x] ```1``` - "Activation -> Enable Mouse Without Borders" set to "on" and disabled, with GPO warning visible - ```reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v ConfigureEnabledUtilityMouseWithoutBorders /t REG_DWORD /d 1 /f``` - [ ] MwbClipboardSharingEnabled - [ ] MwbFileTransferEnabled - [ ] MwbUseOriginalUserInterface - [ ] MwbDisallowBlockingScreensaver - [ ] MwbSameSubnetOnly - [ ] MwbValidateRemoteIp - [x] MwbDisableUserDefinedIpMappingRules - [x] ```[missing]``` - "Advanced Settings -> IP address mapping" enabled, with GPO warning hidden - ```reg delete HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v MwbDisableUserDefinedIpMappingRules /f``` - [x] ```0``` - "Advanced Settings -> IP address mapping" enabled, with GPO warning hidden - ```reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v MwbDisableUserDefinedIpMappingRules /t REG_DWORD /d 0 /f``` - [x] ```1``` - "Advanced Settings -> IP address mapping" disabled, with GPO warning visible - ```reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v MwbDisableUserDefinedIpMappingRules /t REG_DWORD /d 1 /f``` - [x] MwbPolicyDefinedIpMappingRules - [x] ```[missing]``` - "Advanced Settings -> IP address mapping" enabled, with GPO warning and GPO values hidden - ```reg delete HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v MwbPolicyDefinedIpMappingRules /f``` - [x] ```[empty value]``` - "Advanced Settings -> IP address mapping" enabled, with GPO warning hidden and GPO values hidden - ```reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v MwbPolicyDefinedIpMappingRules /t REG_MULTI_SZ /d "" /f``` - [x] ```[non-empty value]``` - "Advanced Settings -> IP address mapping" enabled, with GPO warning visible and GPO values visible - ```reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\PowerToys /v MwbPolicyDefinedIpMappingRules /t REG_MULTI_SZ /d "aaa 10.0.0.1\0bbb 10.0.0.2" /f``` commit bece9c921705872299b0a966365838a2141ec988 Author: Jiří Polášek Date: Tue Dec 2 03:25:38 2025 +0100 CmdPal: Adds a back button to Settings window (#44013) ## Summary of the Pull Request This PR introduces proper navigation support in the Settings window. - Enables the Go back button in the title bar. - Adds support for Alt + Left Arrow, mouse X1 button, and the Go back button. - Fixes breadcrumb updates and localization issues to prevent them from breaking during navigation. ## PR Checklist - [x] Closes: #44011 - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 32c13cead402b0e440383b2d1722a4c64dc7e7df Author: Jiří Polášek Date: Mon Dec 1 20:24:54 2025 +0100 CmdPal: Remove fallbacks from the home page when there's no query (#44005) ## Summary of the Pull Request This PR stops fallback commands from showing on the homepage when there’s no query, with the reasons detailed in the linked issue. ## PR Checklist - [x] Closes: #44004 - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 33808fdb9cd3af285a479d1986c6cb34570b35a6 Author: Jiří Polášek Date: Mon Dec 1 20:23:48 2025 +0100 CmdPal: Hide RDC fallback item by default (#43994) ## Summary of the Pull Request This fixes few nits with RDC extension: - hides the RDC fallback item from the home page when there’s no query; - fixes MSTSC process working directory (must physically exists or be an empty string) ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit f510be4c5384662fe0e15e6563d93e9ab7e420dc Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon Dec 1 22:29:21 2025 +0800 Build(deps): Bump actions/checkout from 3 to 6 (#43838) Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 6.
Release notes

Sourced from actions/checkout's releases.

v6.0.0

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v5.0.0...v6.0.0

v6-beta

What's Changed

Updated persist-credentials to store the credentials under $RUNNER_TEMP instead of directly in the local git config.

This requires a minimum Actions Runner version of v2.329.0 to access the persisted credentials for Docker container action scenarios.

v5.0.1

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v5...v5.0.1

v5.0.0

What's Changed

⚠️ Minimum Compatible Runner Version

v2.327.1
Release Notes

Make sure your runner is updated to this version or newer to use this release.

Full Changelog: https://github.com/actions/checkout/compare/v4...v5.0.0

v4.3.1

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4...v4.3.1

v4.3.0

What's Changed

... (truncated)

Changelog

Sourced from actions/checkout's changelog.

Changelog

V6.0.0

V5.0.1

V5.0.0

V4.3.1

V4.3.0

v4.2.2

v4.2.1

v4.2.0

v4.1.7

v4.1.6

v4.1.5

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3&new-version=6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> commit 4d3c223402bb037851b76f77dc143793eda88981 Author: Jiří Polášek Date: Mon Dec 1 02:32:30 2025 +0100 CmdPal: Fix grid views (#43991) ## Summary of the Pull Request This PR fixes the crash due to binding to a trimmed property. For this it converts runtime bindings on GridView to use `{x:Bind}` so this issue can't happen in the future. - Fixes a crash related to the `Visibility` property in gallery/grid views when trimmed during AOT builds. - Fixes ShowTitle and ShowSubtitle properties, they are now taken into account in a view. - Improves UI layout, removes some margins and maches the corner radius of the item contaienr with the item content in the gallery view. - Refactores gallery and grid views to move logic from the view to the view model so we can x:Bind to them. - Replaces `{Binding}` with `{x:Bind}` to improve performance and enable compile-time binding validation. - Properties related to grids are splatted on to the common `IGridPropertiesViewModel` interface. Subclassing would add extra overhead without substential benefit. - Adds new samples to showcase various grid view configurations. ## Pictures? Pictures! A) Gallery view (with title and subtitle) image B) Gallery view (only title) image C) Gallery view (no title or subtitle) image D) Small icons image E) Medium icons (with labels) image F) Medium icons (no labels) image ## PR Checklist - [x] Closes: #43973 - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 1ba5a258e93247a30a78519cceb5311cbf1e2441 Author: Jiří Polášek Date: Sun Nov 30 01:59:58 2025 +0100 CmdPal: Add custom search engine option to Web Search extension (#43941) ## Summary of the Pull Request This PR allows user to customize a search query in Command Palette's Web Search built-in extension. This will also solve a problem with some browser that doesn't handle argument in form "? " as it will allow user to specify the complete URI. - Introduces a new text box in Web Search extension settings for specifying a custom search engine URI - If the text box is non-empty, the provided URI is used for queries - If left empty, the extension defaults to previous behavior, sending queries in the format "? query" ## Pictures? Pictures! image ## PR Checklist - [x] Closes: #43940 - [x] Closes: #42867 - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 8aea589b0158e613f437359ef786f884124520bf Author: Jiří Polášek Date: Sun Nov 30 00:36:55 2025 +0100 CmdPal: Align spellchecker and naming to .NET guidelines (#43974) ## Summary of the Pull Request - Add command-line parameter value (icf) - Unify file and class name casing to match .NET naming conventions (RDP -> Rdp as Url, Dns, Xml) -- fixes IRDP spellchecking error - Rename IRdpConnectionManager to IRdpConnectionsManager (*s) to match the class name ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit afd9d4cc3c27aec7d6f1ec051b0547d20b4eacbc Author: Clint Rutkas Date: Sat Nov 29 15:11:17 2025 -0800 Update PowerToys download links to version 0.96.1 (#43965) ## Summary of the Pull Request ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit bc0a760aff6ecc9376bd1fc1f7ff8bfb22915638 Author: Jiří Polášek Date: Sat Nov 29 23:23:24 2025 +0100 CmdPal: Add mini dev center (#43939) ## Summary of the Pull Request This PR introduces a small ribbon to the CmdPal for app developers. The dev ribbon is dynamically added to the main window in local (non-CI) builds. It shows the number of logged errors and warnings, the current build configuration (Debug or Release), and whether it’s built with AOT. The flyout shows the latest errors and warnings and lets you quickly access the logs. ## Pictures? Pictures! image ## PR Checklist - [x] Closes: #43318 - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 06afe099734d3be7ed723666d829a3ce07354be0 Author: Michael Jolley Date: Sat Nov 29 13:07:19 2025 -0600 CmdPal: New Remote Desktop built-in extension (#43090) This PR introduces a new built-in extension for Remote Desktop users. It allows you to view past RDP connections, save predefined connections, and connect to any of them. Or start a new RDP connection. https://github.com/user-attachments/assets/6a5041a6-5741-4df0-a305-da7166f962e1 ### GitHub issue maintenance stuff Closes #38305 --------- Co-authored-by: Niels Laute Co-authored-by: Jiří Polášek commit 0de60445ea99aa97b4c640d192c5f55fdbda7629 Author: Jiří Polášek Date: Thu Nov 27 16:31:10 2025 +0100 CmdPal: Use Shell API to determine the default browser in WebSearch (#43339) ## Summary of the Pull Request This PR introduces a new method for determining the default browser using the Windows Shell API. The new provider selects the browser associated with the HTTPS protocol (falling back to HTTP if necessary). The original implementation is retained as a fallback for now, and the codebase is prepared for future extensions (e.g., manual default-browser selection). As a flyby, it also fixes an issue where commands continued showing the previous browser name if the user changed their default browser while the Command Palette was running. ## One-liner for change log Fixed default browser selection in the Web Search built-in extension. ## PR Checklist - [x] Closes: #42343 - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 47d4a65223c58f2e98f58ea3a51305c1206f8dd0 Author: Jiří Polášek Date: Thu Nov 27 16:24:47 2025 +0100 CmdPal: Add option to return to home automatically after a delay (#43551) ## Summary of the Pull Request This PR replaces the Go home when activated setting with a new Automatically return home option. This allows users to specify how long the Command Palette should wait after being dismissed before automatically returning to the home page. It also introduces migration logic to transition from the old setting to the new one. ## Pictures? Pictures! image ## PR Checklist - [x] Closes: #43355 - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 1b72c0b969935092022bc1dd066db7abcb51e534 Author: Kai Tao <69313318+vanzue@users.noreply.github.com> Date: Thu Nov 27 17:22:59 2025 +0800 Update check-spelling expect list (#43925) ## Summary of the Pull Request ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed Spell no complain commit 9160c82fc2181d1a29525a9f22baecd278228b52 Author: Pratyush Nalam Date: Thu Nov 27 05:15:06 2025 +0530 Update Command Palette's Learn More string to be consistent with other utilities (#43898) ## Summary of the Pull Request In the PowerToys "What's new" window, every utility has the text "Learn more about " next to the "Settings" button. Examples below: learnmore-fancyzones learnmore-textextractor The only exception is the Command Palette utility which just says "Learn more". learnmore-cmdpal This is an inconsistency and this PR fixes that string. ## PR Checklist - [x] Closes: #43897 - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 452e0dcf513fd2d8c09c5115a56ed5327c5d4b38 Author: Mike Hall Date: Wed Nov 26 14:08:34 2025 +0000 Module Loader tool for rapid testing of modules (#43813) ## Summary of the Pull Request ModuleLoader tool, a stand-alone Win32 executable for testing of PowerToy modules without needing branch builds. sample output from running the tool is below: .\ModuleLoader.exe .\powertoys.cursorwrap.dll PowerToys Module Loader v1.0 ============================= Loading module: .\powertoys.cursorwrap.dll Detected module name: cursorwrap Loading settings... Trying settings path: C:\Users\mikehall\AppData\Local\Microsoft\PowerToys\cursorwrap\settings.json Settings file loaded (315 characters) Settings loaded successfully. Loading module DLL... Module instance created successfully Module DLL loaded successfully. Module key: CursorWrap Module name: CursorWrap Applying settings to module... Settings applied. Registering module hotkeys... Module reports 1 legacy hotkey(s) Registering hotkey 0: Win+Alt+U - OK Hotkeys registered: 1 Enabling module... Module enabled. ============================= Module is now running! ============================= Module Status: - Name: CursorWrap - Key: CursorWrap - Enabled: Yes - Hotkeys: 1 registered Registered Hotkeys: Win+Alt+U Press Ctrl+C to exit. You can press the module's hotkey to toggle its functionality. Note that this doesn't integrate with Powertoys settings UI - this is purely to test Powertoys module functionality. ## PR Checklist - [ ] Closes: #xxx - [ ] **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 See details above. ## Validation Steps Performed ModuleLoader tested on Windows 11, Surface Laptop 7 Pro. commit 2c9a9e9fcab59ad66be052f1378be26ce6649bde Author: Jiří Polášek Date: Mon Nov 24 23:57:10 2025 +0100 CmdPal: Improve Command Palette behavior in "Last position" mode (#43543) ## Summary of the Pull Request This PR improves Command Palette behavior in “Last position” mode: - Correctly handles DPI changes between monitors. - Ensures the window is always visible — if it’s fully off-screen or has less than 100px visible on any axis, it is re-centered. ## PR Checklist - [x] Closes: #43398 - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 09c8c1d79a389483d12a3f4b535f2316ec31022a Author: leileizhang Date: Mon Nov 24 10:42:35 2025 +0800 [Hot Fix] Fix Image Resizer not working on Win10 (#43763) ## Summary of the Pull Request Windows 10 can’t launch the app using the Sparse Package. Remove the app manifest so that Image Resizer can start properly on Windows 10. We will figure out how to support Sparse Packages on Windows 10 in the next release. ## PR Checklist - [x] Closes: #43747 #43734 #43722 #43759 - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 95c8a83f797dac6bdf82a71bf93a1e0c16fb0080 Author: leileizhang Date: Mon Nov 24 10:08:12 2025 +0800 [Hotfix] Remove the properties in Prompt Execution Settings for OpenAI (#43766) ## Summary of the Pull Request Remove the properties in Prompt Execution Settings for OpenAI, as the new models may not support them. Will try to expose them in the UI so users can add them on their own in the next release. ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 2830ea919c05d6e37221c8c200a818c17e80d100 Author: Kai Tao <69313318+vanzue@users.noreply.github.com> Date: Mon Nov 24 09:51:27 2025 +0800 Advanced Paste: Adjust model parameter to make the result longer (#43768) ## Summary of the Pull Request Adjust model parameter to make the result longer ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 725ad21952e08ab0fab7547cf88d1f766edfb7e4 Author: Dave Rayment Date: Mon Nov 24 01:12:54 2025 +0000 [Awake] Fix issue with timed mode not expiring correctly (#43785) ## Summary of the Pull Request Resolves an issue with the timed mode's expiry not completing correctly. ## PR Checklist - [x] Closes: #43775 - [ ] **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 This was because of my recent change to the timed mode. The `Subscribe` method on the `Observable` interval accidentally wired the completion logic to the **Error** handler instead of the **Completion** handler because of the use of a discard `_` instead of an empty parameter list `()`. As a result of the incorrect overload being called, Awake stayed in the Timed state despite the timer reaching zero. ## Validation Steps Performed Confirmed that the timed mode times out and exits upon expiry. commit ebc3a139c5897191dad3357cc62d5b7dd1312bd5 Author: Erik Anderson Date: Fri Nov 21 02:34:34 2025 -0800 Fix typo in AI settings card description (#43757) ## Summary of the Pull Request The word "cloud" does not use a vowel sound, so the preceding word should be "A" instead of "An". ## PR Checklist - [X] Closes: #43756 - [ ] **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 - [X] **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 Co-authored-by: Erik Anderson commit 28dba2633e930156e9cf5a0ee6c78216f5171ec8 Author: Jaylyn Barbee <51131738+Jaylyn-Barbee@users.noreply.github.com> Date: Thu Nov 20 15:22:40 2025 -0800 [Light Switch][Dev Docs] Clarify LightSwitchService and LightSwitchStateManager roles (#43748) Updated LightSwitch module documentation to clarify the role of LightSwitchService and LightSwitchStateManager. --------- Co-authored-by: Niels Laute commit 9fbd3de3a2ec3d64457823586246b8fd797d0959 Author: Jiří Polášek Date: Thu Nov 20 16:23:42 2025 +0100 CmdPal: Add native debugging launch profile to launchSettings.json (#43718) ## Summary of the Pull Request See title. I’m too lazy to open the dialog and then revert the change later. ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 4a0d9912aea92130ef55b23f67fce2d27ef886e2 Author: Kai Tao <69313318+vanzue@users.noreply.github.com> Date: Thu Nov 20 09:57:29 2025 +0800 Advanced Paste: No cache for foundry local model list (#43716) ## Summary of the Pull Request Cache of the downloaded model will make the newly added model only work after running of powertoys, this disable the cache, so just downloaded model will take effect immediately ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed Validated locally commit 15c79a0176388f2707d51f90ec5880d334dfb94e Author: Dave Rayment Date: Wed Nov 19 08:50:25 2025 +0000 [Settings] Fix inconsistent description text for the mouse tools (#43651) ## Summary of the Pull Request Change some of the mouse utilities' descriptions from declarative to imperative, to match best practice and to be consistent with the other descriptions. ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed - Confirmed the changed descriptions were updated in Settings. commit 97d46efec2e2d9f0c6d5b1e083463c2e6d193888 Author: Dave Rayment Date: Wed Nov 19 08:49:40 2025 +0000 [Settings] Fix Dashboard toggle glitches and sorting UI (#43626) ## Summary of the Pull Request Fixes two UI bugs in the Settings Dashboard: module list glitching when toggling modules, and incorrect sort menu checkmarks. ## PR Checklist - [x] Closes: #43624 - [x] Closes: #43625 - [ ] **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 ### User-Facing Fixes #### 1. Module list glitching when toggling enabled state When enabling or disabling a module from the "Utilities" list, the entire list would flicker and redraw, causing other toggles to glitch. This made it appear as if multiple modules were being affected by a single change. **Root cause** The `AllModules` ObservableCollection was being completely cleared and re-populated on every change, forcing the UI to destroy and recreate all list items. **Fix** Refactored collection updates to modify items in-place: - Introduced `_moduleItems` master list, built once during initialization. - `RefreshModuleList()` now updates properties without clearing collections - `SortModuleList()` uses `ObservableCollection.Move()` instead of `Clear()`/`Add()` #### 2. Incorrect sort menu checkmark behaviour The checkmark in the "Sort by" menu would not update correctly when changing sort order, sometimes showing the incorrect item checked, or even both at once. **Root cause** The `IsChecked` prop on the `ToggleMenuFlyoutItem` is bound to `DashboardSortOrder`, but the binding was not updating because the ViewModel didn't raise a property change notification when the sort order was changed. **Fix** Added `OnPropertyChanged(nameof(DashboardSortOrder))` in `SortModuleList()`. ### Code quality improvements 1. Renamed `GetShortcutModules()` to `RefreshShortcutModules()`. The original name implied a getter, but the routine actually affects state by rebuilding the shortcut and action lists, violating the Command-Query Separation principle. 2. Added an `_isUpdatingFromUI` flag as a defensive measure against circular updates when a UI toggle is changed. 3. Separation of concerns for operations on the modules list. Building, sorting and refreshing it are separated. 4. Added comments and XML doc headers for new methods. Included brief description of GPO locking behaviour. ## Validation Steps Performed - Verified that toggling modules in the list no longer causes the list to flicker or for other toggles to glitch. - Confirmed that the sort order checkmarks update correctly and reflect the current sort order. - Tested GPO policy settings are still queried as before. - Checked sort behaviour is unaffected. ## Videos *Sorting UI* https://github.com/user-attachments/assets/3484bf63-2946-4460-83a5-361fa7e41c82 *Toggle behaviour* https://github.com/user-attachments/assets/1fae5429-6fa3-4431-80f3-0907dab4f326 --------- Co-authored-by: Gordon Lam (SH) commit 46242b384e000f6b63e77dbbf4a0db7fe21c5c19 Author: Kai Tao <69313318+vanzue@users.noreply.github.com> Date: Wed Nov 19 16:25:52 2025 +0800 96 release change log (#43330) ## Summary of the Pull Request ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed --------- Signed-off-by: Shawn Yuan (from Dev Box) Signed-off-by: Shawn Yuan Co-authored-by: Jiří Polášek Co-authored-by: Jaylyn Barbee <51131738+Jaylyn-Barbee@users.noreply.github.com> Co-authored-by: Jeremy Sinclair <4016293+snickler@users.noreply.github.com> Co-authored-by: leileizhang Co-authored-by: Shawn Yuan <128874481+shuaiyuanxx@users.noreply.github.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: niels9001 <9866362+niels9001@users.noreply.github.com> Co-authored-by: Niels Laute Co-authored-by: Dave Rayment Co-authored-by: Gleb Khmyznikov Co-authored-by: Gordon Lam (SH) Co-authored-by: Juju Anselum J <106316316+anselumjuju@users.noreply.github.com> Co-authored-by: Dustin L. Howett Co-authored-by: Leon Zandman Co-authored-by: Leon Zandman Co-authored-by: moooyo <42196638+moooyo@users.noreply.github.com> Co-authored-by: Yu Leng Co-authored-by: Mike Griese Co-authored-by: Michael Jolley Co-authored-by: Mario Hewardt Co-authored-by: Alex Mihaiuc <69110671+foxmsft@users.noreply.github.com> Co-authored-by: Mike Hall Co-authored-by: Trevor commit 84be261581029b5e9f6bcd2c858a3068016e6e65 Author: Niels Laute Date: Tue Nov 18 19:19:38 2025 -0800 Logo change for Azure Inference (#43686) ## Summary of the Pull Request ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 5a8095b70454cd092527c350289c7659e305ea6c Author: Niels Laute Date: Tue Nov 18 18:32:14 2025 -0800 Loc bug (#43685) ## Summary of the Pull Request ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 417c1a6b988505b92362af65c8cffa03678d9905 Author: Niels Laute Date: Tue Nov 18 16:21:14 2025 -0800 Update FoundryLocal.svg (#43682) ## Summary of the Pull Request ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 2593149d22b53fdd7e8a54f5057eaf90ed9c7585 Author: leileizhang Date: Tue Nov 18 14:22:03 2025 +0800 Fix OOBE Mouse Utilities crash by correcting localization key (#43664) ## Summary of the Pull Request - The OOBE Mouse Utilities page crashed when selected because the TextBlock with x:Uid="Oobe_MouseUtils_MousePointerCrosshairs" tried to bind a Description property that doesn’t exist. - Updated Resources.resw so the string entry is named Oobe_MouseUtils_MousePointerCrosshairs_Description.Text, matching the markdown description control instead of the TextBlock. - With the correct resource key, the XAML loader no longer resolves an invalid property and navigation succeeds. ## PR Checklist - [x] Closes: #43663 - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 0b50c38fe1a1aa58e7d1fee87a86aaaf3aa7e361 Author: Kai Tao <69313318+vanzue@users.noreply.github.com> Date: Tue Nov 18 12:59:52 2025 +0800 Advanced Paste: Refresh environment if foundry is not present (#43662) ## Summary of the Pull Request As title ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed [12:55:29.6763496] [Info] FoundryClient.cs::CreateAsync::23 [FoundryClient] First attempt failed, refreshing PATH and retrying [12:55:29.6766491] [Info] FoundryClient.cs::RefreshEnvironmentPath::225 [FoundryClient] Refreshing PATH environment variable from system [12:55:29.6768710] [Info] FoundryClient.cs::RefreshEnvironmentPath::266 [FoundryClient] Updating process PATH with latest system values [12:55:29.6769080] [Info] FoundryClient.cs::TryCreateClientAsync::33 [FoundryClient] Creating Foundry Local client [12:55:29.6769312] [Info] FoundryClient.cs::TryCreateClientAsync::45 [FoundryClient] Starting Foundry service using manager.StartServiceAsync() [12:55:29.9807668] [Info] FoundryClient.cs::TryCreateClientAsync::48 [FoundryClient] Foundry service started successfully Verified, fist launch successfully commit 840808b465a21abb772bcbec9036ca0fb1585c9a Author: Niels Laute Date: Tue Nov 18 03:28:40 2025 +0100 [AP] Adding a single scrollviewer and fixing hidden tabstop (#43660) ## Summary of the Pull Request ## PR Checklist - [x] Closes: #43655 - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit b50df36b703981af94258d28cc9e0d53b851af80 Author: Jiří Polášek Date: Tue Nov 18 03:00:37 2025 +0100 Setup: Hide apps in PowerToys.SpareApps package from Start Menu (#43650) ## Summary of the Pull Request This PR updates the Appx manifest for PowerToys.SpareApps to hide the apps from the Start Menu, as they lack proper visual elements like icons and text. ## PR Checklist - [x] Closes: #43647 - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit b94593ef7315f5dbb64ef3f9e356e722532b9bca Author: Jiří Polášek Date: Tue Nov 18 00:55:14 2025 +0100 Settings: Add ScrollViewer to Command Palette page in PowerToys Settings (#43649) commit 7a01d56179d5bf345a1498c3ff7e1c2a9eb802b2 Author: Mario Hewardt Date: Mon Nov 17 07:26:42 2025 -0800 Updates version for standalone release (#43645) ## Summary of the Pull Request Updates the version for standalone release ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 130e9a0a6867720a4a4ef6acc0dfc9724f702491 Author: Kai Tao <69313318+vanzue@users.noreply.github.com> Date: Mon Nov 17 12:55:22 2025 +0800 cmdpal: Fix launch by button in settings not work (#43634) ## Summary of the Pull Request Shell does not know it's a protocol, so add protocol to it. ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed Locally verified commit 34c37f2d38df13b0837f67f8ffb802c9d2428bd5 Author: Kai Tao <69313318+vanzue@users.noreply.github.com> Date: Mon Nov 17 09:48:32 2025 +0800 Add not signed dll (#43631) ## Summary of the Pull Request This dll is not signed, will fail the pipeline ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 47aed03c039ebf1052bbc3f10c45d796b01148b7 Author: Niels Laute Date: Sun Nov 16 15:13:40 2025 +0100 [AP] Loc fix (#43617) ## Summary of the Pull Request ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 6423c7693d5c5f25ea2d9f19628da2b310274756 Author: Niels Laute Date: Sun Nov 16 15:02:38 2025 +0100 [CmdPal] Settings page refresh (#43487) - Refreshed the CmdPal page. - CmdPal can now also be activated from this page by clicking a button - Added a Preview InfoBar for FL in AP image ## Summary of the Pull Request ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed --------- Co-authored-by: vanzue commit 3e14d50f65220bf1f1e5b16c645818b2fa9ec4e5 Author: Kai Tao <69313318+vanzue@users.noreply.github.com> Date: Sun Nov 16 15:26:05 2025 +0800 Advanced paste: Add more error handle for foundry local (#43600) ## Summary of the Pull Request Foundry local sdk will not run models that is not in catalog, when catalog removes some, the old ones will fail executing, so add error hint for users to re-configure the models in settings. ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed image commit db7c9e180e113f9e53c26ce093d1767e70fa54d1 Author: Jaylyn Barbee <51131738+Jaylyn-Barbee@users.noreply.github.com> Date: Sat Nov 15 08:08:20 2025 -0500 [Light Switch] Removed logs from every tick, only logging key events. (#43572) Title commit bcc3ded2801d7f8110b79468b53ba451c614f9c6 Author: Michael Jolley Date: Sat Nov 15 07:07:52 2025 -0600 CmdPal: Adding page Id to OpenPage telemetry event (#43584) @niels9001 requested this. As the name says commit 24a3cdd48656d4a24c88629e3e123c54ca9f5c47 Author: Mario Hewardt Date: Fri Nov 14 17:36:31 2025 -0800 Fixes regressions introduced with GIF support (#43589) ## Fixes regressions introduced with GIF support: - Switches default recording format back to MP4 - Fixes framerate issues between the two formats - Fixes file path names ## PR Checklist - [ ] Closes: #xxx - [x ] **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 - Switches default recording format back to MP4 - Fixes framerate issues between the two formats - Fixes file path names - ## Validation Steps Performed Manual testing commit 1884e6abc1e5b724b85cb0d138b5b2e15f12022f Author: Shawn Yuan <128874481+shuaiyuanxx@users.noreply.github.com> Date: Fri Nov 14 16:56:23 2025 +0800 Remove unused properties in AP (#43564) ## Summary of the Pull Request This pull request removes legacy provider configuration migration logic and associated data structures from the Advanced Paste AI provider settings. The changes simplify the codebase by eliminating support for legacy provider configuration snapshots and related migration methods, focusing configuration management on the current provider model. ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed --------- Signed-off-by: Shawn Yuan (from Dev Box) commit ad4b553bb1edec6387b0b6418f6204f61ff2a499 Author: leileizhang Date: Fri Nov 14 16:15:15 2025 +0800 Remove all AdvancedPaste stored keys during uninstall (#43563) ## Summary of the Pull Request Remove all AdvancedPaste stored keys during uninstall ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed commit 193d9aacbe78a7c284d00fb59a2d8b052b7eebf5 Author: Dustin L. Howett Date: Thu Nov 13 17:59:21 2025 -0600 BugReportTool: replace cziplib with tar.exe (#41127) BugReportTool is the last consumer in the PowerToys repo of cziplib, a library we use to produce ZIP files. This pull request replaces cziplib with a simple CreateProcess call that spawns `tar.exe`, which comes with Windows as of RS4 and can produce ZIP files! I've tested this by producing a bug report archive and attempting to open it with File Explorer. It works fine. We have taken every precaution to ensure that we do not allow any attacker-controlled input to tar's command line. We are *not* using `system()`, and we are not opening up a vector through which a nefarious caller can perform shell injection. We do not pass filenames to tar except that of the final archive. We do not pass directory names to tar; we rely on the current directory instead. --- .github/actions/spell-check/allow/code.txt | 7 + .github/actions/spell-check/expect.txt | 10 +- .pipelines/ESRPSigning_core.json | 2 + .pipelines/packages.config | 2 +- .pipelines/v2/templates/job-build-project.yml | 12 +- .../v2/templates/job-build-ui-tests.yml | 4 +- .../templates/steps-build-installer-vnext.yml | 10 +- ...eps-update-winappsdk-and-restore-nuget.yml | 11 +- Cpp.Build.props | 11 +- DATA_AND_PRIVACY.md | 76 +- Directory.Packages.props | 12 +- NOTICE.md | 32 + PowerToys.sln | 3396 ----------------- PowerToys.slnx | 1045 +++++ doc/devdocs/commands.md | 34 + doc/devdocs/core/installer.md | 8 +- .../core/settings/settings-implementation.md | 4 +- doc/devdocs/development/debugging.md | 2 +- doc/devdocs/development/dev-with-vscode.md | 10 +- doc/devdocs/{ => development}/style.md | 0 doc/devdocs/development/ui-tests.md | 2 +- doc/devdocs/localization.md | 165 - doc/devdocs/modules/alwaysontop.md | 2 +- doc/devdocs/modules/fancyzones.md | 4 +- doc/devdocs/modules/keyboardmanager/debug.md | 4 +- doc/devdocs/modules/lightswitch.md | 2 +- doc/devdocs/modules/screenruler.md | 2 +- doc/devdocs/modules/shortcut_guide.md | 2 +- doc/devdocs/readme.md | 13 +- doc/thirdPartyRunPlugins.md | 1 + installer/PowerToysSetup.sln | 96 - installer/PowerToysSetup.slnx | 22 + .../UITestAutomation/SettingsConfigHelper.cs | 2 +- src/common/utils/registry.h | 146 +- .../SettingsResourceModuleTest`1.cs | 2 +- .../FunctionData/SettingsFunctionData`1.cs | 2 +- .../HexColorToColorConverterTests.cs | 56 + .../HelpersTests/ClipboardItemHelperTests.cs | 36 + .../ClipboardHistoryItemPreviewControl.xaml | 21 + ...ClipboardHistoryItemPreviewControl.xaml.cs | 6 +- .../Converters/HexColorConverterHelper.cs | 39 + .../Converters/HexColorToBrushConverter.cs | 28 + .../Helpers/ClipboardItemHelper.cs | 34 +- .../Hosts/Hosts/Settings/UserSettings.cs | 2 +- .../PowerToys.MeasureToolCore.vcxproj | 68 +- .../MeasureToolCore/packages.config | 17 - .../MeasureToolUI/MeasureToolUI.csproj | 9 +- .../MeasureTool/MeasureToolUI/Settings.cs | 2 +- .../FindMyMouse/FindMyMouse.vcxproj | 82 +- .../MouseUtils/FindMyMouse/packages.config | 12 - .../MouseJumpUI/Helpers/SettingsHelper.cs | 2 +- .../App/Class/Common.Encryption.cs | 248 -- .../App/Class/Common.Package.cs | 262 -- .../App/Class/Common.ShutdownWithPowerToys.cs | 33 - .../App/Class/Common.VK.cs | 131 - .../App/Class/Common.WinAPI.cs | 363 -- .../MouseWithoutBorders/App/Class/Common.cs | 28 +- .../App/Class/InputHook.cs | 12 +- .../App/Class/InputSimulation.cs | 30 +- .../MouseWithoutBorders/App/Class/Program.cs | 10 +- .../MouseWithoutBorders/App/Class/Setting.cs | 10 +- .../App/Class/SocketStuff.cs | 66 +- .../App/Class/TcpServer.cs | 2 +- .../MouseWithoutBorders/App/Core/Clipboard.cs | 20 +- .../App/Core/ClipboardPostAction.cs | 25 + .../MouseWithoutBorders/App/Core/DATA.cs | 150 + .../MouseWithoutBorders/App/Core/DragDrop.cs | 10 +- .../App/Core/Encryption.cs | 245 ++ .../MouseWithoutBorders/App/Core/Event.cs | 6 +- .../MouseWithoutBorders/App/Core/Helper.cs | 6 +- .../MouseWithoutBorders/App/Core/ID.cs | 19 + .../App/Core/InitAndCleanup.cs | 26 +- .../MouseWithoutBorders/App/Core/KEYBDDATA.cs | 25 + .../MouseWithoutBorders/App/Core/Logger.cs | 70 +- .../MouseWithoutBorders/App/Core/MOUSEDATA.cs | 26 + .../App/Core/MachineStuff.cs | 10 +- .../MouseWithoutBorders/App/Core/Package.cs | 23 + .../App/Core/PackageMonitor.cs | 38 + .../App/Core/PackageType.cs | 57 + .../MouseWithoutBorders/App/Core/Receiver.cs | 60 +- .../App/Core/ShutdownWithPowerToys.cs | 29 + .../MouseWithoutBorders/App/Core/VK.cs | 88 + .../MouseWithoutBorders/App/Core/WM.cs | 55 + .../MouseWithoutBorders/App/Core/WinAPI.cs | 359 ++ .../App/Form/Settings/SettingsFormPage.cs | 2 +- .../App/Form/Settings/SetupPage2a.cs | 4 +- .../MouseWithoutBorders/App/Form/frmMatrix.cs | 18 +- .../MouseWithoutBorders/App/Form/frmScreen.cs | 22 +- .../Core/Logger.PrivateDump.expected.txt | 226 +- .../PowerOCR/Settings/UserSettings.cs | 2 +- .../WorkspacesEditor/Utils/Settings.cs | 2 +- .../ViewModels/MainViewModel.cs | 2 +- src/modules/awake/Awake/Core/Manager.cs | 2 +- src/modules/awake/Awake/Program.cs | 2 +- .../Messages/DismissMessage.cs | 4 +- .../Messages/NavigateBackMessage.cs | 4 +- .../Messages/NavigateLeftCommand.cs | 10 + .../Messages/NavigateRightCommand.cs | 10 + .../ShellViewModel.cs | 4 +- src/modules/cmdpal/CoreCommonProps.props | 6 +- .../Commands/MainListPage.cs | 50 +- .../Commands/MainListPageResultFactory.cs | 156 + .../SettingsModel.cs | 10 + .../SettingsViewModel.cs | 10 + .../cmdpal/Microsoft.CmdPal.UI/App.xaml.cs | 5 +- .../Microsoft.CmdPal.UI/CmdPal.Branding.props | 14 +- .../Microsoft.CmdPal.UI/CmdPal.pre.props | 2 +- .../Controls/CommandBar.xaml | 4 +- .../Controls/SearchBar.xaml.cs | 82 +- .../ExtViews/ListPage.xaml.cs | 206 +- .../Microsoft.CmdPal.UI/MainWindow.xaml.cs | 5 + .../Microsoft.CmdPal.UI.csproj | 27 +- .../Pages/ShellPage.xaml.cs | 2 +- .../Settings/GeneralPage.xaml | 9 + .../Settings/SettingsWindow.xaml | 11 +- .../Settings/SettingsWindow.xaml.cs | 120 +- .../Strings/en-us/Resources.resw | 81 +- .../FontIconGlyphClassifier.cpp | 6 +- .../Microsoft.Terminal.UI.vcxproj | 72 +- .../Microsoft.Terminal.UI/packages.config | 17 - .../AllAppsCommandProviderTests.cs | 6 +- .../MainListPageResultFactoryTests.cs | 161 + .../AllAppsCommandProvider.cs | 68 +- .../ext/Microsoft.CmdPal.Ext.Apps/AppItem.cs | 4 + .../Microsoft.CmdPal.Ext.Apps/AppListItem.cs | 8 + .../Helpers/UninstallRegistryAppLocator.cs | 205 + .../Programs/UWPApplication.cs | 1 + .../Programs/Win32Program.cs | 1 + .../Properties/Resources.Designer.cs | 5 +- .../Properties/Resources.resx | 3 +- .../Pages/InstallPackageCommand.cs | 2 +- .../Pages/InstallPackageListItem.cs | 97 +- .../WinGetExtensionCommandsProvider.cs | 6 +- .../WinGetStatics.cs | 4 +- .../FuzzyStringMatcher.cs | 41 + ...t.CommandPalette.Extensions.Toolkit.csproj | 1 + .../extensionsdk/nuget/BuildSDKHelper.ps1 | 2 +- .../ColorPickerUI/Settings/UserSettings.cs | 2 +- .../FancyZonesCLI/Commands/EditorCommands.cs | 90 + .../FancyZonesCLI/Commands/HotkeyCommands.cs | 98 + .../FancyZonesCLI/Commands/LayoutCommands.cs | 276 ++ .../FancyZonesCLI/Commands/MonitorCommands.cs | 49 + .../FancyZonesCLI/FancyZonesCLI.csproj | 32 + .../FancyZonesCLI/FancyZonesData.cs | 142 + .../FancyZonesCLI/FancyZonesPaths.cs | 30 + .../FancyZonesCLI/LayoutVisualizer.cs | 550 +++ .../fancyzones/FancyZonesCLI/Logger.cs | 126 + .../fancyzones/FancyZonesCLI/Models.cs | 137 + .../fancyzones/FancyZonesCLI/NativeMethods.cs | 56 + .../FancyZonesCLI/NativeMethods.json | 5 + .../FancyZonesCLI/NativeMethods.txt | 4 + .../fancyzones/FancyZonesCLI/Program.cs | 115 + .../tests/Models/ResizeOperationTests.cs | 87 + .../imageresizer/ui/Models/ResizeOperation.cs | 78 +- .../Components/UtilityProvider.cs | 4 +- .../launcher/PowerLauncher/SettingsReader.cs | 2 +- .../Models/PreviewSettings.cs | 2 +- .../peek/Peek.UI/Services/UserSettings.cs | 2 +- .../poweraccent/PowerAccent.Core/Languages.cs | 43 +- .../PowerAccent.Core/PowerAccent.cs | 28 +- .../Services/SettingsService.cs | 2 +- .../PowerAccent.Core/Tools/Calculation.cs | 10 +- .../Tools/CharactersUsageInfo.cs | 2 +- .../PowerAccent.UI/Selector.xaml.cs | 7 + .../PowerRenameUILib/PowerRenameUI.vcxproj | 82 +- .../MonacoPreviewHandler/Settings.cs | 2 +- .../StlThumbnailProvider.cs | 2 +- .../previewpane/SvgPreviewHandler/Settings.cs | 2 +- src/runner/packages.config | 16 - src/runner/runner.base.rc | Bin 2972 -> 3122 bytes src/runner/runner.vcxproj | 74 +- .../AdvancedPasteCustomActions.cs | 2 +- .../AdvancedPasteProperties.cs | 2 +- .../BasePTModuleSettings.cs | 45 +- .../Settings.UI.Library/BoolProperty.cs | 2 +- .../BoolPropertyJsonConverter.cs | 4 +- .../Settings.UI.Library/CmdPalProperties.cs | 2 +- .../ColorPickerProperties.cs | 2 +- .../ColorPickerPropertiesVersion1.cs | 2 +- .../Settings.UI.Library/DoubleProperty.cs | 2 +- .../FileLocksmithLocalProperties.cs | 2 +- .../FileLocksmithProperties.cs | 2 +- .../Settings.UI.Library/GeneralSettings.cs | 2 +- .../GeneralSettingsCustomAction.cs | 2 +- .../Settings.UI.Library/Helpers/SunTimes.cs | 19 +- .../ImageResizerProperties.cs | 2 +- .../ImageResizerSettings.cs | 3 +- .../Settings.UI.Library/IntProperty.cs | 2 +- .../KeyboardManagerProfile.cs | 2 +- .../MeasureToolProperties.cs | 2 +- .../MouseWithoutBordersProperties.cs | 5 +- .../Settings.UI.Library/NewPlusProperties.cs | 2 +- .../OutGoingGeneralSettings.cs | 2 +- .../OutGoingLanguageSettings.cs | 2 +- .../PasteAIConfiguration.cs | 2 +- .../PeekPreviewSettings.cs | 2 +- .../Settings.UI.Library/PeekProperties.cs | 2 +- .../Settings.UI.Library/PowerOcrProperties.cs | 2 +- .../PowerPreviewProperties.cs | 2 +- .../PowerRenameLocalProperties.cs | 2 +- .../SettingsBackupAndRestoreUtils.cs | 2 +- .../SettingsSerializationContext.cs | 172 + .../Settings.UI.Library/SettingsUtils.cs | 65 +- .../Settings.UI.Library/StringProperty.cs | 2 +- .../Utilities/GetSettingCommandLineCommand.cs | 2 +- .../BasePTModuleSettingsSerializationTests.cs | 127 + .../ModelsTests/BasePTSettingsTest.cs | 8 + .../ModelsTests/SettingsUtilsTests.cs | 17 +- .../TestSettingsSerializationContext.cs | 22 + .../ViewModelTests/ColorPicker.cs | 2 +- .../ViewModelTests/FancyZones.cs | 68 +- .../ViewModelTests/ShortcutGuide.cs | 3 +- .../Helpers/HotkeyConflictIgnoreHelper.cs | 2 +- .../SourceGenerationContextContext.cs | 4 +- .../Settings.UI/SettingsXAML/App.xaml.cs | 6 +- .../SettingsXAML/Controls/Dashboard/Card.xaml | 1 + .../Dashboard/ShortcutConflictWindow.xaml.cs | 2 +- .../SettingsXAML/Flyout/AppsListPage.xaml.cs | 2 +- .../SettingsXAML/Flyout/LaunchPage.xaml.cs | 6 +- .../SettingsXAML/MainWindow.xaml.cs | 2 +- .../OOBE/Views/OobeAdvancedPaste.xaml.cs | 8 +- .../OOBE/Views/OobeAlwaysOnTop.xaml.cs | 2 +- .../OOBE/Views/OobeColorPicker.xaml.cs | 2 +- .../OOBE/Views/OobeCropAndLock.xaml.cs | 4 +- .../Views/OobeEnvironmentVariables.xaml.cs | 2 +- .../OOBE/Views/OobeFancyZones.xaml.cs | 2 +- .../SettingsXAML/OOBE/Views/OobeHosts.xaml.cs | 2 +- .../OOBE/Views/OobeMeasureTool.xaml.cs | 2 +- .../OOBE/Views/OobeOverviewAlternate.xaml.cs | 8 +- .../SettingsXAML/OOBE/Views/OobePeek.xaml.cs | 2 +- .../OOBE/Views/OobePowerOCR.xaml.cs | 2 +- .../SettingsXAML/OOBE/Views/OobeRun.xaml.cs | 2 +- .../OOBE/Views/OobeShellPage.xaml.cs | 2 +- .../OOBE/Views/OobeShortcutGuide.xaml.cs | 2 +- .../OOBE/Views/OobeWorkspaces.xaml.cs | 2 +- .../Views/AdvancedPastePage.xaml.cs | 2 +- .../Views/AlwaysOnTopPage.xaml.cs | 2 +- .../SettingsXAML/Views/AwakePage.xaml.cs | 2 +- .../SettingsXAML/Views/CmdPalPage.xaml.cs | 2 +- .../Views/ColorPickerPage.xaml.cs | 2 +- .../Views/CropAndLockPage.xaml.cs | 2 +- .../SettingsXAML/Views/DashboardPage.xaml | 1 + .../SettingsXAML/Views/DashboardPage.xaml.cs | 2 +- .../Views/EnvironmentVariablesPage.xaml.cs | 2 +- .../SettingsXAML/Views/FancyZonesPage.xaml.cs | 2 +- .../Views/FileLocksmithPage.xaml.cs | 2 +- .../SettingsXAML/Views/GeneralPage.xaml.cs | 2 +- .../SettingsXAML/Views/HostsPage.xaml.cs | 2 +- .../Views/ImageResizerPage.xaml.cs | 2 +- .../Views/KeyboardManagerPage.xaml.cs | 2 +- .../Views/LightSwitchPage.xaml.cs | 2 +- .../Views/MeasureToolPage.xaml.cs | 2 +- .../SettingsXAML/Views/MouseUtilsPage.xaml.cs | 4 +- .../Views/MouseWithoutBordersPage.xaml.cs | 2 +- .../SettingsXAML/Views/NewPlusPage.xaml.cs | 2 +- .../SettingsXAML/Views/PeekPage.xaml.cs | 2 +- .../Views/PowerAccentPage.xaml.cs | 2 +- .../Views/PowerLauncherPage.xaml.cs | 2 +- .../SettingsXAML/Views/PowerOcrPage.xaml.cs | 2 +- .../Views/PowerPreviewPage.xaml.cs | 2 +- .../Views/PowerRenamePage.xaml.cs | 2 +- .../Views/RegistryPreviewPage.xaml.cs | 2 +- .../SettingsXAML/Views/ShellPage.xaml.cs | 2 +- .../Views/ShortcutGuidePage.xaml.cs | 2 +- .../SettingsXAML/Views/WorkspacesPage.xaml.cs | 2 +- .../SettingsXAML/Views/ZoomItPage.xaml.cs | 2 +- .../Settings.UI/Strings/en-us/Resources.resw | 20 +- .../ViewModels/DashboardViewModel.cs | 40 +- .../ViewModels/Flyout/LauncherViewModel.cs | 14 +- .../ViewModels/GeneralViewModel.cs | 2 +- .../ViewModels/KeyboardManagerViewModel.cs | 2 +- tools/build/BUILD-GUIDELINES.md | 2 +- tools/build/build-common.ps1 | 2 +- tools/build/build-essentials.ps1 | 10 +- tools/build/build-installer.ps1 | 16 +- tools/project_template/README.md | 4 +- 276 files changed, 7066 insertions(+), 5884 deletions(-) delete mode 100644 PowerToys.sln create mode 100644 PowerToys.slnx create mode 100644 doc/devdocs/commands.md rename doc/devdocs/{ => development}/style.md (100%) delete mode 100644 doc/devdocs/localization.md delete mode 100644 installer/PowerToysSetup.sln create mode 100644 installer/PowerToysSetup.slnx create mode 100644 src/modules/AdvancedPaste/AdvancedPaste.UnitTests/ConvertersTests/HexColorToColorConverterTests.cs create mode 100644 src/modules/AdvancedPaste/AdvancedPaste.UnitTests/HelpersTests/ClipboardItemHelperTests.cs create mode 100644 src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Converters/HexColorConverterHelper.cs create mode 100644 src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Converters/HexColorToBrushConverter.cs delete mode 100644 src/modules/MeasureTool/MeasureToolCore/packages.config delete mode 100644 src/modules/MouseUtils/FindMyMouse/packages.config delete mode 100644 src/modules/MouseWithoutBorders/App/Class/Common.Encryption.cs delete mode 100644 src/modules/MouseWithoutBorders/App/Class/Common.Package.cs delete mode 100644 src/modules/MouseWithoutBorders/App/Class/Common.ShutdownWithPowerToys.cs delete mode 100644 src/modules/MouseWithoutBorders/App/Class/Common.VK.cs delete mode 100644 src/modules/MouseWithoutBorders/App/Class/Common.WinAPI.cs create mode 100644 src/modules/MouseWithoutBorders/App/Core/ClipboardPostAction.cs create mode 100644 src/modules/MouseWithoutBorders/App/Core/DATA.cs create mode 100644 src/modules/MouseWithoutBorders/App/Core/Encryption.cs create mode 100644 src/modules/MouseWithoutBorders/App/Core/ID.cs create mode 100644 src/modules/MouseWithoutBorders/App/Core/KEYBDDATA.cs create mode 100644 src/modules/MouseWithoutBorders/App/Core/MOUSEDATA.cs create mode 100644 src/modules/MouseWithoutBorders/App/Core/Package.cs create mode 100644 src/modules/MouseWithoutBorders/App/Core/PackageMonitor.cs create mode 100644 src/modules/MouseWithoutBorders/App/Core/PackageType.cs create mode 100644 src/modules/MouseWithoutBorders/App/Core/ShutdownWithPowerToys.cs create mode 100644 src/modules/MouseWithoutBorders/App/Core/VK.cs create mode 100644 src/modules/MouseWithoutBorders/App/Core/WM.cs create mode 100644 src/modules/MouseWithoutBorders/App/Core/WinAPI.cs create mode 100644 src/modules/cmdpal/Core/Microsoft.CmdPal.Core.ViewModels/Messages/NavigateLeftCommand.cs create mode 100644 src/modules/cmdpal/Core/Microsoft.CmdPal.Core.ViewModels/Messages/NavigateRightCommand.cs create mode 100644 src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/MainListPageResultFactory.cs delete mode 100644 src/modules/cmdpal/Microsoft.Terminal.UI/packages.config create mode 100644 src/modules/cmdpal/Tests/Microsoft.CmdPal.UI.ViewModels.UnitTests/MainListPageResultFactoryTests.cs create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Helpers/UninstallRegistryAppLocator.cs create mode 100644 src/modules/fancyzones/FancyZonesCLI/Commands/EditorCommands.cs create mode 100644 src/modules/fancyzones/FancyZonesCLI/Commands/HotkeyCommands.cs create mode 100644 src/modules/fancyzones/FancyZonesCLI/Commands/LayoutCommands.cs create mode 100644 src/modules/fancyzones/FancyZonesCLI/Commands/MonitorCommands.cs create mode 100644 src/modules/fancyzones/FancyZonesCLI/FancyZonesCLI.csproj create mode 100644 src/modules/fancyzones/FancyZonesCLI/FancyZonesData.cs create mode 100644 src/modules/fancyzones/FancyZonesCLI/FancyZonesPaths.cs create mode 100644 src/modules/fancyzones/FancyZonesCLI/LayoutVisualizer.cs create mode 100644 src/modules/fancyzones/FancyZonesCLI/Logger.cs create mode 100644 src/modules/fancyzones/FancyZonesCLI/Models.cs create mode 100644 src/modules/fancyzones/FancyZonesCLI/NativeMethods.cs create mode 100644 src/modules/fancyzones/FancyZonesCLI/NativeMethods.json create mode 100644 src/modules/fancyzones/FancyZonesCLI/NativeMethods.txt create mode 100644 src/modules/fancyzones/FancyZonesCLI/Program.cs delete mode 100644 src/runner/packages.config create mode 100644 src/settings-ui/Settings.UI.Library/SettingsSerializationContext.cs create mode 100644 src/settings-ui/Settings.UI.UnitTests/ModelsTests/BasePTModuleSettingsSerializationTests.cs create mode 100644 src/settings-ui/Settings.UI.UnitTests/TestSettingsSerializationContext.cs diff --git a/.github/actions/spell-check/allow/code.txt b/.github/actions/spell-check/allow/code.txt index 41a53d33ed..c655bb1b55 100644 --- a/.github/actions/spell-check/allow/code.txt +++ b/.github/actions/spell-check/allow/code.txt @@ -95,6 +95,7 @@ OTP Yubi Yubico Perplexity +Groq svgl # KEYS @@ -328,3 +329,9 @@ FFF HHH riday YYY + +# GitHub issue/PR commands +azp +feedbackhub +needinfo +reportbug diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index f080d44d6a..672616c8e7 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -221,6 +221,7 @@ clientside CLIPBOARDUPDATE CLIPCHILDREN CLIPSIBLINGS +CLITo closesocket clp CLSCTX @@ -728,9 +729,9 @@ HWNDPARENT HWNDPREV hyjiacan IAI -icf ICONERROR ICONLOCATION +icf IDCANCEL IDD idk @@ -773,6 +774,7 @@ INITGUID INITTOLOGFONTSTRUCT INLINEPREFIX inlines +Inno INPC inproc INPUTHARDWARE @@ -1072,6 +1074,7 @@ MVVMTK MWBEx MYICON NAMECHANGE +Notavailable namespaceanddescendants nao NCACTIVATE @@ -1480,6 +1483,7 @@ rgh rgn rgs rguid +rhk RIDEV RIGHTSCROLLBAR riid @@ -1585,6 +1589,7 @@ SHGDNF SHGFI SHIL shinfo +shk shlwapi shobjidl SHORTCUTATLEAST @@ -1629,6 +1634,7 @@ SKIPOWNPROCESS sku SLGP sln +slnx SMALLICON smartphone smileys @@ -1794,6 +1800,7 @@ tlbimp tlc tmain TNP +toolgood Toolhelp toolwindow TOPDOWNDIB @@ -1847,6 +1854,7 @@ UNCPRIORITY UNDNAME UNICODETEXT unins +Uninstaller uninstalls Uniquifies unitconverter diff --git a/.pipelines/ESRPSigning_core.json b/.pipelines/ESRPSigning_core.json index 83289fa102..f4e3e1ba38 100644 --- a/.pipelines/ESRPSigning_core.json +++ b/.pipelines/ESRPSigning_core.json @@ -60,6 +60,8 @@ "PowerToys.FancyZonesEditorCommon.dll", "PowerToys.FancyZonesModuleInterface.dll", "PowerToys.FancyZones.exe", + "FancyZonesCLI.exe", + "FancyZonesCLI.dll", "PowerToys.GcodePreviewHandler.dll", "PowerToys.GcodePreviewHandler.exe", diff --git a/.pipelines/packages.config b/.pipelines/packages.config index c4bca409f9..1e9b92d3b7 100644 --- a/.pipelines/packages.config +++ b/.pipelines/packages.config @@ -1,4 +1,4 @@ - + diff --git a/.pipelines/v2/templates/job-build-project.yml b/.pipelines/v2/templates/job-build-project.yml index 62cb993d5d..4ce0c0e7c0 100644 --- a/.pipelines/v2/templates/job-build-project.yml +++ b/.pipelines/v2/templates/job-build-project.yml @@ -192,14 +192,14 @@ jobs: displayName: Verify XAML formatting - pwsh: |- - & '.pipelines/verifyNugetPackages.ps1' -solution '$(build.sourcesdirectory)\PowerToys.sln' - displayName: Verify Nuget package versions for PowerToys.sln + & '.pipelines/verifyNugetPackages.ps1' -solution '$(build.sourcesdirectory)\PowerToys.slnx' + displayName: Verify Nuget package versions for PowerToys.slnx - pwsh: |- - & '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\PowerToys.sln' + & '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\PowerToys.slnx' & '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\tools\BugReportTool\BugReportTool.sln' & '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\tools\StylesReportTool\StylesReportTool.sln' - & '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\installer\PowerToysSetup.sln' + & '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\installer\PowerToysSetup.slnx' displayName: Verify ARM64 configurations - ${{ if eq(parameters.enablePackageCaching, true) }}: @@ -252,7 +252,7 @@ jobs: ${{ else }}: displayName: Build PowerToys main project inputs: - solution: 'PowerToys.sln' + solution: 'PowerToys.slnx' vsVersion: 17.0 msbuildArgs: >- -restore -graph @@ -275,7 +275,7 @@ jobs: displayName: Generate DSC artifacts for ARM64 condition: and(succeeded(), eq(variables['BuildPlatform'], 'arm64')) inputs: - solution: PowerToys.sln + solution: PowerToys.slnx vsVersion: 17.0 msbuildArgs: >- -restore diff --git a/.pipelines/v2/templates/job-build-ui-tests.yml b/.pipelines/v2/templates/job-build-ui-tests.yml index b9fad16d44..342750d51c 100644 --- a/.pipelines/v2/templates/job-build-ui-tests.yml +++ b/.pipelines/v2/templates/job-build-ui-tests.yml @@ -74,7 +74,7 @@ jobs: command: restore feedsToUse: config configPath: nuget.config - restoreSolution: PowerToys.sln + restoreSolution: PowerToys.slnx restoreDirectory: '$(Build.SourcesDirectory)\packages' # Build all UI test projects if no specific modules are specified @@ -129,4 +129,4 @@ jobs: - publish: $(JobOutputDirectory) artifact: $(JobOutputArtifactName) displayName: Publish UI Test artifacts - condition: always() \ No newline at end of file + condition: always() diff --git a/.pipelines/v2/templates/steps-build-installer-vnext.yml b/.pipelines/v2/templates/steps-build-installer-vnext.yml index 71a698b219..bf467ed5d9 100644 --- a/.pipelines/v2/templates/steps-build-installer-vnext.yml +++ b/.pipelines/v2/templates/steps-build-installer-vnext.yml @@ -35,7 +35,7 @@ steps: - task: VSBuild@1 displayName: Build Shared Support DLLs inputs: - solution: "**/installer/PowerToysSetup.sln" + solution: "**/installer/PowerToysSetup.slnx" vsVersion: 17.0 msbuildArgs: >- /t:PowerToysSetupCustomActionsVNext;SilentFilesInUseBAFunction @@ -74,7 +74,7 @@ steps: - task: VSBuild@1 displayName: 💻 Build VNext MSI inputs: - solution: "**/installer/PowerToysSetup.sln" + solution: "**/installer/PowerToysSetup.slnx" vsVersion: 17.0 msbuildArgs: >- -restore @@ -91,7 +91,7 @@ steps: - task: VSBuild@1 displayName: 👤 Build VNext MSI inputs: - solution: "**/installer/PowerToysSetup.sln" + solution: "**/installer/PowerToysSetup.slnx" vsVersion: 17.0 msbuildArgs: >- /t:PowerToysInstallerVNext @@ -142,7 +142,7 @@ steps: - task: VSBuild@1 displayName: 💻 Build VNext Bootstrapper inputs: - solution: "**/installer/PowerToysSetup.sln" + solution: "**/installer/PowerToysSetup.slnx" vsVersion: 17.0 msbuildArgs: >- -restore @@ -159,7 +159,7 @@ steps: - task: VSBuild@1 displayName: 👤 Build VNext Bootstrapper inputs: - solution: "**/installer/PowerToysSetup.sln" + solution: "**/installer/PowerToysSetup.slnx" vsVersion: 17.0 msbuildArgs: >- /t:PowerToysBootstrapperVNext diff --git a/.pipelines/v2/templates/steps-update-winappsdk-and-restore-nuget.yml b/.pipelines/v2/templates/steps-update-winappsdk-and-restore-nuget.yml index 9c59312844..cdb28b572c 100644 --- a/.pipelines/v2/templates/steps-update-winappsdk-and-restore-nuget.yml +++ b/.pipelines/v2/templates/steps-update-winappsdk-and-restore-nuget.yml @@ -54,4 +54,13 @@ steps: feedsToUse: 'config' nugetConfigPath: '$(build.sourcesdirectory)\nuget.config' restoreSolution: '$(build.sourcesdirectory)\**\*.sln' - includeNuGetOrg: false \ No newline at end of file + includeNuGetOrg: false + +- task: NuGetCommand@2 + displayName: 'Restore NuGet packages (slnx)' + inputs: + command: 'restore' + feedsToUse: 'config' + nugetConfigPath: '$(build.sourcesdirectory)\nuget.config' + restoreSolution: '$(build.sourcesdirectory)\**\*.slnx' + includeNuGetOrg: false diff --git a/Cpp.Build.props b/Cpp.Build.props index f146a4d770..7b988f0d6f 100644 --- a/Cpp.Build.props +++ b/Cpp.Build.props @@ -42,6 +42,11 @@ + + true + TurnOffAllWarnings + true + true Use pch.h @@ -111,13 +116,11 @@ - + true true - + false true false diff --git a/DATA_AND_PRIVACY.md b/DATA_AND_PRIVACY.md index 0ad4bda9c9..8aba94f12f 100644 --- a/DATA_AND_PRIVACY.md +++ b/DATA_AND_PRIVACY.md @@ -243,6 +243,10 @@ _If you want to find diagnostic data events in the source code, these two links Event Name Description + + Microsoft.PowerToys.CmdNotFound_EnableCmdNotFound + Triggered when Command Not Found is enabled or disabled. + Microsoft.PowerToys.CmdNotFoundInstallEvent Triggered when a Command Not Found is installed. @@ -257,6 +261,62 @@ _If you want to find diagnostic data events in the source code, these two links +### Command Palette + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Event NameDescription
Microsoft.PowerToys.CmdPal_BeginInvokeTriggered when the Command Palette is launched by the user.
Microsoft.PowerToys.CmdPal_ColdLaunchOccurs when Command Palette starts for the first time (cold start).
Microsoft.PowerToys.CmdPal_OpenPageTriggered when a page is opened within the Command Palette, tracking navigation depth.
Microsoft.PowerToys.CmdPal_OpenUriOccurs when a URI is opened through the Command Palette, including whether it's a web URL.
Microsoft.PowerToys.CmdPal_ReactivateInstanceTriggered when an existing Command Palette instance is reactivated.
Microsoft.PowerToys.CmdPal_RunCommandLogs when a command is executed through the Command Palette, including admin elevation status.
Microsoft.PowerToys.CmdPal_RunQueryTriggered when a search query is performed, including result count and duration.
Microsoft.PowerToys.CmdPalDismissedOnEscOccurs when the Command Palette is dismissed by pressing the Escape key.
Microsoft.PowerToys.CmdPalDismissedOnLostFocusTriggered when the Command Palette is dismissed due to losing focus.
Microsoft.PowerToys.CmdPalHotkeySummonedLogs when the Command Palette is summoned via hotkey, distinguishing between global and context-specific hotkeys.
Microsoft.PowerToys.CmdPalInvokeResultRecords the result type of a Command Palette invocation.
Microsoft.PowerToys.CmdPalProcessStartedTriggered when the Command Palette process is started.
+ ### Crop And Lock @@ -735,6 +795,10 @@ _If you want to find diagnostic data events in the source code, these two links + + + + @@ -743,6 +807,10 @@ _If you want to find diagnostic data events in the source code, these two links + + + + @@ -928,12 +996,8 @@ _If you want to find diagnostic data events in the source code, these two links - - - - - - + + diff --git a/Directory.Packages.props b/Directory.Packages.props index 6744b991aa..3d64052a21 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -7,6 +7,8 @@ + + @@ -69,10 +71,12 @@ This is present due to a bug in CsWinRT where WPF projects cause the analyzer to fail. --> + - - - + + + + @@ -111,6 +115,7 @@ + @@ -118,6 +123,7 @@ + diff --git a/NOTICE.md b/NOTICE.md index 6ca3cbfceb..23efb64864 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -75,6 +75,37 @@ OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to ``` +### ToolGood.Words.Pinyin + +We use the ToolGood.Words.Pinyin NuGet package for converting Chinese characters to pinyin. + +**Source**: [https://github.com/toolgood/ToolGood.Words.Pinyin](https://github.com/toolgood/ToolGood.Words.Pinyin) + +``` +MIT License + +Copyright (c) 2020 ToolGood + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +``` + + ## Utility: Command Palette Built-in Extensions ### Calculator @@ -1532,6 +1563,7 @@ SOFTWARE. - SkiaSharp.Views.WinUI - StreamJsonRpc - StyleCop.Analyzers +- ToolGood.Words.Pinyin - UnicodeInformation - UnitsNet - UTF.Unknown diff --git a/PowerToys.sln b/PowerToys.sln deleted file mode 100644 index 4e42cc9e30..0000000000 --- a/PowerToys.sln +++ /dev/null @@ -1,3396 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.32014.148 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "runner", "src\runner\runner.vcxproj", "{9412D5C6-2CF2-4FC2-A601-B55508EA9B27}" - ProjectSection(ProjectDependencies) = postProject - {031AC72E-FA28-4AB7-B690-6F7B9C28AA73} = {031AC72E-FA28-4AB7-B690-6F7B9C28AA73} - {08E71C67-6A7E-4CA1-B04E-2FB336410BAC} = {08E71C67-6A7E-4CA1-B04E-2FB336410BAC} - {0B43679E-EDFA-4DA0-AD30-F4628B308B1B} = {0B43679E-EDFA-4DA0-AD30-F4628B308B1B} - {0B593A6C-4143-4337-860E-DB5710FB87DB} = {0B593A6C-4143-4337-860E-DB5710FB87DB} - {17DA04DF-E393-4397-9CF0-84DABE11032E} = {17DA04DF-E393-4397-9CF0-84DABE11032E} - {217DF501-135C-4E38-BFC8-99D4821032EA} = {217DF501-135C-4E38-BFC8-99D4821032EA} - {2BE46397-4DFA-414C-9BD4-41E4BBF8CB34} = {2BE46397-4DFA-414C-9BD4-41E4BBF8CB34} - {38177D56-6AD1-4ADF-88C9-2843A7932166} = {38177D56-6AD1-4ADF-88C9-2843A7932166} - {48804216-2A0E-4168-A6D8-9CD068D14227} = {48804216-2A0E-4168-A6D8-9CD068D14227} - {51920F1F-C28C-4ADF-8660-4238766796C2} = {51920F1F-C28C-4ADF-8660-4238766796C2} - {5CCC8468-DEC8-4D36-99D4-5C891BEBD481} = {5CCC8468-DEC8-4D36-99D4-5C891BEBD481} - {5E7360A8-D048-4ED3-8F09-0BFD64C5529A} = {5E7360A8-D048-4ED3-8F09-0BFD64C5529A} - {655C9AF2-18D3-4DA6-80E4-85504A7722BA} = {655C9AF2-18D3-4DA6-80E4-85504A7722BA} - {69E1EE8D-143A-4060-9129-4658ACF14AAF} = {69E1EE8D-143A-4060-9129-4658ACF14AAF} - {6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB} = {6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB} - {89F34AF7-1C34-4A72-AA6E-534BCF972BD9} = {89F34AF7-1C34-4A72-AA6E-534BCF972BD9} - {AF2349B8-E5B6-4004-9502-687C1C7730B1} = {AF2349B8-E5B6-4004-9502-687C1C7730B1} - {B25AC7A5-FB9F-4789-B392-D5C85E948670} = {B25AC7A5-FB9F-4789-B392-D5C85E948670} - {BA58206B-1493-4C75-BFEA-A85768A1E156} = {BA58206B-1493-4C75-BFEA-A85768A1E156} - {D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D} = {D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D} - {D940E07F-532C-4FF3-883F-790DA014F19A} = {D940E07F-532C-4FF3-883F-790DA014F19A} - {DA425894-6E13-404F-8DCB-78584EC0557A} = {DA425894-6E13-404F-8DCB-78584EC0557A} - {E2A5A82E-1E5B-4C8D-9A4F-2B1A8F9E5C3D} = {E2A5A82E-1E5B-4C8D-9A4F-2B1A8F9E5C3D} - {E364F67B-BB12-4E91-B639-355866EBCD8B} = {E364F67B-BB12-4E91-B639-355866EBCD8B} - {F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99} = {F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99} - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{4574FDD0-F61D-4376-98BF-E5A1262C11EC}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "interface", "interface", "{3BB8493E-D18E-4485-A320-CB40F90F55AE}" - ProjectSection(SolutionItems) = preProject - src\modules\interface\powertoy_module_interface.h = src\modules\interface\powertoy_module_interface.h - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "fancyzones", "fancyzones", "{D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FancyZonesLib", "src\modules\fancyzones\FancyZonesLib\FancyZonesLib.vcxproj", "{F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FancyZones.UnitTests", "src\modules\fancyzones\FancyZonesTests\UnitTests\UnitTests.vcxproj", "{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}" - ProjectSection(ProjectDependencies) = postProject - {F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99} = {F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99} - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{1AFB6476-670D-4E80-A464-657E01DFF482}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Common.Lib.UnitTests", "src\common\UnitTests-CommonLib\UnitTests-CommonLib.vcxproj", "{1A066C63-64B3-45F8-92FE-664E1CCE8077}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PackageIdentity", "src\PackageIdentity\PackageIdentity.vcxproj", "{E2A5A82E-1E5B-4C8D-9A4F-2B1A8F9E5C3D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FancyZonesEditor", "src\modules\fancyzones\editor\FancyZonesEditor\FancyZonesEditor.csproj", "{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "powerrename", "powerrename", "{89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameExt", "src\modules\powerrename\dll\PowerRenameExt.vcxproj", "{B25AC7A5-FB9F-4789-B392-D5C85E948670}" - ProjectSection(ProjectDependencies) = postProject - {51920F1F-C28C-4ADF-8660-4238766796C2} = {51920F1F-C28C-4ADF-8660-4238766796C2} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameLib", "src\modules\powerrename\lib\PowerRenameLib.vcxproj", "{51920F1F-C28C-4ADF-8660-4238766796C2}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameTest", "src\modules\powerrename\testapp\PowerRenameTest.vcxproj", "{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRename.UnitTests", "src\modules\powerrename\unittests\PowerRenameLibUnitTests.vcxproj", "{2151F984-E006-4A9F-92EF-C6DDE3DC8413}" - ProjectSection(ProjectDependencies) = postProject - {51920F1F-C28C-4ADF-8660-4238766796C2} = {51920F1F-C28C-4ADF-8660-4238766796C2} - {B25AC7A5-FB9F-4789-B392-D5C85E948670} = {B25AC7A5-FB9F-4789-B392-D5C85E948670} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ModuleTemplateCompileTest", "tools\project_template\ModuleTemplate\ModuleTemplateCompileTest.vcxproj", "{64A80062-4D8B-4229-8A38-DFA1D7497749}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManager", "src\modules\keyboardmanager\dll\KeyboardManager.vcxproj", "{89F34AF7-1C34-4A72-AA6E-534BCF972BD9}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "imageresizer", "imageresizer", "{6C7F47CC-2151-44A3-A546-41C70025132C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageResizerUI", "src\modules\imageresizer\ui\ImageResizerUI.csproj", "{2BE46397-4DFA-414C-9BD4-41E4BBF8CB34}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImageResizerExt", "src\modules\imageresizer\dll\ImageResizerExt.vcxproj", "{0B43679E-EDFA-4DA0-AD30-F4628B308B1B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageResizer.UnitTests", "src\modules\imageresizer\tests\ImageResizer.UnitTests.csproj", "{E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerToys.ActionRunner", "src\ActionRunner\ActionRunner.vcxproj", "{D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D}" - ProjectSection(ProjectDependencies) = postProject - {17DA04DF-E393-4397-9CF0-84DABE11032E} = {17DA04DF-E393-4397-9CF0-84DABE11032E} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ApplicationUpdate", "src\common\updating\updating.vcxproj", "{17DA04DF-E393-4397-9CF0-84DABE11032E}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "keyboardmanager", "keyboardmanager", "{38BDB927-829B-4C65-9CD9-93FB05D66D65}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManagerCommon", "src\modules\keyboardmanager\common\KeyboardManagerCommon.vcxproj", "{8AFFA899-0B73-49EC-8C50-0FADDA57B2FC}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "launcher", "launcher", "{C140A3EF-6DBF-4084-9D4C-4EB5A99FEE68}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wox.Infrastructure", "src\modules\launcher\Wox.Infrastructure\Wox.Infrastructure.csproj", "{4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wox.Plugin", "src\modules\launcher\Wox.Plugin\Wox.Plugin.csproj", "{8451ECDD-2EA4-4966-BB0A-7BBC40138E80}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wox.Test", "src\modules\launcher\Wox.Test\Wox.Test.csproj", "{FF742965-9A80-41A5-B042-D6C7D3A21708}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{4AFC9975-2456-4C70-94A4-84073C1CED93}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.Calculator", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Calculator\Microsoft.PowerToys.Run.Plugin.Calculator.csproj", "{59BD9891-3837-438A-958D-ADC7F91F6F7E}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Community.PowerToys.Run.Plugin.VSCodeWorkspaces", "src\modules\launcher\Plugins\Community.PowerToys.Run.Plugin.VSCodeWorkspaces\Community.PowerToys.Run.Plugin.VSCodeWorkspaces.csproj", "{4D971245-7A70-41D5-BAA0-DDB5684CAF51}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Plugin.WindowWalker", "src\modules\launcher\Plugins\Microsoft.Plugin.WindowWalker\Microsoft.Plugin.WindowWalker.csproj", "{74F1B9ED-F59C-4FE7-B473-7B453E30837E}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Plugin.Program", "src\modules\launcher\Plugins\Microsoft.Plugin.Program\Microsoft.Plugin.Program.csproj", "{FDB3555B-58EF-4AE6-B5F1-904719637AB4}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Plugin.Shell", "src\modules\launcher\Plugins\Microsoft.Plugin.Shell\Microsoft.Plugin.Shell.csproj", "{C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Plugin.Indexer", "src\modules\launcher\Plugins\Microsoft.Plugin.Indexer\Microsoft.Plugin.Indexer.csproj", "{F8B870EB-D5F5-45BA-9CF7-A5C459818820}" - ProjectSection(ProjectDependencies) = postProject - {8451ECDD-2EA4-4966-BB0A-7BBC40138E80} = {8451ECDD-2EA4-4966-BB0A-7BBC40138E80} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Launcher", "src\modules\launcher\Microsoft.Launcher\Microsoft.Launcher.vcxproj", "{E364F67B-BB12-4E91-B639-355866EBCD8B}" - ProjectSection(ProjectDependencies) = postProject - {F97E5003-F263-4D4A-A964-0F1F3C82DEF2} = {F97E5003-F263-4D4A-A964-0F1F3C82DEF2} - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerLauncher", "src\modules\launcher\PowerLauncher\PowerLauncher.csproj", "{F97E5003-F263-4D4A-A964-0F1F3C82DEF2}" - ProjectSection(ProjectDependencies) = postProject - {03276A39-D4E9-417C-8FFD-200B0EE5E871} = {03276A39-D4E9-417C-8FFD-200B0EE5E871} - {0351ADA4-0C32-4652-9BA0-41F7B602372B} = {0351ADA4-0C32-4652-9BA0-41F7B602372B} - {4BABF3FE-3451-42FD-873F-3C332E18DCEF} = {4BABF3FE-3451-42FD-873F-3C332E18DCEF} - {4D971245-7A70-41D5-BAA0-DDB5684CAF51} = {4D971245-7A70-41D5-BAA0-DDB5684CAF51} - {500DED3E-CFB5-4ED5-ACC6-02B3D6DC336D} = {500DED3E-CFB5-4ED5-ACC6-02B3D6DC336D} - {5043CECE-E6A7-4867-9CBE-02D27D83747A} = {5043CECE-E6A7-4867-9CBE-02D27D83747A} - {59BD9891-3837-438A-958D-ADC7F91F6F7E} = {59BD9891-3837-438A-958D-ADC7F91F6F7E} - {5A1DB2F0-0715-4B3B-98E6-79BC41540045} = {5A1DB2F0-0715-4B3B-98E6-79BC41540045} - {5BDBD6C9-A31F-4CEB-871A-5E9E709197EF} = {5BDBD6C9-A31F-4CEB-871A-5E9E709197EF} - {74F1B9ED-F59C-4FE7-B473-7B453E30837E} = {74F1B9ED-F59C-4FE7-B473-7B453E30837E} - {787B8AA6-CA93-4C84-96FE-DF31110AD1C4} = {787B8AA6-CA93-4C84-96FE-DF31110AD1C4} - {9F94B303-5E21-4364-9362-64426F8DB932} = {9F94B303-5E21-4364-9362-64426F8DB932} - {A2D583F0-B70C-4462-B1F0-8E81AFB7BA85} = {A2D583F0-B70C-4462-B1F0-8E81AFB7BA85} - {BB23A474-5058-4F75-8FA3-5FE3DE53CDF4} = {BB23A474-5058-4F75-8FA3-5FE3DE53CDF4} - {C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0} = {C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0} - {D095BE44-1F2E-463E-A494-121892A75EA2} = {D095BE44-1F2E-463E-A494-121892A75EA2} - {F8B870EB-D5F5-45BA-9CF7-A5C459818820} = {F8B870EB-D5F5-45BA-9CF7-A5C459818820} - {FD8EB419-FF9C-4D88-BB6F-BF6CED37747B} = {FD8EB419-FF9C-4D88-BB6F-BF6CED37747B} - {FDB3555B-58EF-4AE6-B5F1-904719637AB4} = {FDB3555B-58EF-4AE6-B5F1-904719637AB4} - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "previewpane", "previewpane", "{2F305555-C296-497E-AC20-5FA1B237996A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PreviewHandlerCommon", "src\modules\previewpane\Common\PreviewHandlerCommon.csproj", "{AF2349B8-E5B6-4004-9502-687C1C7730B1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MarkdownPreviewHandler", "src\modules\previewpane\MarkdownPreviewHandler\MarkdownPreviewHandler.csproj", "{6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preview.MarkdownPreviewHandler.UnitTests", "src\modules\previewpane\UnitTests-MarkdownPreviewHandler\Preview.MarkdownPreviewHandler.UnitTests.csproj", "{A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SvgPreviewHandler", "src\modules\previewpane\SvgPreviewHandler\SvgPreviewHandler.csproj", "{DA425894-6E13-404F-8DCB-78584EC0557A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preview.SvgPreviewHandler.UnitTests", "src\modules\previewpane\UnitTests-SvgPreviewHandler\Preview.SvgPreviewHandler.UnitTests.csproj", "{060D75DA-2D1C-48E6-A4A1-6F0718B64661}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preview.PreviewHandlerCommon.UnitTests", "src\modules\previewpane\UnitTests-PreviewHandlerCommon\Preview.PreviewHandlerCommon.UnitTests.csproj", "{748417CA-F17E-487F-9411-CAFB6D3F4877}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "powerpreview", "src\modules\previewpane\powerpreview\powerpreview.vcxproj", "{217DF501-135C-4E38-BFC8-99D4821032EA}" - ProjectSection(ProjectDependencies) = postProject - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF} = {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF} - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "settings-ui", "settings-ui", "{C3081D9A-1586-441A-B5F4-ED815B3719C1}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4981CCD1-4CD9-4A49-B240-00AA46493FF8}" - ProjectSection(SolutionItems) = preProject - src\.editorconfig = src\.editorconfig - .vsconfig = .vsconfig - src\Common.Dotnet.AotCompatibility.props = src\Common.Dotnet.AotCompatibility.props - src\Common.Dotnet.CsWinRT.props = src\Common.Dotnet.CsWinRT.props - src\Common.SelfContained.props = src\Common.SelfContained.props - Cpp.Build.props = Cpp.Build.props - Directory.Build.props = Directory.Build.props - Directory.Build.targets = Directory.Build.targets - Directory.Packages.props = Directory.Packages.props - src\Monaco.props = src\Monaco.props - src\Solution.props = src\Solution.props - src\Version.props = src\Version.props - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Settings.UI.Library", "src\settings-ui\Settings.UI.Library\Settings.UI.Library.csproj", "{B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Plugin.Folder", "src\modules\launcher\Plugins\Microsoft.Plugin.Folder\Microsoft.Plugin.Folder.csproj", "{787B8AA6-CA93-4C84-96FE-DF31110AD1C4}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerLauncher.Telemetry", "src\modules\launcher\PowerLauncher.Telemetry\PowerLauncher.Telemetry.csproj", "{08C8C05F-0362-41BC-818C-724572DF8B06}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ManagedTelemetry", "src\common\ManagedTelemetry\Telemetry\ManagedTelemetry.csproj", "{5D00D290-4016-4CFE-9E41-1E7C724509BA}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ManagedCommon", "src\common\ManagedCommon\ManagedCommon.csproj", "{4AED67B6-55FD-486F-B917-E543DEE2CB3C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Plugin.Program.UnitTests", "src\modules\launcher\Plugins\Microsoft.Plugin.Program.UnitTests\Microsoft.Plugin.Program.UnitTests.csproj", "{42851751-CBC8-45A6-97F5-7A0753F7B4D1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preview.SvgThumbnailProvider.UnitTests", "src\modules\previewpane\UnitTests-SvgThumbnailProvider\Preview.SvgThumbnailProvider.UnitTests.csproj", "{1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SvgThumbnailProvider", "src\modules\previewpane\SvgThumbnailProvider\SvgThumbnailProvider.csproj", "{8FFE09DA-FA4F-4EE1-B3A2-AD5497FBD1AD}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ColorPicker", "src\modules\colorPicker\ColorPicker\ColorPicker.vcxproj", "{655C9AF2-18D3-4DA6-80E4-85504A7722BA}" - ProjectSection(ProjectDependencies) = postProject - {D9B8FC84-322A-4F9F-BBB9-20915C47DDFD} = {D9B8FC84-322A-4F9F-BBB9-20915C47DDFD} - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ColorPickerUI", "src\modules\colorPicker\ColorPickerUI\ColorPickerUI.csproj", "{BA58206B-1493-4C75-BFEA-A85768A1E156}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "colorpicker", "colorpicker", "{1D78B84B-CA39-406C-98F4-71F7EC266CC0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Plugin.Uri", "src\modules\launcher\Plugins\Microsoft.Plugin.Uri\Microsoft.Plugin.Uri.csproj", "{03276A39-D4E9-417C-8FFD-200B0EE5E871}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Plugin.Uri.UnitTests", "src\modules\launcher\Plugins\Microsoft.Plugin.Uri.UnitTests\Microsoft.Plugin.Uri.UnitTests.csproj", "{B81FB7B6-D30E-428F-908A-41422EFC1172}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Settings.UI.UnitTests", "src\settings-ui\Settings.UI.UnitTests\Settings.UI.UnitTests.csproj", "{0F85E674-34AE-443D-954C-8321EB8B93B1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.Calculator.UnitTest", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Calculator.UnitTest\Microsoft.PowerToys.Run.Plugin.Calculator.UnitTest.csproj", "{632BBE62-5421-49EA-835A-7FFA4F499BD6}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spdlog", "src\logging\logging.vcxproj", "{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.System", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.System\Microsoft.PowerToys.Run.Plugin.System.csproj", "{FD8EB419-FF9C-4D88-BB6F-BF6CED37747B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.System.UnitTests", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.System.UnitTests\Microsoft.PowerToys.Run.Plugin.System.UnitTests.csproj", "{DA5A6FE9-0040-40CC-83CC-764AE5306590}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.Service", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Service\Microsoft.PowerToys.Run.Plugin.Service.csproj", "{0351ADA4-0C32-4652-9BA0-41F7B602372B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "logger", "src\common\logger\logger.vcxproj", "{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}" - ProjectSection(ProjectDependencies) = postProject - {7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F} = {7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SettingsAPI", "src\common\SettingsAPI\SettingsAPI.vcxproj", "{6955446D-23F7-4023-9BB3-8657F904AF99}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Common.Interop.UnitTests", "src\common\interop\interop-tests\Common.Interop.UnitTests.csproj", "{58736667-1027-4AD7-BFDF-7A3A6474103A}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "notifications", "notifications", "{D92131D6-7610-4D60-A7DB-1C169783F83B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Notifications", "src\common\notifications\notifications.vcxproj", "{1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BackgroundActivatorDLL", "src\common\notifications\BackgroundActivatorDLL\BackgroundActivatorDLL.vcxproj", "{031AC72E-FA28-4AB7-B690-6F7B9C28AA73}" - ProjectSection(ProjectDependencies) = postProject - {0B593A6C-4143-4337-860E-DB5710FB87DB} = {0B593A6C-4143-4337-860E-DB5710FB87DB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BackgroundActivator", "src\common\notifications\BackgroundActivator\BackgroundActivator.vcxproj", "{0B593A6C-4143-4337-860E-DB5710FB87DB}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Version", "src\common\version\version.vcxproj", "{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "interop", "interop", "{5A7818A8-109C-4E1C-850D-1A654E234B0E}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "log", "log", "{E4E03FE0-94FD-47C7-88C5-F17D0AA549D3}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "COMUtils", "src\common\COMUtils\COMUtils.vcxproj", "{7319089E-46D6-4400-BC65-E39BDF1416EE}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Display", "src\common\Display\Display.vcxproj", "{CABA8DFB-823B-4BF2-93AC-3F31984150D9}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Themes", "src\common\Themes\Themes.vcxproj", "{98537082-0FDB-40DE-ABD8-0DC5A4269BAB}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "utils", "utils", "{B39DC643-4663-475E-B329-03F0C9918D48}" - ProjectSection(SolutionItems) = preProject - src\common\utils\appMutex.h = src\common\utils\appMutex.h - src\common\utils\color.h = src\common\utils\color.h - src\common\utils\com_object_factory.h = src\common\utils\com_object_factory.h - src\common\utils\elevation.h = src\common\utils\elevation.h - src\common\utils\EventLocker.h = src\common\utils\EventLocker.h - src\common\utils\EventWaiter.h = src\common\utils\EventWaiter.h - src\common\utils\excluded_apps.h = src\common\utils\excluded_apps.h - src\common\utils\exec.h = src\common\utils\exec.h - src\common\utils\game_mode.h = src\common\utils\game_mode.h - src\common\utils\gpo.h = src\common\utils\gpo.h - src\common\utils\HDropIterator.h = src\common\utils\HDropIterator.h - src\common\utils\HttpClient.h = src\common\utils\HttpClient.h - src\common\utils\json.h = src\common\utils\json.h - src\common\utils\language_helper.h = src\common\utils\language_helper.h - src\common\utils\logger_helper.h = src\common\utils\logger_helper.h - src\common\utils\modulesRegistry.h = src\common\utils\modulesRegistry.h - src\common\utils\MsiUtils.h = src\common\utils\MsiUtils.h - src\common\utils\MsWindowsSettings.h = src\common\utils\MsWindowsSettings.h - src\common\utils\OnThreadExecutor.h = src\common\utils\OnThreadExecutor.h - src\common\utils\os-detect.h = src\common\utils\os-detect.h - src\common\utils\package.h = src\common\utils\package.h - src\common\utils\ProcessWaiter.h = src\common\utils\ProcessWaiter.h - src\common\utils\process_path.h = src\common\utils\process_path.h - src\common\utils\registry.h = src\common\utils\registry.h - src\common\utils\resources.h = src\common\utils\resources.h - src\common\utils\serialized.h = src\common\utils\serialized.h - src\common\utils\shell_ext_registration.h = src\common\utils\shell_ext_registration.h - src\common\utils\string_utils.h = src\common\utils\string_utils.h - src\common\utils\timeutil.h = src\common\utils\timeutil.h - src\common\utils\UnhandledExceptionHandler.h = src\common\utils\UnhandledExceptionHandler.h - src\common\utils\winapi_error.h = src\common\utils\winapi_error.h - src\common\utils\window.h = src\common\utils\window.h - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Telemetry", "Telemetry", "{8F62026A-294B-41C6-8839-87463613F216}" - ProjectSection(SolutionItems) = preProject - src\common\Telemetry\ProjectTelemetry.h = src\common\Telemetry\ProjectTelemetry.h - src\common\Telemetry\TelemetryBase.cs = src\common\Telemetry\TelemetryBase.cs - src\common\Telemetry\TraceBase.h = src\common\Telemetry\TraceBase.h - src\common\Telemetry\TraceLoggingDefines.h = src\common\Telemetry\TraceLoggingDefines.h - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Common.UI", "src\common\Common.UI\Common.UI.csproj", "{C3A17DCA-217B-462C-BB0C-BE086AF80081}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PdfPreviewHandler", "src\modules\previewpane\PdfPreviewHandler\PdfPreviewHandler.csproj", "{69E1EE8D-143A-4060-9129-4658ACF14AAF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preview.PdfPreviewHandler.UnitTests", "src\modules\previewpane\UnitTests-PdfPreviewHandler\Preview.PdfPreviewHandler.UnitTests.csproj", "{ECC20689-002A-4354-95A6-B58DF089C6FF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.Registry", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Registry\Microsoft.PowerToys.Run.Plugin.Registry.csproj", "{4BABF3FE-3451-42FD-873F-3C332E18DCEF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.Registry.UnitTests", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Registry.UnitTest\Microsoft.PowerToys.Run.Plugin.Registry.UnitTests.csproj", "{0648DF05-5DDA-4BE1-B5F2-584926EBDB65}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManagerEngine", "src\modules\keyboardmanager\KeyboardManagerEngine\KeyboardManagerEngine.vcxproj", "{BA661F5B-1D5A-4FFC-9BF1-FC39DF280BDD}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManagerEngineLibrary", "src\modules\keyboardmanager\KeyboardManagerEngineLibrary\KeyboardManagerEngineLibrary.vcxproj", "{E496B7FC-1E99-4BAB-849B-0E8367040B02}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManager.Engine.UnitTests", "src\modules\keyboardmanager\KeyboardManagerEngineTest\KeyboardManagerEngineTest.vcxproj", "{7F4B3A60-BC27-45A7-8000-68B0B6EA7466}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManagerEditor", "src\modules\keyboardmanager\KeyboardManagerEditor\KeyboardManagerEditor.vcxproj", "{8DF78B53-200E-451F-9328-01EB907193AE}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManagerEditorLibrary", "src\modules\keyboardmanager\KeyboardManagerEditorLibrary\KeyboardManagerEditorLibrary.vcxproj", "{23D2070D-E4AD-4ADD-85A7-083D9C76AD49}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManager.Editor.UnitTests", "src\modules\keyboardmanager\KeyboardManagerEditorTest\KeyboardManagerEditorTest.vcxproj", "{62173D9A-6724-4C00-A1C8-FB646480A9EC}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "awake", "awake", "{127F38E0-40AA-4594-B955-5616BF206882}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AwakeModuleInterface", "src\modules\awake\AwakeModuleInterface\AwakeModuleInterface.vcxproj", "{5E7360A8-D048-4ED3-8F09-0BFD64C5529A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Awake", "src\modules\awake\Awake\Awake.csproj", "{D940E07F-532C-4FF3-883F-790DA014F19A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Community.PowerToys.Run.Plugin.UnitConverter", "src\modules\launcher\Plugins\Community.PowerToys.Run.Plugin.UnitConverter\Community.PowerToys.Run.Plugin.UnitConverter.csproj", "{BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Community.PowerToys.Run.Plugin.UnitConverter.UnitTest", "src\modules\launcher\Plugins\Community.PowerToys.Run.Plugin.UnitConverter.UnitTest\Community.PowerToys.Run.Plugin.UnitConverter.UnitTest.csproj", "{3E424AD2-19E5-4AE6-B833-F53963EB5FC1}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shortcutguide", "shortcutguide", "{106CBECA-0701-4FC3-838C-9DF816A19AE2}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShortcutGuideModuleInterface", "src\modules\ShortcutGuide\ShortcutGuideModuleInterface\ShortcutGuideModuleInterface.vcxproj", "{2D604C07-51FC-46BB-9EB7-75AECC7F5E81}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShortcutGuide", "src\modules\ShortcutGuide\ShortcutGuide\ShortcutGuide.vcxproj", "{2EDB3EB4-FA92-4BFF-B2D8-566584837231}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FancyZonesModuleInterface", "src\modules\fancyzones\FancyZonesModuleInterface\FancyZonesModuleInterface.vcxproj", "{48804216-2A0E-4168-A6D8-9CD068D14227}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FancyZones", "src\modules\fancyzones\FancyZones\FancyZones.vcxproj", "{FF1D7936-842A-4BBB-8BEA-E9FE796DE700}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerToys.Update", "src\Update\PowerToys.Update.vcxproj", "{44CE9AE1-4390-42C5-BACC-0FD6B40AA203}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.WindowsSettings", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsSettings\Microsoft.PowerToys.Run.Plugin.WindowsSettings.csproj", "{5043CECE-E6A7-4867-9CBE-02D27D83747A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PdfThumbnailProvider", "src\modules\previewpane\PdfThumbnailProvider\PdfThumbnailProvider.csproj", "{11491FD8-F921-48BF-880C-7FEA185B80A1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preview.PdfThumbnailProvider.UnitTests", "src\modules\previewpane\UnitTests-PdfThumbnailProvider\Preview.PdfThumbnailProvider.UnitTests.csproj", "{F40C3397-1834-4530-B2D9-8F8B8456BCDF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.WindowsTerminal", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsTerminal\Microsoft.PowerToys.Run.Plugin.WindowsTerminal.csproj", "{A2D583F0-B70C-4462-B1F0-8E81AFB7BA85}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Plugin.WindowsTerminal.UnitTests", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsTerminal.UnitTests\Microsoft.Plugin.WindowsTerminal.UnitTests.csproj", "{4ED320BC-BA04-4D42-8D15-CBE62151F08B}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MouseUtils", "MouseUtils", "{322566EF-20DC-43A6-B9F8-616AF942579A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FindMyMouse", "src\modules\MouseUtils\FindMyMouse\FindMyMouse.vcxproj", "{E94FD11C-0591-456F-899F-EFC0CA548336}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MouseHighlighter", "src\modules\MouseUtils\MouseHighlighter\MouseHighlighter.vcxproj", "{782A61BE-9D85-4081-B35C-1CCC9DCC1E88}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GcodeThumbnailProvider", "src\modules\previewpane\GcodeThumbnailProvider\GcodeThumbnailProvider.csproj", "{809AA252-E17A-4FA2-B0A1-0450976B763F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preview.GcodeThumbnailProvider.UnitTests", "src\modules\previewpane\UnitTests-GcodeThumbnailProvider\Preview.GcodeThumbnailProvider.UnitTests.csproj", "{133281D8-1BCE-4D07-B31E-796612A9609E}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GcodePreviewHandler", "src\modules\previewpane\GcodePreviewHandler\GcodePreviewHandler.csproj", "{805306FF-A562-4415-8DEF-E493BDC45918}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preview.GcodePreviewHandler.UnitTests", "src\modules\previewpane\UnitTests-GcodePreviewHandler\Preview.GcodePreviewHandler.UnitTests.csproj", "{FCF3E52D-B80A-4FC3-98FD-6391354F0EE3}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AlwaysOnTop", "AlwaysOnTop", "{60CD2D4F-C3B9-4897-9821-FCA5098B41CE}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AlwaysOnTop", "src\modules\alwaysontop\AlwaysOnTop\AlwaysOnTop.vcxproj", "{1DC3BE92-CE89-43FB-8110-9C043A2FE7A2}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AlwaysOnTopModuleInterface", "src\modules\alwaysontop\AlwaysOnTopModuleInterface\AlwaysOnTopModuleInterface.vcxproj", "{48A0A19E-A0BE-4256-ACF8-CC3B80291AF9}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Community.PowerToys.Run.Plugin.WebSearch", "src\modules\launcher\Plugins\Community.PowerToys.Run.Plugin.WebSearch\Community.PowerToys.Run.Plugin.WebSearch.csproj", "{9F94B303-5E21-4364-9362-64426F8DB932}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MousePointerCrosshairs", "src\modules\MouseUtils\MousePointerCrosshairs\MousePointerCrosshairs.vcxproj", "{EAE14C0E-7A6B-45DA-9080-A7D8C077BA6E}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StlThumbnailProvider", "src\modules\previewpane\StlThumbnailProvider\StlThumbnailProvider.csproj", "{F7C8C0F1-5431-4347-89D0-8E5354F93CF2}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preview.StlThumbnailProvider.UnitTests", "src\modules\previewpane\UnitTests-StlThumbnailProvider\Preview.StlThumbnailProvider.UnitTests.csproj", "{F1F6B6B6-9F18-4A17-8B5C-97DF552C53DC}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonacoPreviewHandler", "src\modules\previewpane\MonacoPreviewHandler\MonacoPreviewHandler.csproj", "{04B193D7-3E21-46B8-A958-89B63A8A69DE}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.TimeDate", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.TimeDate\Microsoft.PowerToys.Run.Plugin.TimeDate.csproj", "{5BDBD6C9-A31F-4CEB-871A-5E9E709197EF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests\Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests.csproj", "{FD464B4C-2F68-4D06-91E7-4208146C41F5}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Plugin.WindowWalker.UnitTests", "src\modules\launcher\Plugins\Microsoft.Plugin.WindowWalker.UnitTests\Microsoft.Plugin.WindowWalker.UnitTests.csproj", "{8FE5A5EE-1B59-401C-9FB3-B04ECD3E29C1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerToys.Settings", "src\settings-ui\Settings.UI\PowerToys.Settings.csproj", "{020A7474-3601-4160-A159-D7B70B77B15F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameUI", "src\modules\powerrename\PowerRenameUILib\PowerRenameUI.vcxproj", "{27718999-C175-450A-861C-89F911E16A88}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameContextMenu", "src\modules\powerrename\PowerRenameContextMenu\PowerRenameContextMenu.vcxproj", "{1DBBB112-4BB1-444B-8EBB-E66555C76BA6}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.OneNote", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.OneNote\Microsoft.PowerToys.Run.Plugin.OneNote.csproj", "{5A1DB2F0-0715-4B3B-98E6-79BC41540045}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImageResizerContextMenu", "src\modules\imageresizer\ImageResizerContextMenu\ImageResizerContextMenu.vcxproj", "{93B72A06-C8BD-484F-A6F7-C9F280B150BF}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImageResizerLib", "src\modules\imageresizer\ImageResizerLib\ImageResizerLib.vcxproj", "{18B3DB45-4FFE-4D01-97D6-5223FEEE1853}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PowerAccent", "PowerAccent", "{0F14491C-6369-4C45-AAA8-135814E66E6B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerAccentModuleInterface", "src\modules\poweraccent\PowerAccentModuleInterface\PowerAccentModuleInterface.vcxproj", "{34A354C5-23C7-4343-916C-C52DAF4FC39D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerAccent.Core", "src\modules\poweraccent\PowerAccent.Core\PowerAccent.Core.csproj", "{3264DF53-C805-4B0C-867C-FCEAF7AEF762}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerAccent.UI", "src\modules\poweraccent\PowerAccent.UI\PowerAccent.UI.csproj", "{31CAD28E-778A-441C-85BC-40AB3EAA2A10}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PowerOCR", "PowerOCR", "{A50C70A6-2DA0-4027-B90E-B1A40755A8A5}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerOCR", "src\modules\PowerOCR\PowerOCR\PowerOCR.csproj", "{25C91A4E-BA4E-467A-85CD-8B62545BF674}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerOCRModuleInterface", "src\modules\PowerOCR\PowerOCRModuleInterface\PowerOCRModuleInterface.vcxproj", "{6AB6A2D6-F859-4A82-9184-0BD29C9F07D1}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{B1234567-1234-1234-1234-123456789ABC}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.History", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.History\Microsoft.PowerToys.Run.Plugin.History.csproj", "{212AD910-8488-4036-BE20-326931B75FB2}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MeasureTool", "MeasureTool", "{7AC943C9-52E8-44CF-9083-744D8049667B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerToys.MeasureToolCore", "src\modules\MeasureTool\MeasureToolCore\PowerToys.MeasureToolCore.vcxproj", "{54A93AF7-60C7-4F6C-99D2-FBB1F75F853A}" - ProjectSection(ProjectDependencies) = postProject - {6955446D-23F7-4023-9BB3-8657F904AF99} = {6955446D-23F7-4023-9BB3-8657F904AF99} - {CABA8DFB-823B-4BF2-93AC-3F31984150D9} = {CABA8DFB-823B-4BF2-93AC-3F31984150D9} - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF} = {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MeasureToolModuleInterface", "src\modules\MeasureTool\MeasureToolModuleInterface\MeasureToolModuleInterface.vcxproj", "{92C39820-9F84-4529-BC7D-22AAE514D63B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MeasureToolUI", "src\modules\MeasureTool\MeasureToolUI\MeasureToolUI.csproj", "{515554D1-D004-4F7F-A107-2211FC0F6B2C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerAccentKeyboardService", "src\modules\poweraccent\PowerAccentKeyboardService\PowerAccentKeyboardService.vcxproj", "{C97D9A5D-206C-454E-997E-009E227D7F02}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostsUILib", "src\modules\Hosts\HostsUILib\HostsUILib.csproj", "{31D1C81D-765F-4446-AA62-E743F6325049}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Hosts", "Hosts", "{F05E590D-AD46-42BE-9C25-6A63ADD2E3EA}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostsEditor.UnitTests", "src\modules\Hosts\Hosts.Tests\HostsEditor.UnitTests.csproj", "{E2D03E0F-7A75-4813-9F4B-D8763D43FD3A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HostsModuleInterface", "src\modules\Hosts\HostsModuleInterface\HostsModuleInterface.vcxproj", "{B41B888C-7DB8-4747-B262-4062E05A230D}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FileLocksmith", "FileLocksmith", "{AB82E5DD-C32D-4F28-9746-2C780846188E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileLocksmithExt", "src\modules\FileLocksmith\FileLocksmithExt\FileLocksmithExt.vcxproj", "{57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileLocksmithUI", "src\modules\FileLocksmith\FileLocksmithUI\FileLocksmithUI.csproj", "{E69B044A-2F8A-45AA-AD0B-256C59421807}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerToys.FileLocksmithLib.Interop", "src\modules\FileLocksmith\FileLocksmithLibInterop\FileLocksmithLibInterop.vcxproj", "{C604B37E-9D0E-4484-8778-E8B31B0E1B3A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GPOWrapper", "src\common\GPOWrapper\GPOWrapper.vcxproj", "{E599C30B-9DC8-4E5A-BF27-93D4CCEDE788}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GPOWrapperProjection", "src\common\GPOWrapperProjection\GPOWrapperProjection.csproj", "{00EE9BA6-4E8F-43CA-960D-D4882F0FBB97}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Peek", "Peek", "{17B4FA70-001E-4D33-BBBB-0D142DBC2E20}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Peek", "src\modules\peek\peek\peek.vcxproj", "{A1425B53-3D61-4679-8623-E64A0D3D0A48}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Peek.UI", "src\modules\peek\Peek.UI\Peek.UI.csproj", "{9D7A6DE0-7D27-424D-ABAE-41B2161F9A03}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Peek.Common", "src\modules\peek\Peek.Common\Peek.Common.csproj", "{17A99C7C-0BFF-45BB-A9FD-63A0DDC105BB}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Peek.FilePreviewer", "src\modules\peek\Peek.FilePreviewer\Peek.FilePreviewer.csproj", "{AA9F0AF8-7924-4D59-BAA1-E36F1304E0DC}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Peek.UITests", "src\modules\peek\Peek.UITests\Peek.UITests.csproj", "{4E0AE3A4-2EE0-44D7-A2D0-8769977254A5}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MarkdownPreviewHandlerCpp", "src\modules\previewpane\MarkdownPreviewHandlerCpp\MarkdownPreviewHandlerCpp.vcxproj", "{ED9A1AC6-AEB0-4569-A6E9-E1696182B545}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GcodePreviewHandlerCpp", "src\modules\previewpane\GcodePreviewHandlerCpp\GcodePreviewHandlerCpp.vcxproj", "{5A5DD09D-723A-44D3-8F2B-293584C3D731}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MonacoPreviewHandlerCpp", "src\modules\previewpane\MonacoPreviewHandlerCpp\MonacoPreviewHandlerCpp.vcxproj", "{B3E869C4-8210-4EBD-A621-FF4C4AFCBFA9}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PdfPreviewHandlerCpp", "src\modules\previewpane\PdfPreviewHandlerCpp\PdfPreviewHandlerCpp.vcxproj", "{54F7C616-FD41-4E62-BFF9-015686914F4D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SvgPreviewHandlerCpp", "src\modules\previewpane\SvgPreviewHandlerCpp\SvgPreviewHandlerCpp.vcxproj", "{143F13E3-D2E3-4D83-B035-356612D99956}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GcodeThumbnailProviderCpp", "src\modules\previewpane\GcodeThumbnailProviderCpp\GcodeThumbnailProviderCpp.vcxproj", "{56CC2F10-6E41-453D-BE16-C593A5E58482}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PdfThumbnailProviderCpp", "src\modules\previewpane\PdfThumbnailProviderCpp\PdfThumbnailProviderCpp.vcxproj", "{CA5518ED-0458-4B09-8F53-4122B9888655}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StlThumbnailProviderCpp", "src\modules\previewpane\StlThumbnailProviderCpp\StlThumbnailProviderCpp.vcxproj", "{D6DCC3AE-18C0-488A-B978-BAA9E3CFF09D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SvgThumbnailProviderCpp", "src\modules\previewpane\SvgThumbnailProviderCpp\SvgThumbnailProviderCpp.vcxproj", "{2BBC9E33-21EC-401C-84DA-BB6590A9B2AA}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MouseWithoutBorders", "MouseWithoutBorders", "{B6C42F16-73EB-477E-8B0D-4E6CF6C20AAC}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MouseWithoutBordersModuleInterface", "src\modules\MouseWithoutBorders\ModuleInterface\MouseWithoutBordersModuleInterface.vcxproj", "{2833C9C6-AB32-4048-A5C7-A70898337B57}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MouseWithoutBorders", "src\modules\MouseWithoutBorders\App\MouseWithoutBorders.csproj", "{50B82783-242F-42D2-BC03-B3430BF01354}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MouseWithoutBordersService", "src\modules\MouseWithoutBorders\App\Service\MouseWithoutBordersService.csproj", "{B5EB9FE9-37EF-47C3-B8B8-81AD3C2972C2}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MouseWithoutBordersHelper", "src\modules\MouseWithoutBorders\App\Helper\MouseWithoutBordersHelper.csproj", "{A663E672-B26D-4EC0-BEAB-FE2E424AC46F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MouseJump", "src\modules\MouseUtils\MouseJump\MouseJump.vcxproj", "{8A08D663-4995-40E3-B42C-3F910625F284}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MouseJump.Common", "src\modules\MouseUtils\MouseJump.Common\MouseJump.Common.csproj", "{923DF87C-CA99-4D1C-B1D2-959174E95BFA}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MouseJump.Common.UnitTests", "src\modules\MouseUtils\MouseJump.Common.UnitTests\MouseJump.Common.UnitTests.csproj", "{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MouseJumpUI", "src\modules\MouseUtils\MouseJumpUI\MouseJumpUI.csproj", "{D962A009-834F-4EEC-AABB-430DF8F98E39}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AdvancedPaste", "AdvancedPaste", "{9873BA05-4C41-4819-9283-CF45D795431B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AdvancedPasteModuleInterface", "src\modules\AdvancedPaste\AdvancedPasteModuleInterface\AdvancedPasteModuleInterface.vcxproj", "{FC373B24-3293-453C-AAF5-CF2909DCEE6A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AllExperiments", "src\common\AllExperiments\AllExperiments.csproj", "{9CE59ED5-7087-4353-88EB-788038A73CEC}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RegistryPreviewUILib", "src\modules\registrypreview\RegistryPreviewUILib\RegistryPreviewUILib.csproj", "{FD86C06A-FB54-4D5E-9831-1CDADF60D45F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RegistryPreviewExt", "src\modules\registrypreview\RegistryPreviewExt\RegistryPreviewExt.vcxproj", "{697C6AF9-0A48-49A9-866C-67DA12384015}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "RegistryPreview", "RegistryPreview", "{929C1324-22E8-4412-A9A8-80E85F3985A5}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FilePreviewCommon", "src\common\FilePreviewCommon\FilePreviewCommon.csproj", "{9EBAA524-0EDA-470B-95D4-39383285CBB2}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.PowerToys", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.PowerToys\Microsoft.PowerToys.Run.Plugin.PowerToys.csproj", "{500DED3E-CFB5-4ED5-ACC6-02B3D6DC336D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Community.PowerToys.Run.Plugin.ValueGenerator", "src\modules\launcher\Plugins\Community.PowerToys.Run.Plugin.ValueGenerator\Community.PowerToys.Run.Plugin.ValueGenerator.csproj", "{D095BE44-1F2E-463E-A494-121892A75EA2}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Community.PowerToys.Run.Plugin.ValueGenerator.UnitTests", "src\modules\launcher\Plugins\Community.PowerToys.Run.Plugin.ValueGenerator.UnitTests\Community.PowerToys.Run.Plugin.ValueGenerator.UnitTests.csproj", "{90F9FA90-2C20-4004-96E6-F3B78151F5A5}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CropAndLock", "CropAndLock", "{3B227528-4BA6-4CAF-B44A-A10C78A64849}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CropAndLock", "src\modules\CropAndLock\CropAndLock\CropAndLock.vcxproj", "{F5E1146E-B7B3-4E11-85FD-270A500BD78C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CropAndLockModuleInterface", "src\modules\CropAndLock\CropAndLockModuleInterface\CropAndLockModuleInterface.vcxproj", "{3157FA75-86CF-4EE2-8F62-C43F776493C6}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "cmdNotFound", "cmdNotFound", "{4C0D0746-BE5B-49EE-BD5D-A7811628AE8B}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EnvironmentVariables", "EnvironmentVariables", "{538ED0BB-B863-4B20-98CC-BCDF7FA0B68A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EnvironmentVariablesUILib", "src\modules\EnvironmentVariables\EnvironmentVariablesUILib\EnvironmentVariablesUILib.csproj", "{51465DA1-C18B-4B99-93E1-ECF8E0FA0CBA}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EnvironmentVariablesModuleInterface", "src\modules\EnvironmentVariables\EnvironmentVariablesModuleInterface\EnvironmentVariablesModuleInterface.vcxproj", "{B9420661-B0E4-4241-ABD4-4A27A1F64250}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QoiThumbnailProviderCpp", "src\modules\previewpane\QoiThumbnailProviderCpp\QoiThumbnailProviderCpp.vcxproj", "{CCB5E44F-84D9-4203-83C6-1C9EC9302BC7}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QoiThumbnailProvider", "src\modules\previewpane\QoiThumbnailProvider\QoiThumbnailProvider.csproj", "{D949EC7D-48A9-4279-95D5-078E7FD1F048}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QoiPreviewHandlerCpp", "src\modules\previewpane\QoiPreviewHandlerCpp\QoiPreviewHandlerCpp.vcxproj", "{3BAF9C81-A194-4925-A035-5E24A5D1E542}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QoiPreviewHandler", "src\modules\previewpane\QoiPreviewHandler\QoiPreviewHandler.csproj", "{6B04803D-B418-4833-A67E-B0FC966636A5}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preview.QoiPreviewHandler.UnitTests", "src\modules\previewpane\UnitTests-QoiPreviewHandler\Preview.QoiPreviewHandler.UnitTests.csproj", "{3940AD4D-F748-4BE4-9083-85769CD553EF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preview.QoiThumbnailProvider.UnitTests", "src\modules\previewpane\UnitTests-QoiThumbnailProvider\Preview.QoiThumbnailProvider.UnitTests.csproj", "{F8FFFC12-A31A-4AFA-B3DF-14DCF42B5E38}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CmdNotFoundModuleInterface", "src\modules\cmdNotFound\CmdNotFoundModuleInterface\CmdNotFoundModuleInterface.vcxproj", "{0014D652-901F-4456-8D65-06FC5F997FB0}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileLocksmithContextMenu", "src\modules\FileLocksmith\FileLocksmithContextMenu\FileLocksmithContextMenu.vcxproj", "{799A50D8-DE89-4ED1-8FF8-AD5A9ED8C0CA}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileLocksmithLib", "src\modules\FileLocksmith\FileLocksmithLib\FileLocksmithLib.vcxproj", "{9D52FD25-EF90-4F9A-A015-91EFC5DAF54F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AdvancedPaste", "src\modules\AdvancedPaste\AdvancedPaste\AdvancedPaste.csproj", "{C32D254F-7597-4CBE-BF74-D922D81CDF29}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hosts", "src\modules\Hosts\Hosts\Hosts.csproj", "{02DD46D3-F761-47D9-8894-2D6DA0124650}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RegistryPreview", "src\modules\registrypreview\RegistryPreview\RegistryPreview.csproj", "{8E23E173-7127-4A5F-9F93-3049F2B68047}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EnvironmentVariables", "src\modules\EnvironmentVariables\EnvironmentVariables\EnvironmentVariables.csproj", "{DFF88D16-D36F-40A4-A955-CDCAA76EF7B8}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FancyZonesEditorCommon", "src\modules\fancyzones\FancyZonesEditorCommon\FancyZonesEditorCommon.csproj", "{C0974915-8A1D-4BF0-977B-9587D3807AB7}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DSC", "DSC", "{557C4636-D7E1-4838-A504-7D19B725EE95}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerToys.Settings.DSC.Schema.Generator", "src\dsc\PowerToys.Settings.DSC.Schema.Generator\PowerToys.Settings.DSC.Schema.Generator.csproj", "{1D6893CB-BC0C-46A8-A76C-9728706CA51A}" - ProjectSection(ProjectDependencies) = postProject - {020A7474-3601-4160-A159-D7B70B77B15F} = {020A7474-3601-4160-A159-D7B70B77B15F} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NewPlus.ShellExtension", "src\modules\NewPlus\NewShellExtensionContextMenu\NewShellExtensionContextMenu.vcxproj", "{8ACB33D9-C95B-47D4-8363-9731EE0930A0}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "New+", "New+", "{CA716AE6-FE5C-40AC-BB8F-2C87912687AC}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerToys.Interop", "src\common\interop\PowerToys.Interop.vcxproj", "{F055103B-F80B-4D0C-BF48-057C55620033}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Workspaces", "Workspaces", "{A2221D7E-55E7-4BEA-90D1-4F162D670BBF}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workspaces-common", "workspaces-common", "{BE126CBB-AE12-406A-9837-A05ACFCA57A7}" - ProjectSection(SolutionItems) = preProject - src\modules\Workspaces\workspaces-common\GuidUtils.h = src\modules\Workspaces\workspaces-common\GuidUtils.h - src\modules\Workspaces\workspaces-common\InvokePoint.h = src\modules\Workspaces\workspaces-common\InvokePoint.h - src\modules\Workspaces\workspaces-common\MonitorEnumerator.h = src\modules\Workspaces\workspaces-common\MonitorEnumerator.h - src\modules\Workspaces\workspaces-common\MonitorUtils.h = src\modules\Workspaces\workspaces-common\MonitorUtils.h - src\modules\Workspaces\workspaces-common\VirtualDesktop.h = src\modules\Workspaces\workspaces-common\VirtualDesktop.h - src\modules\Workspaces\workspaces-common\WindowEnumerator.h = src\modules\Workspaces\workspaces-common\WindowEnumerator.h - src\modules\Workspaces\workspaces-common\WindowFilter.h = src\modules\Workspaces\workspaces-common\WindowFilter.h - src\modules\Workspaces\workspaces-common\WindowUtils.h = src\modules\Workspaces\workspaces-common\WindowUtils.h - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WindowProperties", "WindowProperties", "{14CB58B7-D280-4A7A-95DE-4B2DF14EA000}" - ProjectSection(SolutionItems) = preProject - src\modules\Workspaces\WindowProperties\WorkspacesWindowPropertyUtils.h = src\modules\Workspaces\WindowProperties\WorkspacesWindowPropertyUtils.h - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WorkspacesLib", "src\modules\Workspaces\WorkspacesLib\WorkspacesLib.vcxproj", "{B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Workspaces.Lib.UnitTests", "src\modules\Workspaces\WorkspacesLib.UnitTests\WorkspacesLibUnitTests.vcxproj", "{A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkspacesLauncherUI", "src\modules\Workspaces\WorkspacesLauncherUI\WorkspacesLauncherUI.csproj", "{9C53CC25-0623-4569-95BC-B05410675EE3}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WorkspacesModuleInterface", "src\modules\Workspaces\WorkspacesModuleInterface\WorkspacesModuleInterface.vcxproj", "{45285DF2-9742-4ECA-9AC9-58951FC26489}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WorkspacesSnapshotTool", "src\modules\Workspaces\WorkspacesSnapshotTool\WorkspacesSnapshotTool.vcxproj", "{3D63307B-9D27-44FD-B033-B26F39245B85}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkspacesEditor", "src\modules\Workspaces\WorkspacesEditor\WorkspacesEditor.csproj", "{367D7543-7DBA-4381-99F1-BF6142A996C4}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WorkspacesLauncher", "src\modules\Workspaces\WorkspacesLauncher\WorkspacesLauncher.vcxproj", "{2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WorkspacesWindowArranger", "src\modules\Workspaces\WorkspacesWindowArranger\WorkspacesWindowArranger.vcxproj", "{37D07516-4185-43A4-924F-3C7A5D95ECF6}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EtwTrace", "src\common\Telemetry\EtwTrace\EtwTrace.vcxproj", "{8F021B46-362B-485C-BFBA-CCF83E820CBD}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MouseWithoutBorders.UnitTests", "src\modules\MouseWithoutBorders\MouseWithoutBorders.UnitTests\MouseWithoutBorders.UnitTests.csproj", "{66614C26-314C-4B91-9071-76133422CFEF}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CommandPalette", "CommandPalette", "{3846508C-77EB-4034-A702-F8BB263C4F79}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Built-in Extensions", "Built-in Extensions", "{ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Apps", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.Apps\Microsoft.CmdPal.Ext.Apps.csproj", "{6CE438DF-C245-4997-A360-0A0939E4BA34}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Bookmarks", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.Bookmark\Microsoft.CmdPal.Ext.Bookmarks.csproj", "{E09AA983-C755-474F-83D6-A5CDF528C070}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Calc", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.Calc\Microsoft.CmdPal.Ext.Calc.csproj", "{6D56B64D-FF1F-488F-AFED-9B9854A5D399}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Registry", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.Registry\Microsoft.CmdPal.Ext.Registry.csproj", "{92EC89E4-9972-453A-8A1A-3A9E230C146A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowsServices", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WindowsServices\Microsoft.CmdPal.Ext.WindowsServices.csproj", "{51939B4F-1F62-4BFF-A6A2-C08646E5BE95}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowsSettings", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WindowsSettings\Microsoft.CmdPal.Ext.WindowsSettings.csproj", "{D1160404-D3D1-497A-883A-4059C07C2273}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowsTerminal", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WindowsTerminal\Microsoft.CmdPal.Ext.WindowsTerminal.csproj", "{40F6D69D-E321-400F-A767-5628C7AE453D}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extension SDK", "Extension SDK", "{F3D09629-59A2-4924-A4B9-D6BFAA2C1B49}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.CommandPalette.Extensions", "src\modules\cmdpal\extensionsdk\Microsoft.CommandPalette.Extensions\Microsoft.CommandPalette.Extensions.vcxproj", "{305DD37E-C85D-4B08-AAFE-7381FA890463}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CommandPalette.Extensions.Toolkit", "src\modules\cmdpal\extensionsdk\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj", "{CA4D810F-C8F4-4B61-9DA9-71807E0B9F24}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Core.Common", "src\modules\cmdpal\Core\Microsoft.CmdPal.Core.Common\Microsoft.CmdPal.Core.Common.csproj", "{14E62033-58D0-4A7D-8990-52F50A08BBBD}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.UI", "src\modules\cmdpal\Microsoft.Terminal.UI\Microsoft.Terminal.UI.vcxproj", "{6515F03F-E56D-4DB4-B23D-AC4FB80DB36F}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sample Extensions", "Sample Extensions", "{071E18A4-A530-46B8-AB7D-B862EE55E24E}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProcessMonitorExtension", "src\modules\cmdpal\ext\ProcessMonitorExtension\ProcessMonitorExtension.csproj", "{C846F7A7-792A-47D9-B0CB-417C900EE03D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SamplePagesExtension", "src\modules\cmdpal\ext\SamplePagesExtension\SamplePagesExtension.csproj", "{C831231F-891C-4572-9694-45062534B42A}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UI", "UI", "{7520A2FE-00A2-49B8-83ED-DB216E874C04}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.UI", "src\modules\cmdpal\Microsoft.CmdPal.UI\Microsoft.CmdPal.UI.csproj", "{8FBDABA4-40EE-4C0E-9BC8-2F6444A6EF90}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.UI.ViewModels", "src\modules\cmdpal\Microsoft.CmdPal.UI.ViewModels\Microsoft.CmdPal.UI.ViewModels.csproj", "{C66020D1-CB10-4CF7-8715-84C97FD5E5E2}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.ClipboardHistory", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.ClipboardHistory\Microsoft.CmdPal.Ext.ClipboardHistory.csproj", "{79775343-7A3D-445D-9104-3DD5B2893DF9}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CmdPalModuleInterface", "src\modules\cmdpal\CmdPalModuleInterface\CmdPalModuleInterface.vcxproj", "{0ADEB797-C8C7-4FFA-ACD5-2AF6CAD7ECD8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkspacesCsharpLibrary", "src\modules\Workspaces\WorkspacesCsharpLibrary\WorkspacesCsharpLibrary.csproj", "{89D0E199-B17A-418C-B2F8-7375B6708357}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NewPlus.ShellExtension.win10", "src\modules\NewPlus\NewShellExtensionContextMenu.win10\NewPlus.ShellExtension.win10.vcxproj", "{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.Indexer", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.Indexer\Microsoft.CmdPal.Ext.Indexer.csproj", "{453CBB73-A3CB-4D0B-8D24-6940B86FE21D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Shell", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.Shell\Microsoft.CmdPal.Ext.Shell.csproj", "{C0CE3B5E-16D3-495D-B335-CA791B660162}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowWalker", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WindowWalker\Microsoft.CmdPal.Ext.WindowWalker.csproj", "{3A9A7297-92C4-4F16-B6F9-8D4AB652C86C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.WebSearch", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WebSearch\Microsoft.CmdPal.Ext.WebSearch.csproj", "{605E914B-7232-4789-AF46-BF5D3DDFC14E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.WinGet", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WinGet\Microsoft.CmdPal.Ext.WinGet.csproj", "{E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ZoomIt", "ZoomIt", "{DD6E12FE-5509-4ABC-ACC2-3D6DC98A238C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZoomIt", "src\modules\ZoomIt\ZoomIt\ZoomIt.vcxproj", "{0A84F764-3A88-44CD-AA96-41BDBD48627B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZoomItModuleInterface", "src\modules\ZoomIt\ZoomItModuleInterface\ZoomItModuleInterface.vcxproj", "{E4585179-2AC1-4D5F-A3FF-CFC5392F694C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZoomItSettingsInterop", "src\modules\ZoomIt\ZoomItSettingsInterop\ZoomItSettingsInterop.vcxproj", "{CA7D8106-30B9-4AEC-9D05-B69B31B8C461}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.TimeDate", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.TimeDate\Microsoft.CmdPal.Ext.TimeDate.csproj", "{DCC6BD67-17BB-47AA-B507-FB0FE43A7449}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UITestAutomation", "src\common\UITestAutomation\UITestAutomation.csproj", "{A558C25D-2007-498E-8B6F-43405AFAE9E2}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeyboardManagerEditorUI", "src\modules\keyboardmanager\KeyboardManagerEditorUI\KeyboardManagerEditorUI.csproj", "{08F9155D-B6DC-46E5-9C83-AF60B655898B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManagerEditorLibraryWrapper", "src\modules\keyboardmanager\KeyboardManagerEditorLibraryWrapper\KeyboardManagerEditorLibraryWrapper.vcxproj", "{4382A954-179A-4078-92AF-715187DFFF50}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HostsEditor.FuzzTests", "src\modules\Hosts\Hosts.FuzzTests\HostsEditor.FuzzTests.csproj", "{EBED240C-8702-452D-B764-6DB9DA9179AF}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HostsEditor.UITests", "src\modules\Hosts\Hosts.UITests\HostsEditor.UITests.csproj", "{4E0AE3A4-2EE0-44D7-A2D0-8769977254A0}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RegistryPreview.FuzzTests", "src\modules\registrypreview\RegistryPreview.FuzzTests\RegistryPreview.FuzzTests.csproj", "{5702B3CC-8575-48D5-83D8-15BB42269CD3}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.System", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.System\Microsoft.CmdPal.Ext.System.csproj", "{64B88F02-CD88-4ED8-9624-989A800230F9}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CmdPalKeyboardService", "src\modules\cmdpal\CmdPalKeyboardService\CmdPalKeyboardService.vcxproj", "{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRename.FuzzTests", "src\modules\powerrename\PowerRename.FuzzingTest\PowerRename.FuzzingTest.vcxproj", "{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BgcodePreviewHandler", "src\modules\previewpane\BgcodePreviewHandler\BgcodePreviewHandler.csproj", "{9E0CBC06-F29A-4810-B93C-97D53863B95E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BgcodePreviewHandlerCpp", "src\modules\previewpane\BgcodePreviewHandlerCpp\BgcodePreviewHandlerCpp.vcxproj", "{F6088A11-1C9E-4420-AA90-CF7E78DD7F1C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BgcodeThumbnailProviderCpp", "src\modules\previewpane\BgcodeThumbnailProviderCpp\BgcodeThumbnailProviderCpp.vcxproj", "{47B0678C-806B-4FE1-9F50-46BA88989532}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BgcodeThumbnailProvider", "src\modules\previewpane\BgcodeThumbnailProvider\BgcodeThumbnailProvider.csproj", "{9BC1C986-1E97-4D07-A7B1-CE226C239EFA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Preview.BgcodePreviewHandler.UnitTests", "src\modules\previewpane\UnitTests-BgcodePreviewHandler\Preview.BgcodePreviewHandler.UnitTests.csproj", "{99CA1509-FB73-456E-AFAF-AB89C017BD72}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Preview.BgcodeThumbnailProvider.UnitTests", "src\modules\previewpane\UnitTests-BgcodeThumbnailProvider\Preview.BgcodeThumbnailProvider.UnitTests.csproj", "{61CBF221-9452-4934-B685-146285E080D7}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.Search", "src\common\Common.Search\Common.Search.csproj", "{38F187B2-6638-5A40-072F-DBE5E54070A0}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Settings.UI.XamlIndexBuilder", "src\settings-ui\Settings.UI.XamlIndexBuilder\Settings.UI.XamlIndexBuilder.csproj", "{DA0744BC-E822-680E-9CEB-D0FBA903A8EE}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MouseUtils.UITests", "src\modules\MouseUtils\MouseUtils.UITests\MouseUtils.UITests.csproj", "{4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Workspaces.Editor.UITests", "src\modules\Workspaces\WorkspacesEditorUITest\Workspaces.Editor.UITests.csproj", "{43E779F3-D83C-48B1-BA8D-1912DBD76FC9}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalculatorEngineCommon", "src\common\CalculatorEngineCommon\CalculatorEngineCommon.vcxproj", "{2CF78CF7-8FEB-4BE1-9591-55FA25B48FC6}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ManagedCsWin32", "src\common\ManagedCsWin32\ManagedCsWin32.csproj", "{14AFD976-B4D2-49D0-9E6C-AA93CC061B8A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowerRename.UITests", "src\modules\powerrename\PowerRenameUITest\PowerRename.UITests.csproj", "{9D3F3793-EFE3-4525-8782-238015DABA62}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Core.ViewModels", "src\modules\cmdpal\Core\Microsoft.CmdPal.Core.ViewModels\Microsoft.CmdPal.Core.ViewModels.csproj", "{24133F7F-C1D1-DE04-EFA8-F5D5467FE027}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{0E556541-6A45-42CB-AE49-EE5A9BE05E7C}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{27D9CB3A-46D1-402C-9273-F88CB8AC42F7}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{B9617A31-0F0A-4397-851D-BF2FBEE32D7F}" - ProjectSection(SolutionItems) = preProject - src\modules\launcher\Plugins\Microsoft.Plugin.Folder.UnitTests\Microsoft.Plugin.Folder.UnitTests.csproj = src\modules\launcher\Plugins\Microsoft.Plugin.Folder.UnitTests\Microsoft.Plugin.Folder.UnitTests.csproj - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{1C48CD47-D610-463A-A53C-AF82DD6C47E7}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{D9BD324E-1D80-44AA-8E7B-73EB00944434}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{8EF25507-2575-4ADE-BF7E-D23376903AB8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowerOCR.UITests", "src\modules\PowerOCR\PowerOCR-UITests\PowerOCR.UITests.csproj", "{070AC093-C9F2-20AD-0BCD-F318FC2761EA}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{2C318EC3-BA86-4372-B1BC-DB0F33C208B2}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{BFFB607F-7C78-434B-86B9-DA4C8196A1B5}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{66E1534A-1587-42B2-912F-45C994D32904}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{E885E71F-0B34-4A03-B13B-20F4E05E90BB}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{264B412F-DB8B-4CF8-A74B-96998B183045}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{3527BF37-DFC5-4309-A032-29278CA21328}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{68328142-5B31-4715-BCBB-7B6345EE0971}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvancedPaste.FuzzTests", "src\modules\AdvancedPaste\AdvancedPaste.FuzzTests\AdvancedPaste.FuzzTests.csproj", "{4122388B-59E4-CDB0-0338-EA6881DF86F0}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvancedPaste.UnitTests", "src\modules\AdvancedPaste\AdvancedPaste.UnitTests\AdvancedPaste.UnitTests.csproj", "{988C9FAF-5AEC-EB15-578D-FED0DF52BF55}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.UITests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.UITests\Microsoft.CmdPal.UITests.csproj", "{6748A29D-DA6A-033A-825B-752295FF6AA0}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FancyZones.FuzzTests", "src\modules\fancyzones\FancyZones.FuzzTests\FancyZones.FuzzTests.csproj", "{6EABCF9A-6526-441F-932F-658B1DC3E403}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FancyZones.UITests", "src\modules\fancyzones\FancyZones.UITests\FancyZones.UITests.csproj", "{69D76A76-6EF6-4846-94CD-EAAF0CAC9F15}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FancyZonesEditor.UITests", "src\modules\fancyzones\FancyZonesEditor.UITests\FancyZonesEditor.UITests.csproj", "{9BAFFC28-E1EF-4C14-A101-EEBFC0A50D83}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FancyZonesEditor.UnitTests", "src\modules\fancyzones\FancyZonesEditor.UnitTests\FancyZonesEditor.UnitTests.csproj", "{806BF185-8B89-5BE1-9AA1-DA5BC9487DB9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColorPickerUI.UnitTests", "src\modules\colorPicker\ColorPickerUI.UnitTests\ColorPickerUI.UnitTests.csproj", "{F93C2817-C846-4259-84D8-B39A6B57C8DE}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{8131151D-B0E9-4E18-84A5-E5F946C4480A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.Calc.UnitTests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.Ext.Calc.UnitTests\Microsoft.CmdPal.Ext.Calc.UnitTests.csproj", "{E816D7AC-4688-4ECB-97CC-3D8E798F3825}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.Registry.UnitTests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.Ext.Registry.UnitTests\Microsoft.CmdPal.Ext.Registry.UnitTests.csproj", "{E816D7AD-4688-4ECB-97CC-3D8E798F3826}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.System.UnitTests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.Ext.System.UnitTests\Microsoft.CmdPal.Ext.System.UnitTests.csproj", "{E816D7AE-4688-4ECB-97CC-3D8E798F3827}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.TimeDate.UnitTests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.Ext.TimeDate.UnitTests\Microsoft.CmdPal.Ext.TimeDate.UnitTests.csproj", "{E816D7AF-4688-4ECB-97CC-3D8E798F3828}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.WindowWalker.UnitTests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.Ext.WindowWalker.UnitTests\Microsoft.CmdPal.Ext.WindowWalker.UnitTests.csproj", "{E816D7B0-4688-4ECB-97CC-3D8E798F3829}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.UnitTestBase", "src\modules\cmdpal\Tests\Microsoft.CmdPal.Ext.UnitTestsBase\Microsoft.CmdPal.Ext.UnitTestBase.csproj", "{00D8659C-2068-40B6-8B86-759CD6284BBB}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LightSwitch", "LightSwitch", "{5B201255-53C8-490B-A34F-01F05D48A477}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LightSwitchModuleInterface", "src\modules\LightSwitch\LightSwitchModuleInterface\LightSwitchModuleInterface.vcxproj", "{38177D56-6AD1-4ADF-88C9-2843A7932166}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LightSwitchService", "src\modules\LightSwitch\LightSwitchService\LightSwitchService.vcxproj", "{08E71C67-6A7E-4CA1-B04E-2FB336410BAC}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{E11826E1-76DF-42AC-985C-164CC2EE57A1}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScreenRuler.UITests", "src\modules\MeasureTool\Tests\ScreenRuler.UITests\ScreenRuler.UITests.csproj", "{66C069F8-C548-4CA6-8CDE-239104D68E88}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "v3", "v3", "{9605B84E-FAC4-477B-B9EC-0753177EE6A8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowerToys.DSC", "src\dsc\v3\PowerToys.DSC\PowerToys.DSC.csproj", "{94CDC147-6137-45E9-AEDE-17FF809607C0}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowerToys.DSC.UnitTests", "src\dsc\v3\PowerToys.DSC.UnitTests\PowerToys.DSC.UnitTests.csproj", "{A24BF1AF-79AA-4896-BAE3-CCBBE0380A78}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.Apps.UnitTests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.Ext.Apps.UnitTests\Microsoft.CmdPal.Ext.Apps.UnitTests.csproj", "{E816D7B1-4688-4ECB-97CC-3D8E798F3830}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.Bookmarks.UnitTests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.Ext.Bookmarks.UnitTests\Microsoft.CmdPal.Ext.Bookmarks.UnitTests.csproj", "{E816D7B3-4688-4ECB-97CC-3D8E798F3832}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.WebSearch.UnitTests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.Ext.WebSearch.UnitTests\Microsoft.CmdPal.Ext.WebSearch.UnitTests.csproj", "{E816D7B2-4688-4ECB-97CC-3D8E798F3831}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.Shell.UnitTests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.Ext.Shell.UnitTests\Microsoft.CmdPal.Ext.Shell.UnitTests.csproj", "{E816D7B4-4688-4ECB-97CC-3D8E798F3833}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CursorWrap", "src\modules\MouseUtils\CursorWrap\CursorWrap.vcxproj", "{48A1DB8C-5DF8-4FB3-9E14-2B67F3F2D8B5}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{3DCCD936-D085-4869-A1DE-CA6A64152C94}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LightSwitch.UITests", "src\modules\LightSwitch\Tests\LightSwitch.UITests\LightSwitch.UITests.csproj", "{F5333ED7-06D8-4AB3-953A-36D63F08CB6F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.ClipboardHistory.UnitTests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.Ext.ClipboardHistory.UnitTests\Microsoft.CmdPal.Ext.ClipboardHistory.UnitTests.csproj", "{4E0FCF69-B06B-D272-76BF-ED3A559B4EDA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LanguageModelProvider", "src\common\LanguageModelProvider\LanguageModelProvider.csproj", "{45354F4F-1414-45CE-B600-51CD1209FD19}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.UI.ViewModels.UnitTests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.UI.ViewModels.UnitTests\Microsoft.CmdPal.UI.ViewModels.UnitTests.csproj", "{A66E9270-5D93-EC9C-F06E-CE7295BB9A6C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.RemoteDesktop", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.RemoteDesktop\Microsoft.CmdPal.Ext.RemoteDesktop.csproj", "{2B3FB837-23DE-629F-82C6-42304E7083C9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.RemoteDesktop.UnitTests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.Ext.RemoteDesktop.UnitTests\Microsoft.CmdPal.Ext.RemoteDesktop.UnitTests.csproj", "{DB34808A-FF91-D06E-A426-AFB5A8BD583B}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|ARM64 = Debug|ARM64 - Debug|x64 = Debug|x64 - Release|ARM64 = Release|ARM64 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {9412D5C6-2CF2-4FC2-A601-B55508EA9B27}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {9412D5C6-2CF2-4FC2-A601-B55508EA9B27}.Debug|ARM64.Build.0 = Debug|ARM64 - {9412D5C6-2CF2-4FC2-A601-B55508EA9B27}.Debug|x64.ActiveCfg = Debug|x64 - {9412D5C6-2CF2-4FC2-A601-B55508EA9B27}.Debug|x64.Build.0 = Debug|x64 - {9412D5C6-2CF2-4FC2-A601-B55508EA9B27}.Release|ARM64.ActiveCfg = Release|ARM64 - {9412D5C6-2CF2-4FC2-A601-B55508EA9B27}.Release|ARM64.Build.0 = Release|ARM64 - {9412D5C6-2CF2-4FC2-A601-B55508EA9B27}.Release|x64.ActiveCfg = Release|x64 - {9412D5C6-2CF2-4FC2-A601-B55508EA9B27}.Release|x64.Build.0 = Release|x64 - {F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}.Debug|ARM64.Build.0 = Debug|ARM64 - {F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}.Debug|x64.ActiveCfg = Debug|x64 - {F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}.Debug|x64.Build.0 = Debug|x64 - {F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}.Release|ARM64.ActiveCfg = Release|ARM64 - {F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}.Release|ARM64.Build.0 = Release|ARM64 - {F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}.Release|x64.ActiveCfg = Release|x64 - {F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}.Release|x64.Build.0 = Release|x64 - {9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}.Debug|ARM64.Build.0 = Debug|ARM64 - {9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}.Debug|x64.ActiveCfg = Debug|x64 - {9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}.Debug|x64.Build.0 = Debug|x64 - {9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}.Release|ARM64.ActiveCfg = Release|ARM64 - {9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}.Release|ARM64.Build.0 = Release|ARM64 - {9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}.Release|x64.ActiveCfg = Release|x64 - {9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}.Release|x64.Build.0 = Release|x64 - {1A066C63-64B3-45F8-92FE-664E1CCE8077}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {1A066C63-64B3-45F8-92FE-664E1CCE8077}.Debug|ARM64.Build.0 = Debug|ARM64 - {1A066C63-64B3-45F8-92FE-664E1CCE8077}.Debug|x64.ActiveCfg = Debug|x64 - {1A066C63-64B3-45F8-92FE-664E1CCE8077}.Debug|x64.Build.0 = Debug|x64 - {1A066C63-64B3-45F8-92FE-664E1CCE8077}.Release|ARM64.ActiveCfg = Release|ARM64 - {1A066C63-64B3-45F8-92FE-664E1CCE8077}.Release|ARM64.Build.0 = Release|ARM64 - {1A066C63-64B3-45F8-92FE-664E1CCE8077}.Release|x64.ActiveCfg = Release|x64 - {1A066C63-64B3-45F8-92FE-664E1CCE8077}.Release|x64.Build.0 = Release|x64 - {E2A5A82E-1E5B-4C8D-9A4F-2B1A8F9E5C3D}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {E2A5A82E-1E5B-4C8D-9A4F-2B1A8F9E5C3D}.Debug|ARM64.Build.0 = Debug|ARM64 - {E2A5A82E-1E5B-4C8D-9A4F-2B1A8F9E5C3D}.Debug|x64.ActiveCfg = Debug|x64 - {E2A5A82E-1E5B-4C8D-9A4F-2B1A8F9E5C3D}.Debug|x64.Build.0 = Debug|x64 - {E2A5A82E-1E5B-4C8D-9A4F-2B1A8F9E5C3D}.Release|ARM64.ActiveCfg = Release|ARM64 - {E2A5A82E-1E5B-4C8D-9A4F-2B1A8F9E5C3D}.Release|ARM64.Build.0 = Release|ARM64 - {E2A5A82E-1E5B-4C8D-9A4F-2B1A8F9E5C3D}.Release|x64.ActiveCfg = Release|x64 - {E2A5A82E-1E5B-4C8D-9A4F-2B1A8F9E5C3D}.Release|x64.Build.0 = Release|x64 - {5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Debug|ARM64.Build.0 = Debug|ARM64 - {5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Debug|x64.ActiveCfg = Debug|x64 - {5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Debug|x64.Build.0 = Debug|x64 - {5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Release|ARM64.ActiveCfg = Release|ARM64 - {5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Release|ARM64.Build.0 = Release|ARM64 - {5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Release|x64.ActiveCfg = Release|x64 - {5CCC8468-DEC8-4D36-99D4-5C891BEBD481}.Release|x64.Build.0 = Release|x64 - {B25AC7A5-FB9F-4789-B392-D5C85E948670}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {B25AC7A5-FB9F-4789-B392-D5C85E948670}.Debug|ARM64.Build.0 = Debug|ARM64 - {B25AC7A5-FB9F-4789-B392-D5C85E948670}.Debug|x64.ActiveCfg = Debug|x64 - {B25AC7A5-FB9F-4789-B392-D5C85E948670}.Debug|x64.Build.0 = Debug|x64 - {B25AC7A5-FB9F-4789-B392-D5C85E948670}.Release|ARM64.ActiveCfg = Release|ARM64 - {B25AC7A5-FB9F-4789-B392-D5C85E948670}.Release|ARM64.Build.0 = Release|ARM64 - {B25AC7A5-FB9F-4789-B392-D5C85E948670}.Release|x64.ActiveCfg = Release|x64 - {B25AC7A5-FB9F-4789-B392-D5C85E948670}.Release|x64.Build.0 = Release|x64 - {51920F1F-C28C-4ADF-8660-4238766796C2}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {51920F1F-C28C-4ADF-8660-4238766796C2}.Debug|ARM64.Build.0 = Debug|ARM64 - {51920F1F-C28C-4ADF-8660-4238766796C2}.Debug|x64.ActiveCfg = Debug|x64 - {51920F1F-C28C-4ADF-8660-4238766796C2}.Debug|x64.Build.0 = Debug|x64 - {51920F1F-C28C-4ADF-8660-4238766796C2}.Release|ARM64.ActiveCfg = Release|ARM64 - {51920F1F-C28C-4ADF-8660-4238766796C2}.Release|ARM64.Build.0 = Release|ARM64 - {51920F1F-C28C-4ADF-8660-4238766796C2}.Release|x64.ActiveCfg = Release|x64 - {51920F1F-C28C-4ADF-8660-4238766796C2}.Release|x64.Build.0 = Release|x64 - {A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Debug|ARM64.Build.0 = Debug|ARM64 - {A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Debug|x64.ActiveCfg = Debug|x64 - {A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Debug|x64.Build.0 = Debug|x64 - {A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Release|ARM64.ActiveCfg = Release|ARM64 - {A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Release|ARM64.Build.0 = Release|ARM64 - {A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Release|x64.ActiveCfg = Release|x64 - {A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Release|x64.Build.0 = Release|x64 - {2151F984-E006-4A9F-92EF-C6DDE3DC8413}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {2151F984-E006-4A9F-92EF-C6DDE3DC8413}.Debug|ARM64.Build.0 = Debug|ARM64 - {2151F984-E006-4A9F-92EF-C6DDE3DC8413}.Debug|x64.ActiveCfg = Debug|x64 - {2151F984-E006-4A9F-92EF-C6DDE3DC8413}.Debug|x64.Build.0 = Debug|x64 - {2151F984-E006-4A9F-92EF-C6DDE3DC8413}.Release|ARM64.ActiveCfg = Release|ARM64 - {2151F984-E006-4A9F-92EF-C6DDE3DC8413}.Release|ARM64.Build.0 = Release|ARM64 - {2151F984-E006-4A9F-92EF-C6DDE3DC8413}.Release|x64.ActiveCfg = Release|x64 - {2151F984-E006-4A9F-92EF-C6DDE3DC8413}.Release|x64.Build.0 = Release|x64 - {64A80062-4D8B-4229-8A38-DFA1D7497749}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {64A80062-4D8B-4229-8A38-DFA1D7497749}.Debug|ARM64.Build.0 = Debug|ARM64 - {64A80062-4D8B-4229-8A38-DFA1D7497749}.Debug|x64.ActiveCfg = Debug|x64 - {64A80062-4D8B-4229-8A38-DFA1D7497749}.Debug|x64.Build.0 = Debug|x64 - {64A80062-4D8B-4229-8A38-DFA1D7497749}.Release|ARM64.ActiveCfg = Release|ARM64 - {64A80062-4D8B-4229-8A38-DFA1D7497749}.Release|ARM64.Build.0 = Release|ARM64 - {64A80062-4D8B-4229-8A38-DFA1D7497749}.Release|x64.ActiveCfg = Release|x64 - {64A80062-4D8B-4229-8A38-DFA1D7497749}.Release|x64.Build.0 = Release|x64 - {89F34AF7-1C34-4A72-AA6E-534BCF972BD9}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {89F34AF7-1C34-4A72-AA6E-534BCF972BD9}.Debug|ARM64.Build.0 = Debug|ARM64 - {89F34AF7-1C34-4A72-AA6E-534BCF972BD9}.Debug|x64.ActiveCfg = Debug|x64 - {89F34AF7-1C34-4A72-AA6E-534BCF972BD9}.Debug|x64.Build.0 = Debug|x64 - {89F34AF7-1C34-4A72-AA6E-534BCF972BD9}.Release|ARM64.ActiveCfg = Release|ARM64 - {89F34AF7-1C34-4A72-AA6E-534BCF972BD9}.Release|ARM64.Build.0 = Release|ARM64 - {89F34AF7-1C34-4A72-AA6E-534BCF972BD9}.Release|x64.ActiveCfg = Release|x64 - {89F34AF7-1C34-4A72-AA6E-534BCF972BD9}.Release|x64.Build.0 = Release|x64 - {2BE46397-4DFA-414C-9BD4-41E4BBF8CB34}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {2BE46397-4DFA-414C-9BD4-41E4BBF8CB34}.Debug|ARM64.Build.0 = Debug|ARM64 - {2BE46397-4DFA-414C-9BD4-41E4BBF8CB34}.Debug|x64.ActiveCfg = Debug|x64 - {2BE46397-4DFA-414C-9BD4-41E4BBF8CB34}.Debug|x64.Build.0 = Debug|x64 - {2BE46397-4DFA-414C-9BD4-41E4BBF8CB34}.Release|ARM64.ActiveCfg = Release|ARM64 - {2BE46397-4DFA-414C-9BD4-41E4BBF8CB34}.Release|ARM64.Build.0 = Release|ARM64 - {2BE46397-4DFA-414C-9BD4-41E4BBF8CB34}.Release|x64.ActiveCfg = Release|x64 - {2BE46397-4DFA-414C-9BD4-41E4BBF8CB34}.Release|x64.Build.0 = Release|x64 - {0B43679E-EDFA-4DA0-AD30-F4628B308B1B}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {0B43679E-EDFA-4DA0-AD30-F4628B308B1B}.Debug|ARM64.Build.0 = Debug|ARM64 - {0B43679E-EDFA-4DA0-AD30-F4628B308B1B}.Debug|x64.ActiveCfg = Debug|x64 - {0B43679E-EDFA-4DA0-AD30-F4628B308B1B}.Debug|x64.Build.0 = Debug|x64 - {0B43679E-EDFA-4DA0-AD30-F4628B308B1B}.Release|ARM64.ActiveCfg = Release|ARM64 - {0B43679E-EDFA-4DA0-AD30-F4628B308B1B}.Release|ARM64.Build.0 = Release|ARM64 - {0B43679E-EDFA-4DA0-AD30-F4628B308B1B}.Release|x64.ActiveCfg = Release|x64 - {0B43679E-EDFA-4DA0-AD30-F4628B308B1B}.Release|x64.Build.0 = Release|x64 - {E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8}.Debug|ARM64.Build.0 = Debug|ARM64 - {E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8}.Debug|x64.ActiveCfg = Debug|x64 - {E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8}.Debug|x64.Build.0 = Debug|x64 - {E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8}.Release|ARM64.ActiveCfg = Release|ARM64 - {E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8}.Release|ARM64.Build.0 = Release|ARM64 - {E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8}.Release|x64.ActiveCfg = Release|x64 - {E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8}.Release|x64.Build.0 = Release|x64 - {D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D}.Debug|ARM64.Build.0 = Debug|ARM64 - {D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D}.Debug|x64.ActiveCfg = Debug|x64 - {D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D}.Debug|x64.Build.0 = Debug|x64 - {D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D}.Release|ARM64.ActiveCfg = Release|ARM64 - {D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D}.Release|ARM64.Build.0 = Release|ARM64 - {D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D}.Release|x64.ActiveCfg = Release|x64 - {D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D}.Release|x64.Build.0 = Release|x64 - {17DA04DF-E393-4397-9CF0-84DABE11032E}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {17DA04DF-E393-4397-9CF0-84DABE11032E}.Debug|ARM64.Build.0 = Debug|ARM64 - {17DA04DF-E393-4397-9CF0-84DABE11032E}.Debug|x64.ActiveCfg = Debug|x64 - {17DA04DF-E393-4397-9CF0-84DABE11032E}.Debug|x64.Build.0 = Debug|x64 - {17DA04DF-E393-4397-9CF0-84DABE11032E}.Release|ARM64.ActiveCfg = Release|ARM64 - {17DA04DF-E393-4397-9CF0-84DABE11032E}.Release|ARM64.Build.0 = Release|ARM64 - {17DA04DF-E393-4397-9CF0-84DABE11032E}.Release|x64.ActiveCfg = Release|x64 - {17DA04DF-E393-4397-9CF0-84DABE11032E}.Release|x64.Build.0 = Release|x64 - {8AFFA899-0B73-49EC-8C50-0FADDA57B2FC}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {8AFFA899-0B73-49EC-8C50-0FADDA57B2FC}.Debug|ARM64.Build.0 = Debug|ARM64 - {8AFFA899-0B73-49EC-8C50-0FADDA57B2FC}.Debug|x64.ActiveCfg = Debug|x64 - {8AFFA899-0B73-49EC-8C50-0FADDA57B2FC}.Debug|x64.Build.0 = Debug|x64 - {8AFFA899-0B73-49EC-8C50-0FADDA57B2FC}.Release|ARM64.ActiveCfg = Release|ARM64 - {8AFFA899-0B73-49EC-8C50-0FADDA57B2FC}.Release|ARM64.Build.0 = Release|ARM64 - {8AFFA899-0B73-49EC-8C50-0FADDA57B2FC}.Release|x64.ActiveCfg = Release|x64 - {8AFFA899-0B73-49EC-8C50-0FADDA57B2FC}.Release|x64.Build.0 = Release|x64 - {4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}.Debug|ARM64.Build.0 = Debug|ARM64 - {4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}.Debug|x64.ActiveCfg = Debug|x64 - {4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}.Debug|x64.Build.0 = Debug|x64 - {4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}.Release|ARM64.ActiveCfg = Release|ARM64 - {4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}.Release|ARM64.Build.0 = Release|ARM64 - {4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}.Release|x64.ActiveCfg = Release|x64 - {4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}.Release|x64.Build.0 = Release|x64 - {8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Debug|ARM64.Build.0 = Debug|ARM64 - {8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Debug|x64.ActiveCfg = Debug|x64 - {8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Debug|x64.Build.0 = Debug|x64 - {8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Release|ARM64.ActiveCfg = Release|ARM64 - {8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Release|ARM64.Build.0 = Release|ARM64 - {8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Release|x64.ActiveCfg = Release|x64 - {8451ECDD-2EA4-4966-BB0A-7BBC40138E80}.Release|x64.Build.0 = Release|x64 - {FF742965-9A80-41A5-B042-D6C7D3A21708}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {FF742965-9A80-41A5-B042-D6C7D3A21708}.Debug|ARM64.Build.0 = Debug|ARM64 - {FF742965-9A80-41A5-B042-D6C7D3A21708}.Debug|x64.ActiveCfg = Debug|x64 - {FF742965-9A80-41A5-B042-D6C7D3A21708}.Debug|x64.Build.0 = Debug|x64 - {FF742965-9A80-41A5-B042-D6C7D3A21708}.Release|ARM64.ActiveCfg = Release|ARM64 - {FF742965-9A80-41A5-B042-D6C7D3A21708}.Release|ARM64.Build.0 = Release|ARM64 - {FF742965-9A80-41A5-B042-D6C7D3A21708}.Release|x64.ActiveCfg = Release|x64 - {FF742965-9A80-41A5-B042-D6C7D3A21708}.Release|x64.Build.0 = Release|x64 - {59BD9891-3837-438A-958D-ADC7F91F6F7E}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {59BD9891-3837-438A-958D-ADC7F91F6F7E}.Debug|ARM64.Build.0 = Debug|ARM64 - {59BD9891-3837-438A-958D-ADC7F91F6F7E}.Debug|x64.ActiveCfg = Debug|x64 - {59BD9891-3837-438A-958D-ADC7F91F6F7E}.Debug|x64.Build.0 = Debug|x64 - {59BD9891-3837-438A-958D-ADC7F91F6F7E}.Release|ARM64.ActiveCfg = Release|ARM64 - {59BD9891-3837-438A-958D-ADC7F91F6F7E}.Release|ARM64.Build.0 = Release|ARM64 - {59BD9891-3837-438A-958D-ADC7F91F6F7E}.Release|x64.ActiveCfg = Release|x64 - {59BD9891-3837-438A-958D-ADC7F91F6F7E}.Release|x64.Build.0 = Release|x64 - {4D971245-7A70-41D5-BAA0-DDB5684CAF51}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {4D971245-7A70-41D5-BAA0-DDB5684CAF51}.Debug|ARM64.Build.0 = Debug|ARM64 - {4D971245-7A70-41D5-BAA0-DDB5684CAF51}.Debug|x64.ActiveCfg = Debug|x64 - {4D971245-7A70-41D5-BAA0-DDB5684CAF51}.Debug|x64.Build.0 = Debug|x64 - {4D971245-7A70-41D5-BAA0-DDB5684CAF51}.Release|ARM64.ActiveCfg = Release|ARM64 - {4D971245-7A70-41D5-BAA0-DDB5684CAF51}.Release|ARM64.Build.0 = Release|ARM64 - {4D971245-7A70-41D5-BAA0-DDB5684CAF51}.Release|x64.ActiveCfg = Release|x64 - {4D971245-7A70-41D5-BAA0-DDB5684CAF51}.Release|x64.Build.0 = Release|x64 - {74F1B9ED-F59C-4FE7-B473-7B453E30837E}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {74F1B9ED-F59C-4FE7-B473-7B453E30837E}.Debug|ARM64.Build.0 = Debug|ARM64 - {74F1B9ED-F59C-4FE7-B473-7B453E30837E}.Debug|x64.ActiveCfg = Debug|x64 - {74F1B9ED-F59C-4FE7-B473-7B453E30837E}.Debug|x64.Build.0 = Debug|x64 - {74F1B9ED-F59C-4FE7-B473-7B453E30837E}.Release|ARM64.ActiveCfg = Release|ARM64 - {74F1B9ED-F59C-4FE7-B473-7B453E30837E}.Release|ARM64.Build.0 = Release|ARM64 - {74F1B9ED-F59C-4FE7-B473-7B453E30837E}.Release|x64.ActiveCfg = Release|x64 - {74F1B9ED-F59C-4FE7-B473-7B453E30837E}.Release|x64.Build.0 = Release|x64 - {FDB3555B-58EF-4AE6-B5F1-904719637AB4}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {FDB3555B-58EF-4AE6-B5F1-904719637AB4}.Debug|ARM64.Build.0 = Debug|ARM64 - {FDB3555B-58EF-4AE6-B5F1-904719637AB4}.Debug|x64.ActiveCfg = Debug|x64 - {FDB3555B-58EF-4AE6-B5F1-904719637AB4}.Debug|x64.Build.0 = Debug|x64 - {FDB3555B-58EF-4AE6-B5F1-904719637AB4}.Release|ARM64.ActiveCfg = Release|ARM64 - {FDB3555B-58EF-4AE6-B5F1-904719637AB4}.Release|ARM64.Build.0 = Release|ARM64 - {FDB3555B-58EF-4AE6-B5F1-904719637AB4}.Release|x64.ActiveCfg = Release|x64 - {FDB3555B-58EF-4AE6-B5F1-904719637AB4}.Release|x64.Build.0 = Release|x64 - {C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}.Debug|ARM64.Build.0 = Debug|ARM64 - {C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}.Debug|x64.ActiveCfg = Debug|x64 - {C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}.Debug|x64.Build.0 = Debug|x64 - {C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}.Release|ARM64.ActiveCfg = Release|ARM64 - {C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}.Release|ARM64.Build.0 = Release|ARM64 - {C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}.Release|x64.ActiveCfg = Release|x64 - {C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}.Release|x64.Build.0 = Release|x64 - {F8B870EB-D5F5-45BA-9CF7-A5C459818820}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {F8B870EB-D5F5-45BA-9CF7-A5C459818820}.Debug|ARM64.Build.0 = Debug|ARM64 - {F8B870EB-D5F5-45BA-9CF7-A5C459818820}.Debug|x64.ActiveCfg = Debug|x64 - {F8B870EB-D5F5-45BA-9CF7-A5C459818820}.Debug|x64.Build.0 = Debug|x64 - {F8B870EB-D5F5-45BA-9CF7-A5C459818820}.Release|ARM64.ActiveCfg = Release|ARM64 - {F8B870EB-D5F5-45BA-9CF7-A5C459818820}.Release|ARM64.Build.0 = Release|ARM64 - {F8B870EB-D5F5-45BA-9CF7-A5C459818820}.Release|x64.ActiveCfg = Release|x64 - {F8B870EB-D5F5-45BA-9CF7-A5C459818820}.Release|x64.Build.0 = Release|x64 - {E364F67B-BB12-4E91-B639-355866EBCD8B}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {E364F67B-BB12-4E91-B639-355866EBCD8B}.Debug|ARM64.Build.0 = Debug|ARM64 - {E364F67B-BB12-4E91-B639-355866EBCD8B}.Debug|x64.ActiveCfg = Debug|x64 - {E364F67B-BB12-4E91-B639-355866EBCD8B}.Debug|x64.Build.0 = Debug|x64 - {E364F67B-BB12-4E91-B639-355866EBCD8B}.Release|ARM64.ActiveCfg = Release|ARM64 - {E364F67B-BB12-4E91-B639-355866EBCD8B}.Release|ARM64.Build.0 = Release|ARM64 - {E364F67B-BB12-4E91-B639-355866EBCD8B}.Release|x64.ActiveCfg = Release|x64 - {E364F67B-BB12-4E91-B639-355866EBCD8B}.Release|x64.Build.0 = Release|x64 - {F97E5003-F263-4D4A-A964-0F1F3C82DEF2}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {F97E5003-F263-4D4A-A964-0F1F3C82DEF2}.Debug|ARM64.Build.0 = Debug|ARM64 - {F97E5003-F263-4D4A-A964-0F1F3C82DEF2}.Debug|x64.ActiveCfg = Debug|x64 - {F97E5003-F263-4D4A-A964-0F1F3C82DEF2}.Debug|x64.Build.0 = Debug|x64 - {F97E5003-F263-4D4A-A964-0F1F3C82DEF2}.Release|ARM64.ActiveCfg = Release|ARM64 - {F97E5003-F263-4D4A-A964-0F1F3C82DEF2}.Release|ARM64.Build.0 = Release|ARM64 - {F97E5003-F263-4D4A-A964-0F1F3C82DEF2}.Release|x64.ActiveCfg = Release|x64 - {F97E5003-F263-4D4A-A964-0F1F3C82DEF2}.Release|x64.Build.0 = Release|x64 - {AF2349B8-E5B6-4004-9502-687C1C7730B1}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {AF2349B8-E5B6-4004-9502-687C1C7730B1}.Debug|ARM64.Build.0 = Debug|ARM64 - {AF2349B8-E5B6-4004-9502-687C1C7730B1}.Debug|x64.ActiveCfg = Debug|x64 - {AF2349B8-E5B6-4004-9502-687C1C7730B1}.Debug|x64.Build.0 = Debug|x64 - {AF2349B8-E5B6-4004-9502-687C1C7730B1}.Release|ARM64.ActiveCfg = Release|ARM64 - {AF2349B8-E5B6-4004-9502-687C1C7730B1}.Release|ARM64.Build.0 = Release|ARM64 - {AF2349B8-E5B6-4004-9502-687C1C7730B1}.Release|x64.ActiveCfg = Release|x64 - {AF2349B8-E5B6-4004-9502-687C1C7730B1}.Release|x64.Build.0 = Release|x64 - {6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}.Debug|ARM64.Build.0 = Debug|ARM64 - {6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}.Debug|x64.ActiveCfg = Debug|x64 - {6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}.Debug|x64.Build.0 = Debug|x64 - {6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}.Release|ARM64.ActiveCfg = Release|ARM64 - {6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}.Release|ARM64.Build.0 = Release|ARM64 - {6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}.Release|x64.ActiveCfg = Release|x64 - {6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}.Release|x64.Build.0 = Release|x64 - {A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}.Debug|ARM64.Build.0 = Debug|ARM64 - {A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}.Debug|x64.ActiveCfg = Debug|x64 - {A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}.Debug|x64.Build.0 = Debug|x64 - {A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}.Release|ARM64.ActiveCfg = Release|ARM64 - {A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}.Release|ARM64.Build.0 = Release|ARM64 - {A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}.Release|x64.ActiveCfg = Release|x64 - {A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}.Release|x64.Build.0 = Release|x64 - {DA425894-6E13-404F-8DCB-78584EC0557A}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {DA425894-6E13-404F-8DCB-78584EC0557A}.Debug|ARM64.Build.0 = Debug|ARM64 - {DA425894-6E13-404F-8DCB-78584EC0557A}.Debug|x64.ActiveCfg = Debug|x64 - {DA425894-6E13-404F-8DCB-78584EC0557A}.Debug|x64.Build.0 = Debug|x64 - {DA425894-6E13-404F-8DCB-78584EC0557A}.Release|ARM64.ActiveCfg = Release|ARM64 - {DA425894-6E13-404F-8DCB-78584EC0557A}.Release|ARM64.Build.0 = Release|ARM64 - {DA425894-6E13-404F-8DCB-78584EC0557A}.Release|x64.ActiveCfg = Release|x64 - {DA425894-6E13-404F-8DCB-78584EC0557A}.Release|x64.Build.0 = Release|x64 - {060D75DA-2D1C-48E6-A4A1-6F0718B64661}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {060D75DA-2D1C-48E6-A4A1-6F0718B64661}.Debug|ARM64.Build.0 = Debug|ARM64 - {060D75DA-2D1C-48E6-A4A1-6F0718B64661}.Debug|x64.ActiveCfg = Debug|x64 - {060D75DA-2D1C-48E6-A4A1-6F0718B64661}.Debug|x64.Build.0 = Debug|x64 - {060D75DA-2D1C-48E6-A4A1-6F0718B64661}.Release|ARM64.ActiveCfg = Release|ARM64 - {060D75DA-2D1C-48E6-A4A1-6F0718B64661}.Release|ARM64.Build.0 = Release|ARM64 - {060D75DA-2D1C-48E6-A4A1-6F0718B64661}.Release|x64.ActiveCfg = Release|x64 - {060D75DA-2D1C-48E6-A4A1-6F0718B64661}.Release|x64.Build.0 = Release|x64 - {748417CA-F17E-487F-9411-CAFB6D3F4877}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {748417CA-F17E-487F-9411-CAFB6D3F4877}.Debug|ARM64.Build.0 = Debug|ARM64 - {748417CA-F17E-487F-9411-CAFB6D3F4877}.Debug|x64.ActiveCfg = Debug|x64 - {748417CA-F17E-487F-9411-CAFB6D3F4877}.Debug|x64.Build.0 = Debug|x64 - {748417CA-F17E-487F-9411-CAFB6D3F4877}.Release|ARM64.ActiveCfg = Release|ARM64 - {748417CA-F17E-487F-9411-CAFB6D3F4877}.Release|ARM64.Build.0 = Release|ARM64 - {748417CA-F17E-487F-9411-CAFB6D3F4877}.Release|x64.ActiveCfg = Release|x64 - {748417CA-F17E-487F-9411-CAFB6D3F4877}.Release|x64.Build.0 = Release|x64 - {217DF501-135C-4E38-BFC8-99D4821032EA}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {217DF501-135C-4E38-BFC8-99D4821032EA}.Debug|ARM64.Build.0 = Debug|ARM64 - {217DF501-135C-4E38-BFC8-99D4821032EA}.Debug|x64.ActiveCfg = Debug|x64 - {217DF501-135C-4E38-BFC8-99D4821032EA}.Debug|x64.Build.0 = Debug|x64 - {217DF501-135C-4E38-BFC8-99D4821032EA}.Release|ARM64.ActiveCfg = Release|ARM64 - {217DF501-135C-4E38-BFC8-99D4821032EA}.Release|ARM64.Build.0 = Release|ARM64 - {217DF501-135C-4E38-BFC8-99D4821032EA}.Release|x64.ActiveCfg = Release|x64 - {217DF501-135C-4E38-BFC8-99D4821032EA}.Release|x64.Build.0 = Release|x64 - {B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A}.Debug|ARM64.Build.0 = Debug|ARM64 - {B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A}.Debug|x64.ActiveCfg = Debug|x64 - {B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A}.Debug|x64.Build.0 = Debug|x64 - {B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A}.Release|ARM64.ActiveCfg = Release|ARM64 - {B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A}.Release|ARM64.Build.0 = Release|ARM64 - {B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A}.Release|x64.ActiveCfg = Release|x64 - {B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A}.Release|x64.Build.0 = Release|x64 - {787B8AA6-CA93-4C84-96FE-DF31110AD1C4}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {787B8AA6-CA93-4C84-96FE-DF31110AD1C4}.Debug|ARM64.Build.0 = Debug|ARM64 - {787B8AA6-CA93-4C84-96FE-DF31110AD1C4}.Debug|x64.ActiveCfg = Debug|x64 - {787B8AA6-CA93-4C84-96FE-DF31110AD1C4}.Debug|x64.Build.0 = Debug|x64 - {787B8AA6-CA93-4C84-96FE-DF31110AD1C4}.Release|ARM64.ActiveCfg = Release|ARM64 - {787B8AA6-CA93-4C84-96FE-DF31110AD1C4}.Release|ARM64.Build.0 = Release|ARM64 - {787B8AA6-CA93-4C84-96FE-DF31110AD1C4}.Release|x64.ActiveCfg = Release|x64 - {787B8AA6-CA93-4C84-96FE-DF31110AD1C4}.Release|x64.Build.0 = Release|x64 - {08C8C05F-0362-41BC-818C-724572DF8B06}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {08C8C05F-0362-41BC-818C-724572DF8B06}.Debug|ARM64.Build.0 = Debug|ARM64 - {08C8C05F-0362-41BC-818C-724572DF8B06}.Debug|x64.ActiveCfg = Debug|x64 - {08C8C05F-0362-41BC-818C-724572DF8B06}.Debug|x64.Build.0 = Debug|x64 - {08C8C05F-0362-41BC-818C-724572DF8B06}.Release|ARM64.ActiveCfg = Release|ARM64 - {08C8C05F-0362-41BC-818C-724572DF8B06}.Release|ARM64.Build.0 = Release|ARM64 - {08C8C05F-0362-41BC-818C-724572DF8B06}.Release|x64.ActiveCfg = Release|x64 - {08C8C05F-0362-41BC-818C-724572DF8B06}.Release|x64.Build.0 = Release|x64 - {5D00D290-4016-4CFE-9E41-1E7C724509BA}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {5D00D290-4016-4CFE-9E41-1E7C724509BA}.Debug|ARM64.Build.0 = Debug|ARM64 - {5D00D290-4016-4CFE-9E41-1E7C724509BA}.Debug|x64.ActiveCfg = Debug|x64 - {5D00D290-4016-4CFE-9E41-1E7C724509BA}.Debug|x64.Build.0 = Debug|x64 - {5D00D290-4016-4CFE-9E41-1E7C724509BA}.Release|ARM64.ActiveCfg = Release|ARM64 - {5D00D290-4016-4CFE-9E41-1E7C724509BA}.Release|ARM64.Build.0 = Release|ARM64 - {5D00D290-4016-4CFE-9E41-1E7C724509BA}.Release|x64.ActiveCfg = Release|x64 - {5D00D290-4016-4CFE-9E41-1E7C724509BA}.Release|x64.Build.0 = Release|x64 - {4AED67B6-55FD-486F-B917-E543DEE2CB3C}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {4AED67B6-55FD-486F-B917-E543DEE2CB3C}.Debug|ARM64.Build.0 = Debug|ARM64 - {4AED67B6-55FD-486F-B917-E543DEE2CB3C}.Debug|x64.ActiveCfg = Debug|x64 - {4AED67B6-55FD-486F-B917-E543DEE2CB3C}.Debug|x64.Build.0 = Debug|x64 - {4AED67B6-55FD-486F-B917-E543DEE2CB3C}.Release|ARM64.ActiveCfg = Release|ARM64 - {4AED67B6-55FD-486F-B917-E543DEE2CB3C}.Release|ARM64.Build.0 = Release|ARM64 - {4AED67B6-55FD-486F-B917-E543DEE2CB3C}.Release|x64.ActiveCfg = Release|x64 - {4AED67B6-55FD-486F-B917-E543DEE2CB3C}.Release|x64.Build.0 = Release|x64 - {42851751-CBC8-45A6-97F5-7A0753F7B4D1}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {42851751-CBC8-45A6-97F5-7A0753F7B4D1}.Debug|ARM64.Build.0 = Debug|ARM64 - {42851751-CBC8-45A6-97F5-7A0753F7B4D1}.Debug|x64.ActiveCfg = Debug|x64 - {42851751-CBC8-45A6-97F5-7A0753F7B4D1}.Debug|x64.Build.0 = Debug|x64 - {42851751-CBC8-45A6-97F5-7A0753F7B4D1}.Release|ARM64.ActiveCfg = Release|ARM64 - {42851751-CBC8-45A6-97F5-7A0753F7B4D1}.Release|ARM64.Build.0 = Release|ARM64 - {42851751-CBC8-45A6-97F5-7A0753F7B4D1}.Release|x64.ActiveCfg = Release|x64 - {42851751-CBC8-45A6-97F5-7A0753F7B4D1}.Release|x64.Build.0 = Release|x64 - {1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E}.Debug|ARM64.Build.0 = Debug|ARM64 - {1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E}.Debug|x64.ActiveCfg = Debug|x64 - {1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E}.Debug|x64.Build.0 = Debug|x64 - {1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E}.Release|ARM64.ActiveCfg = Release|ARM64 - {1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E}.Release|ARM64.Build.0 = Release|ARM64 - {1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E}.Release|x64.ActiveCfg = Release|x64 - {1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E}.Release|x64.Build.0 = Release|x64 - {8FFE09DA-FA4F-4EE1-B3A2-AD5497FBD1AD}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {8FFE09DA-FA4F-4EE1-B3A2-AD5497FBD1AD}.Debug|ARM64.Build.0 = Debug|ARM64 - {8FFE09DA-FA4F-4EE1-B3A2-AD5497FBD1AD}.Debug|x64.ActiveCfg = Debug|x64 - {8FFE09DA-FA4F-4EE1-B3A2-AD5497FBD1AD}.Debug|x64.Build.0 = Debug|x64 - {8FFE09DA-FA4F-4EE1-B3A2-AD5497FBD1AD}.Release|ARM64.ActiveCfg = Release|ARM64 - {8FFE09DA-FA4F-4EE1-B3A2-AD5497FBD1AD}.Release|ARM64.Build.0 = Release|ARM64 - {8FFE09DA-FA4F-4EE1-B3A2-AD5497FBD1AD}.Release|x64.ActiveCfg = Release|x64 - {8FFE09DA-FA4F-4EE1-B3A2-AD5497FBD1AD}.Release|x64.Build.0 = Release|x64 - {655C9AF2-18D3-4DA6-80E4-85504A7722BA}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {655C9AF2-18D3-4DA6-80E4-85504A7722BA}.Debug|ARM64.Build.0 = Debug|ARM64 - {655C9AF2-18D3-4DA6-80E4-85504A7722BA}.Debug|x64.ActiveCfg = Debug|x64 - {655C9AF2-18D3-4DA6-80E4-85504A7722BA}.Debug|x64.Build.0 = Debug|x64 - {655C9AF2-18D3-4DA6-80E4-85504A7722BA}.Release|ARM64.ActiveCfg = Release|ARM64 - {655C9AF2-18D3-4DA6-80E4-85504A7722BA}.Release|ARM64.Build.0 = Release|ARM64 - {655C9AF2-18D3-4DA6-80E4-85504A7722BA}.Release|x64.ActiveCfg = Release|x64 - {655C9AF2-18D3-4DA6-80E4-85504A7722BA}.Release|x64.Build.0 = Release|x64 - {BA58206B-1493-4C75-BFEA-A85768A1E156}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {BA58206B-1493-4C75-BFEA-A85768A1E156}.Debug|ARM64.Build.0 = Debug|ARM64 - {BA58206B-1493-4C75-BFEA-A85768A1E156}.Debug|x64.ActiveCfg = Debug|x64 - {BA58206B-1493-4C75-BFEA-A85768A1E156}.Debug|x64.Build.0 = Debug|x64 - {BA58206B-1493-4C75-BFEA-A85768A1E156}.Release|ARM64.ActiveCfg = Release|ARM64 - {BA58206B-1493-4C75-BFEA-A85768A1E156}.Release|ARM64.Build.0 = Release|ARM64 - {BA58206B-1493-4C75-BFEA-A85768A1E156}.Release|x64.ActiveCfg = Release|x64 - {BA58206B-1493-4C75-BFEA-A85768A1E156}.Release|x64.Build.0 = Release|x64 - {03276A39-D4E9-417C-8FFD-200B0EE5E871}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {03276A39-D4E9-417C-8FFD-200B0EE5E871}.Debug|ARM64.Build.0 = Debug|ARM64 - {03276A39-D4E9-417C-8FFD-200B0EE5E871}.Debug|x64.ActiveCfg = Debug|x64 - {03276A39-D4E9-417C-8FFD-200B0EE5E871}.Debug|x64.Build.0 = Debug|x64 - {03276A39-D4E9-417C-8FFD-200B0EE5E871}.Release|ARM64.ActiveCfg = Release|ARM64 - {03276A39-D4E9-417C-8FFD-200B0EE5E871}.Release|ARM64.Build.0 = Release|ARM64 - {03276A39-D4E9-417C-8FFD-200B0EE5E871}.Release|x64.ActiveCfg = Release|x64 - {03276A39-D4E9-417C-8FFD-200B0EE5E871}.Release|x64.Build.0 = Release|x64 - {B81FB7B6-D30E-428F-908A-41422EFC1172}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {B81FB7B6-D30E-428F-908A-41422EFC1172}.Debug|ARM64.Build.0 = Debug|ARM64 - {B81FB7B6-D30E-428F-908A-41422EFC1172}.Debug|x64.ActiveCfg = Debug|x64 - {B81FB7B6-D30E-428F-908A-41422EFC1172}.Debug|x64.Build.0 = Debug|x64 - {B81FB7B6-D30E-428F-908A-41422EFC1172}.Release|ARM64.ActiveCfg = Release|ARM64 - {B81FB7B6-D30E-428F-908A-41422EFC1172}.Release|ARM64.Build.0 = Release|ARM64 - {B81FB7B6-D30E-428F-908A-41422EFC1172}.Release|x64.ActiveCfg = Release|x64 - {B81FB7B6-D30E-428F-908A-41422EFC1172}.Release|x64.Build.0 = Release|x64 - {0F85E674-34AE-443D-954C-8321EB8B93B1}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {0F85E674-34AE-443D-954C-8321EB8B93B1}.Debug|ARM64.Build.0 = Debug|ARM64 - {0F85E674-34AE-443D-954C-8321EB8B93B1}.Debug|x64.ActiveCfg = Debug|x64 - {0F85E674-34AE-443D-954C-8321EB8B93B1}.Debug|x64.Build.0 = Debug|x64 - {0F85E674-34AE-443D-954C-8321EB8B93B1}.Release|ARM64.ActiveCfg = Release|ARM64 - {0F85E674-34AE-443D-954C-8321EB8B93B1}.Release|ARM64.Build.0 = Release|ARM64 - {0F85E674-34AE-443D-954C-8321EB8B93B1}.Release|x64.ActiveCfg = Release|x64 - {0F85E674-34AE-443D-954C-8321EB8B93B1}.Release|x64.Build.0 = Release|x64 - {632BBE62-5421-49EA-835A-7FFA4F499BD6}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {632BBE62-5421-49EA-835A-7FFA4F499BD6}.Debug|ARM64.Build.0 = Debug|ARM64 - {632BBE62-5421-49EA-835A-7FFA4F499BD6}.Debug|x64.ActiveCfg = Debug|x64 - {632BBE62-5421-49EA-835A-7FFA4F499BD6}.Debug|x64.Build.0 = Debug|x64 - {632BBE62-5421-49EA-835A-7FFA4F499BD6}.Release|ARM64.ActiveCfg = Release|ARM64 - {632BBE62-5421-49EA-835A-7FFA4F499BD6}.Release|ARM64.Build.0 = Release|ARM64 - {632BBE62-5421-49EA-835A-7FFA4F499BD6}.Release|x64.ActiveCfg = Release|x64 - {632BBE62-5421-49EA-835A-7FFA4F499BD6}.Release|x64.Build.0 = Release|x64 - {7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|ARM64.Build.0 = Debug|ARM64 - {7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|x64.ActiveCfg = Debug|x64 - {7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|x64.Build.0 = Debug|x64 - {7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|ARM64.ActiveCfg = Release|ARM64 - {7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|ARM64.Build.0 = Release|ARM64 - {7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|x64.ActiveCfg = Release|x64 - {7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|x64.Build.0 = Release|x64 - {FD8EB419-FF9C-4D88-BB6F-BF6CED37747B}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {FD8EB419-FF9C-4D88-BB6F-BF6CED37747B}.Debug|ARM64.Build.0 = Debug|ARM64 - {FD8EB419-FF9C-4D88-BB6F-BF6CED37747B}.Debug|x64.ActiveCfg = Debug|x64 - {FD8EB419-FF9C-4D88-BB6F-BF6CED37747B}.Debug|x64.Build.0 = Debug|x64 - {FD8EB419-FF9C-4D88-BB6F-BF6CED37747B}.Release|ARM64.ActiveCfg = Release|ARM64 - {FD8EB419-FF9C-4D88-BB6F-BF6CED37747B}.Release|ARM64.Build.0 = Release|ARM64 - {FD8EB419-FF9C-4D88-BB6F-BF6CED37747B}.Release|x64.ActiveCfg = Release|x64 - {FD8EB419-FF9C-4D88-BB6F-BF6CED37747B}.Release|x64.Build.0 = Release|x64 - {DA5A6FE9-0040-40CC-83CC-764AE5306590}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {DA5A6FE9-0040-40CC-83CC-764AE5306590}.Debug|ARM64.Build.0 = Debug|ARM64 - {DA5A6FE9-0040-40CC-83CC-764AE5306590}.Debug|x64.ActiveCfg = Debug|x64 - {DA5A6FE9-0040-40CC-83CC-764AE5306590}.Debug|x64.Build.0 = Debug|x64 - {DA5A6FE9-0040-40CC-83CC-764AE5306590}.Release|ARM64.ActiveCfg = Release|ARM64 - {DA5A6FE9-0040-40CC-83CC-764AE5306590}.Release|ARM64.Build.0 = Release|ARM64 - {DA5A6FE9-0040-40CC-83CC-764AE5306590}.Release|x64.ActiveCfg = Release|x64 - {DA5A6FE9-0040-40CC-83CC-764AE5306590}.Release|x64.Build.0 = Release|x64 - {0351ADA4-0C32-4652-9BA0-41F7B602372B}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {0351ADA4-0C32-4652-9BA0-41F7B602372B}.Debug|ARM64.Build.0 = Debug|ARM64 - {0351ADA4-0C32-4652-9BA0-41F7B602372B}.Debug|x64.ActiveCfg = Debug|x64 - {0351ADA4-0C32-4652-9BA0-41F7B602372B}.Debug|x64.Build.0 = Debug|x64 - {0351ADA4-0C32-4652-9BA0-41F7B602372B}.Release|ARM64.ActiveCfg = Release|ARM64 - {0351ADA4-0C32-4652-9BA0-41F7B602372B}.Release|ARM64.Build.0 = Release|ARM64 - {0351ADA4-0C32-4652-9BA0-41F7B602372B}.Release|x64.ActiveCfg = Release|x64 - {0351ADA4-0C32-4652-9BA0-41F7B602372B}.Release|x64.Build.0 = Release|x64 - {D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Debug|ARM64.Build.0 = Debug|ARM64 - {D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Debug|x64.ActiveCfg = Debug|x64 - {D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Debug|x64.Build.0 = Debug|x64 - {D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|ARM64.ActiveCfg = Release|ARM64 - {D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|ARM64.Build.0 = Release|ARM64 - {D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|x64.ActiveCfg = Release|x64 - {D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|x64.Build.0 = Release|x64 - {6955446D-23F7-4023-9BB3-8657F904AF99}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6955446D-23F7-4023-9BB3-8657F904AF99}.Debug|ARM64.Build.0 = Debug|ARM64 - {6955446D-23F7-4023-9BB3-8657F904AF99}.Debug|x64.ActiveCfg = Debug|x64 - {6955446D-23F7-4023-9BB3-8657F904AF99}.Debug|x64.Build.0 = Debug|x64 - {6955446D-23F7-4023-9BB3-8657F904AF99}.Release|ARM64.ActiveCfg = Release|ARM64 - {6955446D-23F7-4023-9BB3-8657F904AF99}.Release|ARM64.Build.0 = Release|ARM64 - {6955446D-23F7-4023-9BB3-8657F904AF99}.Release|x64.ActiveCfg = Release|x64 - {6955446D-23F7-4023-9BB3-8657F904AF99}.Release|x64.Build.0 = Release|x64 - {58736667-1027-4AD7-BFDF-7A3A6474103A}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {58736667-1027-4AD7-BFDF-7A3A6474103A}.Debug|ARM64.Build.0 = Debug|ARM64 - {58736667-1027-4AD7-BFDF-7A3A6474103A}.Debug|x64.ActiveCfg = Debug|x64 - {58736667-1027-4AD7-BFDF-7A3A6474103A}.Debug|x64.Build.0 = Debug|x64 - {58736667-1027-4AD7-BFDF-7A3A6474103A}.Release|ARM64.ActiveCfg = Release|ARM64 - {58736667-1027-4AD7-BFDF-7A3A6474103A}.Release|ARM64.Build.0 = Release|ARM64 - {58736667-1027-4AD7-BFDF-7A3A6474103A}.Release|x64.ActiveCfg = Release|x64 - {58736667-1027-4AD7-BFDF-7A3A6474103A}.Release|x64.Build.0 = Release|x64 - {1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}.Debug|ARM64.Build.0 = Debug|ARM64 - {1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}.Debug|x64.ActiveCfg = Debug|x64 - {1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}.Debug|x64.Build.0 = Debug|x64 - {1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}.Release|ARM64.ActiveCfg = Release|ARM64 - {1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}.Release|ARM64.Build.0 = Release|ARM64 - {1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}.Release|x64.ActiveCfg = Release|x64 - {1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}.Release|x64.Build.0 = Release|x64 - {031AC72E-FA28-4AB7-B690-6F7B9C28AA73}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {031AC72E-FA28-4AB7-B690-6F7B9C28AA73}.Debug|ARM64.Build.0 = Debug|ARM64 - {031AC72E-FA28-4AB7-B690-6F7B9C28AA73}.Debug|x64.ActiveCfg = Debug|x64 - {031AC72E-FA28-4AB7-B690-6F7B9C28AA73}.Debug|x64.Build.0 = Debug|x64 - {031AC72E-FA28-4AB7-B690-6F7B9C28AA73}.Release|ARM64.ActiveCfg = Release|ARM64 - {031AC72E-FA28-4AB7-B690-6F7B9C28AA73}.Release|ARM64.Build.0 = Release|ARM64 - {031AC72E-FA28-4AB7-B690-6F7B9C28AA73}.Release|x64.ActiveCfg = Release|x64 - {031AC72E-FA28-4AB7-B690-6F7B9C28AA73}.Release|x64.Build.0 = Release|x64 - {0B593A6C-4143-4337-860E-DB5710FB87DB}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {0B593A6C-4143-4337-860E-DB5710FB87DB}.Debug|ARM64.Build.0 = Debug|ARM64 - {0B593A6C-4143-4337-860E-DB5710FB87DB}.Debug|x64.ActiveCfg = Debug|x64 - {0B593A6C-4143-4337-860E-DB5710FB87DB}.Debug|x64.Build.0 = Debug|x64 - {0B593A6C-4143-4337-860E-DB5710FB87DB}.Release|ARM64.ActiveCfg = Release|ARM64 - {0B593A6C-4143-4337-860E-DB5710FB87DB}.Release|ARM64.Build.0 = Release|ARM64 - {0B593A6C-4143-4337-860E-DB5710FB87DB}.Release|x64.ActiveCfg = Release|x64 - {0B593A6C-4143-4337-860E-DB5710FB87DB}.Release|x64.Build.0 = Release|x64 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|ARM64.Build.0 = Debug|ARM64 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|x64.ActiveCfg = Debug|x64 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|x64.Build.0 = Debug|x64 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|ARM64.ActiveCfg = Release|ARM64 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|ARM64.Build.0 = Release|ARM64 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|x64.ActiveCfg = Release|x64 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|x64.Build.0 = Release|x64 - {7319089E-46D6-4400-BC65-E39BDF1416EE}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {7319089E-46D6-4400-BC65-E39BDF1416EE}.Debug|ARM64.Build.0 = Debug|ARM64 - {7319089E-46D6-4400-BC65-E39BDF1416EE}.Debug|x64.ActiveCfg = Debug|x64 - {7319089E-46D6-4400-BC65-E39BDF1416EE}.Debug|x64.Build.0 = Debug|x64 - {7319089E-46D6-4400-BC65-E39BDF1416EE}.Release|ARM64.ActiveCfg = Release|ARM64 - {7319089E-46D6-4400-BC65-E39BDF1416EE}.Release|ARM64.Build.0 = Release|ARM64 - {7319089E-46D6-4400-BC65-E39BDF1416EE}.Release|x64.ActiveCfg = Release|x64 - {7319089E-46D6-4400-BC65-E39BDF1416EE}.Release|x64.Build.0 = Release|x64 - {CABA8DFB-823B-4BF2-93AC-3F31984150D9}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {CABA8DFB-823B-4BF2-93AC-3F31984150D9}.Debug|ARM64.Build.0 = Debug|ARM64 - {CABA8DFB-823B-4BF2-93AC-3F31984150D9}.Debug|x64.ActiveCfg = Debug|x64 - {CABA8DFB-823B-4BF2-93AC-3F31984150D9}.Debug|x64.Build.0 = Debug|x64 - {CABA8DFB-823B-4BF2-93AC-3F31984150D9}.Release|ARM64.ActiveCfg = Release|ARM64 - {CABA8DFB-823B-4BF2-93AC-3F31984150D9}.Release|ARM64.Build.0 = Release|ARM64 - {CABA8DFB-823B-4BF2-93AC-3F31984150D9}.Release|x64.ActiveCfg = Release|x64 - {CABA8DFB-823B-4BF2-93AC-3F31984150D9}.Release|x64.Build.0 = Release|x64 - {98537082-0FDB-40DE-ABD8-0DC5A4269BAB}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {98537082-0FDB-40DE-ABD8-0DC5A4269BAB}.Debug|ARM64.Build.0 = Debug|ARM64 - {98537082-0FDB-40DE-ABD8-0DC5A4269BAB}.Debug|x64.ActiveCfg = Debug|x64 - {98537082-0FDB-40DE-ABD8-0DC5A4269BAB}.Debug|x64.Build.0 = Debug|x64 - {98537082-0FDB-40DE-ABD8-0DC5A4269BAB}.Release|ARM64.ActiveCfg = Release|ARM64 - {98537082-0FDB-40DE-ABD8-0DC5A4269BAB}.Release|ARM64.Build.0 = Release|ARM64 - {98537082-0FDB-40DE-ABD8-0DC5A4269BAB}.Release|x64.ActiveCfg = Release|x64 - {98537082-0FDB-40DE-ABD8-0DC5A4269BAB}.Release|x64.Build.0 = Release|x64 - {C3A17DCA-217B-462C-BB0C-BE086AF80081}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {C3A17DCA-217B-462C-BB0C-BE086AF80081}.Debug|ARM64.Build.0 = Debug|ARM64 - {C3A17DCA-217B-462C-BB0C-BE086AF80081}.Debug|x64.ActiveCfg = Debug|x64 - {C3A17DCA-217B-462C-BB0C-BE086AF80081}.Debug|x64.Build.0 = Debug|x64 - {C3A17DCA-217B-462C-BB0C-BE086AF80081}.Release|ARM64.ActiveCfg = Release|ARM64 - {C3A17DCA-217B-462C-BB0C-BE086AF80081}.Release|ARM64.Build.0 = Release|ARM64 - {C3A17DCA-217B-462C-BB0C-BE086AF80081}.Release|x64.ActiveCfg = Release|x64 - {C3A17DCA-217B-462C-BB0C-BE086AF80081}.Release|x64.Build.0 = Release|x64 - {69E1EE8D-143A-4060-9129-4658ACF14AAF}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {69E1EE8D-143A-4060-9129-4658ACF14AAF}.Debug|ARM64.Build.0 = Debug|ARM64 - {69E1EE8D-143A-4060-9129-4658ACF14AAF}.Debug|x64.ActiveCfg = Debug|x64 - {69E1EE8D-143A-4060-9129-4658ACF14AAF}.Debug|x64.Build.0 = Debug|x64 - {69E1EE8D-143A-4060-9129-4658ACF14AAF}.Release|ARM64.ActiveCfg = Release|ARM64 - {69E1EE8D-143A-4060-9129-4658ACF14AAF}.Release|ARM64.Build.0 = Release|ARM64 - {69E1EE8D-143A-4060-9129-4658ACF14AAF}.Release|x64.ActiveCfg = Release|x64 - {69E1EE8D-143A-4060-9129-4658ACF14AAF}.Release|x64.Build.0 = Release|x64 - {ECC20689-002A-4354-95A6-B58DF089C6FF}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {ECC20689-002A-4354-95A6-B58DF089C6FF}.Debug|ARM64.Build.0 = Debug|ARM64 - {ECC20689-002A-4354-95A6-B58DF089C6FF}.Debug|x64.ActiveCfg = Debug|x64 - {ECC20689-002A-4354-95A6-B58DF089C6FF}.Debug|x64.Build.0 = Debug|x64 - {ECC20689-002A-4354-95A6-B58DF089C6FF}.Release|ARM64.ActiveCfg = Release|ARM64 - {ECC20689-002A-4354-95A6-B58DF089C6FF}.Release|ARM64.Build.0 = Release|ARM64 - {ECC20689-002A-4354-95A6-B58DF089C6FF}.Release|x64.ActiveCfg = Release|x64 - {ECC20689-002A-4354-95A6-B58DF089C6FF}.Release|x64.Build.0 = Release|x64 - {4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Debug|ARM64.Build.0 = Debug|ARM64 - {4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Debug|x64.ActiveCfg = Debug|x64 - {4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Debug|x64.Build.0 = Debug|x64 - {4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Release|ARM64.ActiveCfg = Release|ARM64 - {4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Release|ARM64.Build.0 = Release|ARM64 - {4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Release|x64.ActiveCfg = Release|x64 - {4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Release|x64.Build.0 = Release|x64 - {0648DF05-5DDA-4BE1-B5F2-584926EBDB65}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {0648DF05-5DDA-4BE1-B5F2-584926EBDB65}.Debug|ARM64.Build.0 = Debug|ARM64 - {0648DF05-5DDA-4BE1-B5F2-584926EBDB65}.Debug|x64.ActiveCfg = Debug|x64 - {0648DF05-5DDA-4BE1-B5F2-584926EBDB65}.Debug|x64.Build.0 = Debug|x64 - {0648DF05-5DDA-4BE1-B5F2-584926EBDB65}.Release|ARM64.ActiveCfg = Release|ARM64 - {0648DF05-5DDA-4BE1-B5F2-584926EBDB65}.Release|ARM64.Build.0 = Release|ARM64 - {0648DF05-5DDA-4BE1-B5F2-584926EBDB65}.Release|x64.ActiveCfg = Release|x64 - {0648DF05-5DDA-4BE1-B5F2-584926EBDB65}.Release|x64.Build.0 = Release|x64 - {BA661F5B-1D5A-4FFC-9BF1-FC39DF280BDD}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {BA661F5B-1D5A-4FFC-9BF1-FC39DF280BDD}.Debug|ARM64.Build.0 = Debug|ARM64 - {BA661F5B-1D5A-4FFC-9BF1-FC39DF280BDD}.Debug|x64.ActiveCfg = Debug|x64 - {BA661F5B-1D5A-4FFC-9BF1-FC39DF280BDD}.Debug|x64.Build.0 = Debug|x64 - {BA661F5B-1D5A-4FFC-9BF1-FC39DF280BDD}.Release|ARM64.ActiveCfg = Release|ARM64 - {BA661F5B-1D5A-4FFC-9BF1-FC39DF280BDD}.Release|ARM64.Build.0 = Release|ARM64 - {BA661F5B-1D5A-4FFC-9BF1-FC39DF280BDD}.Release|x64.ActiveCfg = Release|x64 - {BA661F5B-1D5A-4FFC-9BF1-FC39DF280BDD}.Release|x64.Build.0 = Release|x64 - {E496B7FC-1E99-4BAB-849B-0E8367040B02}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {E496B7FC-1E99-4BAB-849B-0E8367040B02}.Debug|ARM64.Build.0 = Debug|ARM64 - {E496B7FC-1E99-4BAB-849B-0E8367040B02}.Debug|x64.ActiveCfg = Debug|x64 - {E496B7FC-1E99-4BAB-849B-0E8367040B02}.Debug|x64.Build.0 = Debug|x64 - {E496B7FC-1E99-4BAB-849B-0E8367040B02}.Release|ARM64.ActiveCfg = Release|ARM64 - {E496B7FC-1E99-4BAB-849B-0E8367040B02}.Release|ARM64.Build.0 = Release|ARM64 - {E496B7FC-1E99-4BAB-849B-0E8367040B02}.Release|x64.ActiveCfg = Release|x64 - {E496B7FC-1E99-4BAB-849B-0E8367040B02}.Release|x64.Build.0 = Release|x64 - {7F4B3A60-BC27-45A7-8000-68B0B6EA7466}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {7F4B3A60-BC27-45A7-8000-68B0B6EA7466}.Debug|ARM64.Build.0 = Debug|ARM64 - {7F4B3A60-BC27-45A7-8000-68B0B6EA7466}.Debug|x64.ActiveCfg = Debug|x64 - {7F4B3A60-BC27-45A7-8000-68B0B6EA7466}.Debug|x64.Build.0 = Debug|x64 - {7F4B3A60-BC27-45A7-8000-68B0B6EA7466}.Release|ARM64.ActiveCfg = Release|ARM64 - {7F4B3A60-BC27-45A7-8000-68B0B6EA7466}.Release|ARM64.Build.0 = Release|ARM64 - {7F4B3A60-BC27-45A7-8000-68B0B6EA7466}.Release|x64.ActiveCfg = Release|x64 - {7F4B3A60-BC27-45A7-8000-68B0B6EA7466}.Release|x64.Build.0 = Release|x64 - {8DF78B53-200E-451F-9328-01EB907193AE}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {8DF78B53-200E-451F-9328-01EB907193AE}.Debug|ARM64.Build.0 = Debug|ARM64 - {8DF78B53-200E-451F-9328-01EB907193AE}.Debug|x64.ActiveCfg = Debug|x64 - {8DF78B53-200E-451F-9328-01EB907193AE}.Debug|x64.Build.0 = Debug|x64 - {8DF78B53-200E-451F-9328-01EB907193AE}.Release|ARM64.ActiveCfg = Release|ARM64 - {8DF78B53-200E-451F-9328-01EB907193AE}.Release|ARM64.Build.0 = Release|ARM64 - {8DF78B53-200E-451F-9328-01EB907193AE}.Release|x64.ActiveCfg = Release|x64 - {8DF78B53-200E-451F-9328-01EB907193AE}.Release|x64.Build.0 = Release|x64 - {23D2070D-E4AD-4ADD-85A7-083D9C76AD49}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {23D2070D-E4AD-4ADD-85A7-083D9C76AD49}.Debug|ARM64.Build.0 = Debug|ARM64 - {23D2070D-E4AD-4ADD-85A7-083D9C76AD49}.Debug|x64.ActiveCfg = Debug|x64 - {23D2070D-E4AD-4ADD-85A7-083D9C76AD49}.Debug|x64.Build.0 = Debug|x64 - {23D2070D-E4AD-4ADD-85A7-083D9C76AD49}.Release|ARM64.ActiveCfg = Release|ARM64 - {23D2070D-E4AD-4ADD-85A7-083D9C76AD49}.Release|ARM64.Build.0 = Release|ARM64 - {23D2070D-E4AD-4ADD-85A7-083D9C76AD49}.Release|x64.ActiveCfg = Release|x64 - {23D2070D-E4AD-4ADD-85A7-083D9C76AD49}.Release|x64.Build.0 = Release|x64 - {62173D9A-6724-4C00-A1C8-FB646480A9EC}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {62173D9A-6724-4C00-A1C8-FB646480A9EC}.Debug|ARM64.Build.0 = Debug|ARM64 - {62173D9A-6724-4C00-A1C8-FB646480A9EC}.Debug|x64.ActiveCfg = Debug|x64 - {62173D9A-6724-4C00-A1C8-FB646480A9EC}.Debug|x64.Build.0 = Debug|x64 - {62173D9A-6724-4C00-A1C8-FB646480A9EC}.Release|ARM64.ActiveCfg = Release|ARM64 - {62173D9A-6724-4C00-A1C8-FB646480A9EC}.Release|ARM64.Build.0 = Release|ARM64 - {62173D9A-6724-4C00-A1C8-FB646480A9EC}.Release|x64.ActiveCfg = Release|x64 - {62173D9A-6724-4C00-A1C8-FB646480A9EC}.Release|x64.Build.0 = Release|x64 - {5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Debug|ARM64.Build.0 = Debug|ARM64 - {5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Debug|x64.ActiveCfg = Debug|x64 - {5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Debug|x64.Build.0 = Debug|x64 - {5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Release|ARM64.ActiveCfg = Release|ARM64 - {5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Release|ARM64.Build.0 = Release|ARM64 - {5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Release|x64.ActiveCfg = Release|x64 - {5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Release|x64.Build.0 = Release|x64 - {D940E07F-532C-4FF3-883F-790DA014F19A}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {D940E07F-532C-4FF3-883F-790DA014F19A}.Debug|ARM64.Build.0 = Debug|ARM64 - {D940E07F-532C-4FF3-883F-790DA014F19A}.Debug|x64.ActiveCfg = Debug|x64 - {D940E07F-532C-4FF3-883F-790DA014F19A}.Debug|x64.Build.0 = Debug|x64 - {D940E07F-532C-4FF3-883F-790DA014F19A}.Release|ARM64.ActiveCfg = Release|ARM64 - {D940E07F-532C-4FF3-883F-790DA014F19A}.Release|ARM64.Build.0 = Release|ARM64 - {D940E07F-532C-4FF3-883F-790DA014F19A}.Release|x64.ActiveCfg = Release|x64 - {D940E07F-532C-4FF3-883F-790DA014F19A}.Release|x64.Build.0 = Release|x64 - {BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}.Debug|ARM64.Build.0 = Debug|ARM64 - {BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}.Debug|x64.ActiveCfg = Debug|x64 - {BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}.Debug|x64.Build.0 = Debug|x64 - {BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}.Release|ARM64.ActiveCfg = Release|ARM64 - {BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}.Release|ARM64.Build.0 = Release|ARM64 - {BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}.Release|x64.ActiveCfg = Release|x64 - {BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}.Release|x64.Build.0 = Release|x64 - {3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Debug|ARM64.Build.0 = Debug|ARM64 - {3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Debug|x64.ActiveCfg = Debug|x64 - {3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Debug|x64.Build.0 = Debug|x64 - {3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Release|ARM64.ActiveCfg = Release|ARM64 - {3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Release|ARM64.Build.0 = Release|ARM64 - {3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Release|x64.ActiveCfg = Release|x64 - {3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Release|x64.Build.0 = Release|x64 - {2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Debug|ARM64.Build.0 = Debug|ARM64 - {2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Debug|x64.ActiveCfg = Debug|x64 - {2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Debug|x64.Build.0 = Debug|x64 - {2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Release|ARM64.ActiveCfg = Release|ARM64 - {2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Release|ARM64.Build.0 = Release|ARM64 - {2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Release|x64.ActiveCfg = Release|x64 - {2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Release|x64.Build.0 = Release|x64 - {2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Debug|ARM64.Build.0 = Debug|ARM64 - {2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Debug|x64.ActiveCfg = Debug|x64 - {2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Debug|x64.Build.0 = Debug|x64 - {2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Release|ARM64.ActiveCfg = Release|ARM64 - {2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Release|ARM64.Build.0 = Release|ARM64 - {2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Release|x64.ActiveCfg = Release|x64 - {2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Release|x64.Build.0 = Release|x64 - {48804216-2A0E-4168-A6D8-9CD068D14227}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {48804216-2A0E-4168-A6D8-9CD068D14227}.Debug|ARM64.Build.0 = Debug|ARM64 - {48804216-2A0E-4168-A6D8-9CD068D14227}.Debug|x64.ActiveCfg = Debug|x64 - {48804216-2A0E-4168-A6D8-9CD068D14227}.Debug|x64.Build.0 = Debug|x64 - {48804216-2A0E-4168-A6D8-9CD068D14227}.Release|ARM64.ActiveCfg = Release|ARM64 - {48804216-2A0E-4168-A6D8-9CD068D14227}.Release|ARM64.Build.0 = Release|ARM64 - {48804216-2A0E-4168-A6D8-9CD068D14227}.Release|x64.ActiveCfg = Release|x64 - {48804216-2A0E-4168-A6D8-9CD068D14227}.Release|x64.Build.0 = Release|x64 - {FF1D7936-842A-4BBB-8BEA-E9FE796DE700}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {FF1D7936-842A-4BBB-8BEA-E9FE796DE700}.Debug|ARM64.Build.0 = Debug|ARM64 - {FF1D7936-842A-4BBB-8BEA-E9FE796DE700}.Debug|x64.ActiveCfg = Debug|x64 - {FF1D7936-842A-4BBB-8BEA-E9FE796DE700}.Debug|x64.Build.0 = Debug|x64 - {FF1D7936-842A-4BBB-8BEA-E9FE796DE700}.Release|ARM64.ActiveCfg = Release|ARM64 - {FF1D7936-842A-4BBB-8BEA-E9FE796DE700}.Release|ARM64.Build.0 = Release|ARM64 - {FF1D7936-842A-4BBB-8BEA-E9FE796DE700}.Release|x64.ActiveCfg = Release|x64 - {FF1D7936-842A-4BBB-8BEA-E9FE796DE700}.Release|x64.Build.0 = Release|x64 - {44CE9AE1-4390-42C5-BACC-0FD6B40AA203}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {44CE9AE1-4390-42C5-BACC-0FD6B40AA203}.Debug|ARM64.Build.0 = Debug|ARM64 - {44CE9AE1-4390-42C5-BACC-0FD6B40AA203}.Debug|x64.ActiveCfg = Debug|x64 - {44CE9AE1-4390-42C5-BACC-0FD6B40AA203}.Debug|x64.Build.0 = Debug|x64 - {44CE9AE1-4390-42C5-BACC-0FD6B40AA203}.Release|ARM64.ActiveCfg = Release|ARM64 - {44CE9AE1-4390-42C5-BACC-0FD6B40AA203}.Release|ARM64.Build.0 = Release|ARM64 - {44CE9AE1-4390-42C5-BACC-0FD6B40AA203}.Release|x64.ActiveCfg = Release|x64 - {44CE9AE1-4390-42C5-BACC-0FD6B40AA203}.Release|x64.Build.0 = Release|x64 - {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Debug|ARM64.Build.0 = Debug|ARM64 - {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Debug|x64.ActiveCfg = Debug|x64 - {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Debug|x64.Build.0 = Debug|x64 - {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|ARM64.ActiveCfg = Release|ARM64 - {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|ARM64.Build.0 = Release|ARM64 - {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|x64.ActiveCfg = Release|x64 - {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|x64.Build.0 = Release|x64 - {11491FD8-F921-48BF-880C-7FEA185B80A1}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {11491FD8-F921-48BF-880C-7FEA185B80A1}.Debug|ARM64.Build.0 = Debug|ARM64 - {11491FD8-F921-48BF-880C-7FEA185B80A1}.Debug|x64.ActiveCfg = Debug|x64 - {11491FD8-F921-48BF-880C-7FEA185B80A1}.Debug|x64.Build.0 = Debug|x64 - {11491FD8-F921-48BF-880C-7FEA185B80A1}.Release|ARM64.ActiveCfg = Release|ARM64 - {11491FD8-F921-48BF-880C-7FEA185B80A1}.Release|ARM64.Build.0 = Release|ARM64 - {11491FD8-F921-48BF-880C-7FEA185B80A1}.Release|x64.ActiveCfg = Release|x64 - {11491FD8-F921-48BF-880C-7FEA185B80A1}.Release|x64.Build.0 = Release|x64 - {F40C3397-1834-4530-B2D9-8F8B8456BCDF}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {F40C3397-1834-4530-B2D9-8F8B8456BCDF}.Debug|ARM64.Build.0 = Debug|ARM64 - {F40C3397-1834-4530-B2D9-8F8B8456BCDF}.Debug|x64.ActiveCfg = Debug|x64 - {F40C3397-1834-4530-B2D9-8F8B8456BCDF}.Debug|x64.Build.0 = Debug|x64 - {F40C3397-1834-4530-B2D9-8F8B8456BCDF}.Release|ARM64.ActiveCfg = Release|ARM64 - {F40C3397-1834-4530-B2D9-8F8B8456BCDF}.Release|ARM64.Build.0 = Release|ARM64 - {F40C3397-1834-4530-B2D9-8F8B8456BCDF}.Release|x64.ActiveCfg = Release|x64 - {F40C3397-1834-4530-B2D9-8F8B8456BCDF}.Release|x64.Build.0 = Release|x64 - {A2D583F0-B70C-4462-B1F0-8E81AFB7BA85}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {A2D583F0-B70C-4462-B1F0-8E81AFB7BA85}.Debug|ARM64.Build.0 = Debug|ARM64 - {A2D583F0-B70C-4462-B1F0-8E81AFB7BA85}.Debug|x64.ActiveCfg = Debug|x64 - {A2D583F0-B70C-4462-B1F0-8E81AFB7BA85}.Debug|x64.Build.0 = Debug|x64 - {A2D583F0-B70C-4462-B1F0-8E81AFB7BA85}.Release|ARM64.ActiveCfg = Release|ARM64 - {A2D583F0-B70C-4462-B1F0-8E81AFB7BA85}.Release|ARM64.Build.0 = Release|ARM64 - {A2D583F0-B70C-4462-B1F0-8E81AFB7BA85}.Release|x64.ActiveCfg = Release|x64 - {A2D583F0-B70C-4462-B1F0-8E81AFB7BA85}.Release|x64.Build.0 = Release|x64 - {4ED320BC-BA04-4D42-8D15-CBE62151F08B}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {4ED320BC-BA04-4D42-8D15-CBE62151F08B}.Debug|ARM64.Build.0 = Debug|ARM64 - {4ED320BC-BA04-4D42-8D15-CBE62151F08B}.Debug|x64.ActiveCfg = Debug|x64 - {4ED320BC-BA04-4D42-8D15-CBE62151F08B}.Debug|x64.Build.0 = Debug|x64 - {4ED320BC-BA04-4D42-8D15-CBE62151F08B}.Release|ARM64.ActiveCfg = Release|ARM64 - {4ED320BC-BA04-4D42-8D15-CBE62151F08B}.Release|ARM64.Build.0 = Release|ARM64 - {4ED320BC-BA04-4D42-8D15-CBE62151F08B}.Release|x64.ActiveCfg = Release|x64 - {4ED320BC-BA04-4D42-8D15-CBE62151F08B}.Release|x64.Build.0 = Release|x64 - {E94FD11C-0591-456F-899F-EFC0CA548336}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {E94FD11C-0591-456F-899F-EFC0CA548336}.Debug|ARM64.Build.0 = Debug|ARM64 - {E94FD11C-0591-456F-899F-EFC0CA548336}.Debug|x64.ActiveCfg = Debug|x64 - {E94FD11C-0591-456F-899F-EFC0CA548336}.Debug|x64.Build.0 = Debug|x64 - {E94FD11C-0591-456F-899F-EFC0CA548336}.Release|ARM64.ActiveCfg = Release|ARM64 - {E94FD11C-0591-456F-899F-EFC0CA548336}.Release|ARM64.Build.0 = Release|ARM64 - {E94FD11C-0591-456F-899F-EFC0CA548336}.Release|x64.ActiveCfg = Release|x64 - {E94FD11C-0591-456F-899F-EFC0CA548336}.Release|x64.Build.0 = Release|x64 - {782A61BE-9D85-4081-B35C-1CCC9DCC1E88}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {782A61BE-9D85-4081-B35C-1CCC9DCC1E88}.Debug|ARM64.Build.0 = Debug|ARM64 - {782A61BE-9D85-4081-B35C-1CCC9DCC1E88}.Debug|x64.ActiveCfg = Debug|x64 - {782A61BE-9D85-4081-B35C-1CCC9DCC1E88}.Debug|x64.Build.0 = Debug|x64 - {782A61BE-9D85-4081-B35C-1CCC9DCC1E88}.Release|ARM64.ActiveCfg = Release|ARM64 - {782A61BE-9D85-4081-B35C-1CCC9DCC1E88}.Release|ARM64.Build.0 = Release|ARM64 - {782A61BE-9D85-4081-B35C-1CCC9DCC1E88}.Release|x64.ActiveCfg = Release|x64 - {782A61BE-9D85-4081-B35C-1CCC9DCC1E88}.Release|x64.Build.0 = Release|x64 - {809AA252-E17A-4FA2-B0A1-0450976B763F}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {809AA252-E17A-4FA2-B0A1-0450976B763F}.Debug|ARM64.Build.0 = Debug|ARM64 - {809AA252-E17A-4FA2-B0A1-0450976B763F}.Debug|x64.ActiveCfg = Debug|x64 - {809AA252-E17A-4FA2-B0A1-0450976B763F}.Debug|x64.Build.0 = Debug|x64 - {809AA252-E17A-4FA2-B0A1-0450976B763F}.Release|ARM64.ActiveCfg = Release|ARM64 - {809AA252-E17A-4FA2-B0A1-0450976B763F}.Release|ARM64.Build.0 = Release|ARM64 - {809AA252-E17A-4FA2-B0A1-0450976B763F}.Release|x64.ActiveCfg = Release|x64 - {809AA252-E17A-4FA2-B0A1-0450976B763F}.Release|x64.Build.0 = Release|x64 - {133281D8-1BCE-4D07-B31E-796612A9609E}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {133281D8-1BCE-4D07-B31E-796612A9609E}.Debug|ARM64.Build.0 = Debug|ARM64 - {133281D8-1BCE-4D07-B31E-796612A9609E}.Debug|x64.ActiveCfg = Debug|x64 - {133281D8-1BCE-4D07-B31E-796612A9609E}.Debug|x64.Build.0 = Debug|x64 - {133281D8-1BCE-4D07-B31E-796612A9609E}.Release|ARM64.ActiveCfg = Release|ARM64 - {133281D8-1BCE-4D07-B31E-796612A9609E}.Release|ARM64.Build.0 = Release|ARM64 - {133281D8-1BCE-4D07-B31E-796612A9609E}.Release|x64.ActiveCfg = Release|x64 - {133281D8-1BCE-4D07-B31E-796612A9609E}.Release|x64.Build.0 = Release|x64 - {805306FF-A562-4415-8DEF-E493BDC45918}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {805306FF-A562-4415-8DEF-E493BDC45918}.Debug|ARM64.Build.0 = Debug|ARM64 - {805306FF-A562-4415-8DEF-E493BDC45918}.Debug|x64.ActiveCfg = Debug|x64 - {805306FF-A562-4415-8DEF-E493BDC45918}.Debug|x64.Build.0 = Debug|x64 - {805306FF-A562-4415-8DEF-E493BDC45918}.Release|ARM64.ActiveCfg = Release|ARM64 - {805306FF-A562-4415-8DEF-E493BDC45918}.Release|ARM64.Build.0 = Release|ARM64 - {805306FF-A562-4415-8DEF-E493BDC45918}.Release|x64.ActiveCfg = Release|x64 - {805306FF-A562-4415-8DEF-E493BDC45918}.Release|x64.Build.0 = Release|x64 - {FCF3E52D-B80A-4FC3-98FD-6391354F0EE3}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {FCF3E52D-B80A-4FC3-98FD-6391354F0EE3}.Debug|ARM64.Build.0 = Debug|ARM64 - {FCF3E52D-B80A-4FC3-98FD-6391354F0EE3}.Debug|x64.ActiveCfg = Debug|x64 - {FCF3E52D-B80A-4FC3-98FD-6391354F0EE3}.Debug|x64.Build.0 = Debug|x64 - {FCF3E52D-B80A-4FC3-98FD-6391354F0EE3}.Release|ARM64.ActiveCfg = Release|ARM64 - {FCF3E52D-B80A-4FC3-98FD-6391354F0EE3}.Release|ARM64.Build.0 = Release|ARM64 - {FCF3E52D-B80A-4FC3-98FD-6391354F0EE3}.Release|x64.ActiveCfg = Release|x64 - {FCF3E52D-B80A-4FC3-98FD-6391354F0EE3}.Release|x64.Build.0 = Release|x64 - {1DC3BE92-CE89-43FB-8110-9C043A2FE7A2}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {1DC3BE92-CE89-43FB-8110-9C043A2FE7A2}.Debug|ARM64.Build.0 = Debug|ARM64 - {1DC3BE92-CE89-43FB-8110-9C043A2FE7A2}.Debug|x64.ActiveCfg = Debug|x64 - {1DC3BE92-CE89-43FB-8110-9C043A2FE7A2}.Debug|x64.Build.0 = Debug|x64 - {1DC3BE92-CE89-43FB-8110-9C043A2FE7A2}.Release|ARM64.ActiveCfg = Release|ARM64 - {1DC3BE92-CE89-43FB-8110-9C043A2FE7A2}.Release|ARM64.Build.0 = Release|ARM64 - {1DC3BE92-CE89-43FB-8110-9C043A2FE7A2}.Release|x64.ActiveCfg = Release|x64 - {1DC3BE92-CE89-43FB-8110-9C043A2FE7A2}.Release|x64.Build.0 = Release|x64 - {48A0A19E-A0BE-4256-ACF8-CC3B80291AF9}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {48A0A19E-A0BE-4256-ACF8-CC3B80291AF9}.Debug|ARM64.Build.0 = Debug|ARM64 - {48A0A19E-A0BE-4256-ACF8-CC3B80291AF9}.Debug|x64.ActiveCfg = Debug|x64 - {48A0A19E-A0BE-4256-ACF8-CC3B80291AF9}.Debug|x64.Build.0 = Debug|x64 - {48A0A19E-A0BE-4256-ACF8-CC3B80291AF9}.Release|ARM64.ActiveCfg = Release|ARM64 - {48A0A19E-A0BE-4256-ACF8-CC3B80291AF9}.Release|ARM64.Build.0 = Release|ARM64 - {48A0A19E-A0BE-4256-ACF8-CC3B80291AF9}.Release|x64.ActiveCfg = Release|x64 - {48A0A19E-A0BE-4256-ACF8-CC3B80291AF9}.Release|x64.Build.0 = Release|x64 - {9F94B303-5E21-4364-9362-64426F8DB932}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {9F94B303-5E21-4364-9362-64426F8DB932}.Debug|ARM64.Build.0 = Debug|ARM64 - {9F94B303-5E21-4364-9362-64426F8DB932}.Debug|x64.ActiveCfg = Debug|x64 - {9F94B303-5E21-4364-9362-64426F8DB932}.Debug|x64.Build.0 = Debug|x64 - {9F94B303-5E21-4364-9362-64426F8DB932}.Release|ARM64.ActiveCfg = Release|ARM64 - {9F94B303-5E21-4364-9362-64426F8DB932}.Release|ARM64.Build.0 = Release|ARM64 - {9F94B303-5E21-4364-9362-64426F8DB932}.Release|x64.ActiveCfg = Release|x64 - {9F94B303-5E21-4364-9362-64426F8DB932}.Release|x64.Build.0 = Release|x64 - {EAE14C0E-7A6B-45DA-9080-A7D8C077BA6E}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {EAE14C0E-7A6B-45DA-9080-A7D8C077BA6E}.Debug|ARM64.Build.0 = Debug|ARM64 - {EAE14C0E-7A6B-45DA-9080-A7D8C077BA6E}.Debug|x64.ActiveCfg = Debug|x64 - {EAE14C0E-7A6B-45DA-9080-A7D8C077BA6E}.Debug|x64.Build.0 = Debug|x64 - {EAE14C0E-7A6B-45DA-9080-A7D8C077BA6E}.Release|ARM64.ActiveCfg = Release|ARM64 - {EAE14C0E-7A6B-45DA-9080-A7D8C077BA6E}.Release|ARM64.Build.0 = Release|ARM64 - {EAE14C0E-7A6B-45DA-9080-A7D8C077BA6E}.Release|x64.ActiveCfg = Release|x64 - {EAE14C0E-7A6B-45DA-9080-A7D8C077BA6E}.Release|x64.Build.0 = Release|x64 - {F7C8C0F1-5431-4347-89D0-8E5354F93CF2}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {F7C8C0F1-5431-4347-89D0-8E5354F93CF2}.Debug|ARM64.Build.0 = Debug|ARM64 - {F7C8C0F1-5431-4347-89D0-8E5354F93CF2}.Debug|x64.ActiveCfg = Debug|x64 - {F7C8C0F1-5431-4347-89D0-8E5354F93CF2}.Debug|x64.Build.0 = Debug|x64 - {F7C8C0F1-5431-4347-89D0-8E5354F93CF2}.Release|ARM64.ActiveCfg = Release|ARM64 - {F7C8C0F1-5431-4347-89D0-8E5354F93CF2}.Release|ARM64.Build.0 = Release|ARM64 - {F7C8C0F1-5431-4347-89D0-8E5354F93CF2}.Release|x64.ActiveCfg = Release|x64 - {F7C8C0F1-5431-4347-89D0-8E5354F93CF2}.Release|x64.Build.0 = Release|x64 - {F1F6B6B6-9F18-4A17-8B5C-97DF552C53DC}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {F1F6B6B6-9F18-4A17-8B5C-97DF552C53DC}.Debug|ARM64.Build.0 = Debug|ARM64 - {F1F6B6B6-9F18-4A17-8B5C-97DF552C53DC}.Debug|x64.ActiveCfg = Debug|x64 - {F1F6B6B6-9F18-4A17-8B5C-97DF552C53DC}.Debug|x64.Build.0 = Debug|x64 - {F1F6B6B6-9F18-4A17-8B5C-97DF552C53DC}.Release|ARM64.ActiveCfg = Release|ARM64 - {F1F6B6B6-9F18-4A17-8B5C-97DF552C53DC}.Release|ARM64.Build.0 = Release|ARM64 - {F1F6B6B6-9F18-4A17-8B5C-97DF552C53DC}.Release|x64.ActiveCfg = Release|x64 - {F1F6B6B6-9F18-4A17-8B5C-97DF552C53DC}.Release|x64.Build.0 = Release|x64 - {04B193D7-3E21-46B8-A958-89B63A8A69DE}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {04B193D7-3E21-46B8-A958-89B63A8A69DE}.Debug|ARM64.Build.0 = Debug|ARM64 - {04B193D7-3E21-46B8-A958-89B63A8A69DE}.Debug|x64.ActiveCfg = Debug|x64 - {04B193D7-3E21-46B8-A958-89B63A8A69DE}.Debug|x64.Build.0 = Debug|x64 - {04B193D7-3E21-46B8-A958-89B63A8A69DE}.Release|ARM64.ActiveCfg = Release|ARM64 - {04B193D7-3E21-46B8-A958-89B63A8A69DE}.Release|ARM64.Build.0 = Release|ARM64 - {04B193D7-3E21-46B8-A958-89B63A8A69DE}.Release|x64.ActiveCfg = Release|x64 - {04B193D7-3E21-46B8-A958-89B63A8A69DE}.Release|x64.Build.0 = Release|x64 - {5BDBD6C9-A31F-4CEB-871A-5E9E709197EF}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {5BDBD6C9-A31F-4CEB-871A-5E9E709197EF}.Debug|ARM64.Build.0 = Debug|ARM64 - {5BDBD6C9-A31F-4CEB-871A-5E9E709197EF}.Debug|x64.ActiveCfg = Debug|x64 - {5BDBD6C9-A31F-4CEB-871A-5E9E709197EF}.Debug|x64.Build.0 = Debug|x64 - {5BDBD6C9-A31F-4CEB-871A-5E9E709197EF}.Release|ARM64.ActiveCfg = Release|ARM64 - {5BDBD6C9-A31F-4CEB-871A-5E9E709197EF}.Release|ARM64.Build.0 = Release|ARM64 - {5BDBD6C9-A31F-4CEB-871A-5E9E709197EF}.Release|x64.ActiveCfg = Release|x64 - {5BDBD6C9-A31F-4CEB-871A-5E9E709197EF}.Release|x64.Build.0 = Release|x64 - {FD464B4C-2F68-4D06-91E7-4208146C41F5}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {FD464B4C-2F68-4D06-91E7-4208146C41F5}.Debug|ARM64.Build.0 = Debug|ARM64 - {FD464B4C-2F68-4D06-91E7-4208146C41F5}.Debug|x64.ActiveCfg = Debug|x64 - {FD464B4C-2F68-4D06-91E7-4208146C41F5}.Debug|x64.Build.0 = Debug|x64 - {FD464B4C-2F68-4D06-91E7-4208146C41F5}.Release|ARM64.ActiveCfg = Release|ARM64 - {FD464B4C-2F68-4D06-91E7-4208146C41F5}.Release|ARM64.Build.0 = Release|ARM64 - {FD464B4C-2F68-4D06-91E7-4208146C41F5}.Release|x64.ActiveCfg = Release|x64 - {FD464B4C-2F68-4D06-91E7-4208146C41F5}.Release|x64.Build.0 = Release|x64 - {8FE5A5EE-1B59-401C-9FB3-B04ECD3E29C1}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {8FE5A5EE-1B59-401C-9FB3-B04ECD3E29C1}.Debug|ARM64.Build.0 = Debug|ARM64 - {8FE5A5EE-1B59-401C-9FB3-B04ECD3E29C1}.Debug|x64.ActiveCfg = Debug|x64 - {8FE5A5EE-1B59-401C-9FB3-B04ECD3E29C1}.Debug|x64.Build.0 = Debug|x64 - {8FE5A5EE-1B59-401C-9FB3-B04ECD3E29C1}.Release|ARM64.ActiveCfg = Release|ARM64 - {8FE5A5EE-1B59-401C-9FB3-B04ECD3E29C1}.Release|ARM64.Build.0 = Release|ARM64 - {8FE5A5EE-1B59-401C-9FB3-B04ECD3E29C1}.Release|x64.ActiveCfg = Release|x64 - {8FE5A5EE-1B59-401C-9FB3-B04ECD3E29C1}.Release|x64.Build.0 = Release|x64 - {020A7474-3601-4160-A159-D7B70B77B15F}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {020A7474-3601-4160-A159-D7B70B77B15F}.Debug|ARM64.Build.0 = Debug|ARM64 - {020A7474-3601-4160-A159-D7B70B77B15F}.Debug|x64.ActiveCfg = Debug|x64 - {020A7474-3601-4160-A159-D7B70B77B15F}.Debug|x64.Build.0 = Debug|x64 - {020A7474-3601-4160-A159-D7B70B77B15F}.Release|ARM64.ActiveCfg = Release|ARM64 - {020A7474-3601-4160-A159-D7B70B77B15F}.Release|ARM64.Build.0 = Release|ARM64 - {020A7474-3601-4160-A159-D7B70B77B15F}.Release|x64.ActiveCfg = Release|x64 - {020A7474-3601-4160-A159-D7B70B77B15F}.Release|x64.Build.0 = Release|x64 - {27718999-C175-450A-861C-89F911E16A88}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {27718999-C175-450A-861C-89F911E16A88}.Debug|ARM64.Build.0 = Debug|ARM64 - {27718999-C175-450A-861C-89F911E16A88}.Debug|x64.ActiveCfg = Debug|x64 - {27718999-C175-450A-861C-89F911E16A88}.Debug|x64.Build.0 = Debug|x64 - {27718999-C175-450A-861C-89F911E16A88}.Release|ARM64.ActiveCfg = Release|ARM64 - {27718999-C175-450A-861C-89F911E16A88}.Release|ARM64.Build.0 = Release|ARM64 - {27718999-C175-450A-861C-89F911E16A88}.Release|x64.ActiveCfg = Release|x64 - {27718999-C175-450A-861C-89F911E16A88}.Release|x64.Build.0 = Release|x64 - {1DBBB112-4BB1-444B-8EBB-E66555C76BA6}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {1DBBB112-4BB1-444B-8EBB-E66555C76BA6}.Debug|ARM64.Build.0 = Debug|ARM64 - {1DBBB112-4BB1-444B-8EBB-E66555C76BA6}.Debug|x64.ActiveCfg = Debug|x64 - {1DBBB112-4BB1-444B-8EBB-E66555C76BA6}.Debug|x64.Build.0 = Debug|x64 - {1DBBB112-4BB1-444B-8EBB-E66555C76BA6}.Release|ARM64.ActiveCfg = Release|ARM64 - {1DBBB112-4BB1-444B-8EBB-E66555C76BA6}.Release|ARM64.Build.0 = Release|ARM64 - {1DBBB112-4BB1-444B-8EBB-E66555C76BA6}.Release|x64.ActiveCfg = Release|x64 - {1DBBB112-4BB1-444B-8EBB-E66555C76BA6}.Release|x64.Build.0 = Release|x64 - {5A1DB2F0-0715-4B3B-98E6-79BC41540045}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {5A1DB2F0-0715-4B3B-98E6-79BC41540045}.Debug|ARM64.Build.0 = Debug|ARM64 - {5A1DB2F0-0715-4B3B-98E6-79BC41540045}.Debug|x64.ActiveCfg = Debug|x64 - {5A1DB2F0-0715-4B3B-98E6-79BC41540045}.Debug|x64.Build.0 = Debug|x64 - {5A1DB2F0-0715-4B3B-98E6-79BC41540045}.Release|ARM64.ActiveCfg = Release|ARM64 - {5A1DB2F0-0715-4B3B-98E6-79BC41540045}.Release|ARM64.Build.0 = Release|ARM64 - {5A1DB2F0-0715-4B3B-98E6-79BC41540045}.Release|x64.ActiveCfg = Release|x64 - {5A1DB2F0-0715-4B3B-98E6-79BC41540045}.Release|x64.Build.0 = Release|x64 - {93B72A06-C8BD-484F-A6F7-C9F280B150BF}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {93B72A06-C8BD-484F-A6F7-C9F280B150BF}.Debug|ARM64.Build.0 = Debug|ARM64 - {93B72A06-C8BD-484F-A6F7-C9F280B150BF}.Debug|x64.ActiveCfg = Debug|x64 - {93B72A06-C8BD-484F-A6F7-C9F280B150BF}.Debug|x64.Build.0 = Debug|x64 - {93B72A06-C8BD-484F-A6F7-C9F280B150BF}.Release|ARM64.ActiveCfg = Release|ARM64 - {93B72A06-C8BD-484F-A6F7-C9F280B150BF}.Release|ARM64.Build.0 = Release|ARM64 - {93B72A06-C8BD-484F-A6F7-C9F280B150BF}.Release|x64.ActiveCfg = Release|x64 - {93B72A06-C8BD-484F-A6F7-C9F280B150BF}.Release|x64.Build.0 = Release|x64 - {18B3DB45-4FFE-4D01-97D6-5223FEEE1853}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {18B3DB45-4FFE-4D01-97D6-5223FEEE1853}.Debug|ARM64.Build.0 = Debug|ARM64 - {18B3DB45-4FFE-4D01-97D6-5223FEEE1853}.Debug|x64.ActiveCfg = Debug|x64 - {18B3DB45-4FFE-4D01-97D6-5223FEEE1853}.Debug|x64.Build.0 = Debug|x64 - {18B3DB45-4FFE-4D01-97D6-5223FEEE1853}.Release|ARM64.ActiveCfg = Release|ARM64 - {18B3DB45-4FFE-4D01-97D6-5223FEEE1853}.Release|ARM64.Build.0 = Release|ARM64 - {18B3DB45-4FFE-4D01-97D6-5223FEEE1853}.Release|x64.ActiveCfg = Release|x64 - {18B3DB45-4FFE-4D01-97D6-5223FEEE1853}.Release|x64.Build.0 = Release|x64 - {34A354C5-23C7-4343-916C-C52DAF4FC39D}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {34A354C5-23C7-4343-916C-C52DAF4FC39D}.Debug|ARM64.Build.0 = Debug|ARM64 - {34A354C5-23C7-4343-916C-C52DAF4FC39D}.Debug|x64.ActiveCfg = Debug|x64 - {34A354C5-23C7-4343-916C-C52DAF4FC39D}.Debug|x64.Build.0 = Debug|x64 - {34A354C5-23C7-4343-916C-C52DAF4FC39D}.Release|ARM64.ActiveCfg = Release|ARM64 - {34A354C5-23C7-4343-916C-C52DAF4FC39D}.Release|ARM64.Build.0 = Release|ARM64 - {34A354C5-23C7-4343-916C-C52DAF4FC39D}.Release|x64.ActiveCfg = Release|x64 - {34A354C5-23C7-4343-916C-C52DAF4FC39D}.Release|x64.Build.0 = Release|x64 - {3264DF53-C805-4B0C-867C-FCEAF7AEF762}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {3264DF53-C805-4B0C-867C-FCEAF7AEF762}.Debug|ARM64.Build.0 = Debug|ARM64 - {3264DF53-C805-4B0C-867C-FCEAF7AEF762}.Debug|x64.ActiveCfg = Debug|x64 - {3264DF53-C805-4B0C-867C-FCEAF7AEF762}.Debug|x64.Build.0 = Debug|x64 - {3264DF53-C805-4B0C-867C-FCEAF7AEF762}.Release|ARM64.ActiveCfg = Release|ARM64 - {3264DF53-C805-4B0C-867C-FCEAF7AEF762}.Release|ARM64.Build.0 = Release|ARM64 - {3264DF53-C805-4B0C-867C-FCEAF7AEF762}.Release|x64.ActiveCfg = Release|x64 - {3264DF53-C805-4B0C-867C-FCEAF7AEF762}.Release|x64.Build.0 = Release|x64 - {31CAD28E-778A-441C-85BC-40AB3EAA2A10}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {31CAD28E-778A-441C-85BC-40AB3EAA2A10}.Debug|ARM64.Build.0 = Debug|ARM64 - {31CAD28E-778A-441C-85BC-40AB3EAA2A10}.Debug|x64.ActiveCfg = Debug|x64 - {31CAD28E-778A-441C-85BC-40AB3EAA2A10}.Debug|x64.Build.0 = Debug|x64 - {31CAD28E-778A-441C-85BC-40AB3EAA2A10}.Release|ARM64.ActiveCfg = Release|ARM64 - {31CAD28E-778A-441C-85BC-40AB3EAA2A10}.Release|ARM64.Build.0 = Release|ARM64 - {31CAD28E-778A-441C-85BC-40AB3EAA2A10}.Release|x64.ActiveCfg = Release|x64 - {31CAD28E-778A-441C-85BC-40AB3EAA2A10}.Release|x64.Build.0 = Release|x64 - {25C91A4E-BA4E-467A-85CD-8B62545BF674}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {25C91A4E-BA4E-467A-85CD-8B62545BF674}.Debug|ARM64.Build.0 = Debug|ARM64 - {25C91A4E-BA4E-467A-85CD-8B62545BF674}.Debug|x64.ActiveCfg = Debug|x64 - {25C91A4E-BA4E-467A-85CD-8B62545BF674}.Debug|x64.Build.0 = Debug|x64 - {25C91A4E-BA4E-467A-85CD-8B62545BF674}.Release|ARM64.ActiveCfg = Release|ARM64 - {25C91A4E-BA4E-467A-85CD-8B62545BF674}.Release|ARM64.Build.0 = Release|ARM64 - {25C91A4E-BA4E-467A-85CD-8B62545BF674}.Release|x64.ActiveCfg = Release|x64 - {25C91A4E-BA4E-467A-85CD-8B62545BF674}.Release|x64.Build.0 = Release|x64 - {6AB6A2D6-F859-4A82-9184-0BD29C9F07D1}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6AB6A2D6-F859-4A82-9184-0BD29C9F07D1}.Debug|ARM64.Build.0 = Debug|ARM64 - {6AB6A2D6-F859-4A82-9184-0BD29C9F07D1}.Debug|x64.ActiveCfg = Debug|x64 - {6AB6A2D6-F859-4A82-9184-0BD29C9F07D1}.Debug|x64.Build.0 = Debug|x64 - {6AB6A2D6-F859-4A82-9184-0BD29C9F07D1}.Release|ARM64.ActiveCfg = Release|ARM64 - {6AB6A2D6-F859-4A82-9184-0BD29C9F07D1}.Release|ARM64.Build.0 = Release|ARM64 - {6AB6A2D6-F859-4A82-9184-0BD29C9F07D1}.Release|x64.ActiveCfg = Release|x64 - {6AB6A2D6-F859-4A82-9184-0BD29C9F07D1}.Release|x64.Build.0 = Release|x64 - {212AD910-8488-4036-BE20-326931B75FB2}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {212AD910-8488-4036-BE20-326931B75FB2}.Debug|ARM64.Build.0 = Debug|ARM64 - {212AD910-8488-4036-BE20-326931B75FB2}.Debug|x64.ActiveCfg = Debug|x64 - {212AD910-8488-4036-BE20-326931B75FB2}.Debug|x64.Build.0 = Debug|x64 - {212AD910-8488-4036-BE20-326931B75FB2}.Release|ARM64.ActiveCfg = Release|ARM64 - {212AD910-8488-4036-BE20-326931B75FB2}.Release|ARM64.Build.0 = Release|ARM64 - {212AD910-8488-4036-BE20-326931B75FB2}.Release|x64.ActiveCfg = Release|x64 - {212AD910-8488-4036-BE20-326931B75FB2}.Release|x64.Build.0 = Release|x64 - {54A93AF7-60C7-4F6C-99D2-FBB1F75F853A}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {54A93AF7-60C7-4F6C-99D2-FBB1F75F853A}.Debug|ARM64.Build.0 = Debug|ARM64 - {54A93AF7-60C7-4F6C-99D2-FBB1F75F853A}.Debug|x64.ActiveCfg = Debug|x64 - {54A93AF7-60C7-4F6C-99D2-FBB1F75F853A}.Debug|x64.Build.0 = Debug|x64 - {54A93AF7-60C7-4F6C-99D2-FBB1F75F853A}.Release|ARM64.ActiveCfg = Release|ARM64 - {54A93AF7-60C7-4F6C-99D2-FBB1F75F853A}.Release|ARM64.Build.0 = Release|ARM64 - {54A93AF7-60C7-4F6C-99D2-FBB1F75F853A}.Release|x64.ActiveCfg = Release|x64 - {54A93AF7-60C7-4F6C-99D2-FBB1F75F853A}.Release|x64.Build.0 = Release|x64 - {92C39820-9F84-4529-BC7D-22AAE514D63B}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {92C39820-9F84-4529-BC7D-22AAE514D63B}.Debug|ARM64.Build.0 = Debug|ARM64 - {92C39820-9F84-4529-BC7D-22AAE514D63B}.Debug|x64.ActiveCfg = Debug|x64 - {92C39820-9F84-4529-BC7D-22AAE514D63B}.Debug|x64.Build.0 = Debug|x64 - {92C39820-9F84-4529-BC7D-22AAE514D63B}.Release|ARM64.ActiveCfg = Release|ARM64 - {92C39820-9F84-4529-BC7D-22AAE514D63B}.Release|ARM64.Build.0 = Release|ARM64 - {92C39820-9F84-4529-BC7D-22AAE514D63B}.Release|x64.ActiveCfg = Release|x64 - {92C39820-9F84-4529-BC7D-22AAE514D63B}.Release|x64.Build.0 = Release|x64 - {515554D1-D004-4F7F-A107-2211FC0F6B2C}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {515554D1-D004-4F7F-A107-2211FC0F6B2C}.Debug|ARM64.Build.0 = Debug|ARM64 - {515554D1-D004-4F7F-A107-2211FC0F6B2C}.Debug|x64.ActiveCfg = Debug|x64 - {515554D1-D004-4F7F-A107-2211FC0F6B2C}.Debug|x64.Build.0 = Debug|x64 - {515554D1-D004-4F7F-A107-2211FC0F6B2C}.Release|ARM64.ActiveCfg = Release|ARM64 - {515554D1-D004-4F7F-A107-2211FC0F6B2C}.Release|ARM64.Build.0 = Release|ARM64 - {515554D1-D004-4F7F-A107-2211FC0F6B2C}.Release|x64.ActiveCfg = Release|x64 - {515554D1-D004-4F7F-A107-2211FC0F6B2C}.Release|x64.Build.0 = Release|x64 - {C97D9A5D-206C-454E-997E-009E227D7F02}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {C97D9A5D-206C-454E-997E-009E227D7F02}.Debug|ARM64.Build.0 = Debug|ARM64 - {C97D9A5D-206C-454E-997E-009E227D7F02}.Debug|x64.ActiveCfg = Debug|x64 - {C97D9A5D-206C-454E-997E-009E227D7F02}.Debug|x64.Build.0 = Debug|x64 - {C97D9A5D-206C-454E-997E-009E227D7F02}.Release|ARM64.ActiveCfg = Release|ARM64 - {C97D9A5D-206C-454E-997E-009E227D7F02}.Release|ARM64.Build.0 = Release|ARM64 - {C97D9A5D-206C-454E-997E-009E227D7F02}.Release|x64.ActiveCfg = Release|x64 - {C97D9A5D-206C-454E-997E-009E227D7F02}.Release|x64.Build.0 = Release|x64 - {31D1C81D-765F-4446-AA62-E743F6325049}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {31D1C81D-765F-4446-AA62-E743F6325049}.Debug|ARM64.Build.0 = Debug|Any CPU - {31D1C81D-765F-4446-AA62-E743F6325049}.Debug|x64.ActiveCfg = Debug|Any CPU - {31D1C81D-765F-4446-AA62-E743F6325049}.Debug|x64.Build.0 = Debug|Any CPU - {31D1C81D-765F-4446-AA62-E743F6325049}.Release|ARM64.ActiveCfg = Release|Any CPU - {31D1C81D-765F-4446-AA62-E743F6325049}.Release|ARM64.Build.0 = Release|Any CPU - {31D1C81D-765F-4446-AA62-E743F6325049}.Release|x64.ActiveCfg = Release|Any CPU - {31D1C81D-765F-4446-AA62-E743F6325049}.Release|x64.Build.0 = Release|Any CPU - {E2D03E0F-7A75-4813-9F4B-D8763D43FD3A}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {E2D03E0F-7A75-4813-9F4B-D8763D43FD3A}.Debug|ARM64.Build.0 = Debug|ARM64 - {E2D03E0F-7A75-4813-9F4B-D8763D43FD3A}.Debug|x64.ActiveCfg = Debug|x64 - {E2D03E0F-7A75-4813-9F4B-D8763D43FD3A}.Debug|x64.Build.0 = Debug|x64 - {E2D03E0F-7A75-4813-9F4B-D8763D43FD3A}.Release|ARM64.ActiveCfg = Release|ARM64 - {E2D03E0F-7A75-4813-9F4B-D8763D43FD3A}.Release|ARM64.Build.0 = Release|ARM64 - {E2D03E0F-7A75-4813-9F4B-D8763D43FD3A}.Release|x64.ActiveCfg = Release|x64 - {E2D03E0F-7A75-4813-9F4B-D8763D43FD3A}.Release|x64.Build.0 = Release|x64 - {B41B888C-7DB8-4747-B262-4062E05A230D}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {B41B888C-7DB8-4747-B262-4062E05A230D}.Debug|ARM64.Build.0 = Debug|ARM64 - {B41B888C-7DB8-4747-B262-4062E05A230D}.Debug|x64.ActiveCfg = Debug|x64 - {B41B888C-7DB8-4747-B262-4062E05A230D}.Debug|x64.Build.0 = Debug|x64 - {B41B888C-7DB8-4747-B262-4062E05A230D}.Release|ARM64.ActiveCfg = Release|ARM64 - {B41B888C-7DB8-4747-B262-4062E05A230D}.Release|ARM64.Build.0 = Release|ARM64 - {B41B888C-7DB8-4747-B262-4062E05A230D}.Release|x64.ActiveCfg = Release|x64 - {B41B888C-7DB8-4747-B262-4062E05A230D}.Release|x64.Build.0 = Release|x64 - {57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}.Debug|ARM64.Build.0 = Debug|ARM64 - {57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}.Debug|x64.ActiveCfg = Debug|x64 - {57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}.Debug|x64.Build.0 = Debug|x64 - {57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}.Release|ARM64.ActiveCfg = Release|ARM64 - {57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}.Release|ARM64.Build.0 = Release|ARM64 - {57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}.Release|x64.ActiveCfg = Release|x64 - {57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}.Release|x64.Build.0 = Release|x64 - {E69B044A-2F8A-45AA-AD0B-256C59421807}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {E69B044A-2F8A-45AA-AD0B-256C59421807}.Debug|ARM64.Build.0 = Debug|ARM64 - {E69B044A-2F8A-45AA-AD0B-256C59421807}.Debug|x64.ActiveCfg = Debug|x64 - {E69B044A-2F8A-45AA-AD0B-256C59421807}.Debug|x64.Build.0 = Debug|x64 - {E69B044A-2F8A-45AA-AD0B-256C59421807}.Release|ARM64.ActiveCfg = Release|ARM64 - {E69B044A-2F8A-45AA-AD0B-256C59421807}.Release|ARM64.Build.0 = Release|ARM64 - {E69B044A-2F8A-45AA-AD0B-256C59421807}.Release|x64.ActiveCfg = Release|x64 - {E69B044A-2F8A-45AA-AD0B-256C59421807}.Release|x64.Build.0 = Release|x64 - {C604B37E-9D0E-4484-8778-E8B31B0E1B3A}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {C604B37E-9D0E-4484-8778-E8B31B0E1B3A}.Debug|ARM64.Build.0 = Debug|ARM64 - {C604B37E-9D0E-4484-8778-E8B31B0E1B3A}.Debug|x64.ActiveCfg = Debug|x64 - {C604B37E-9D0E-4484-8778-E8B31B0E1B3A}.Debug|x64.Build.0 = Debug|x64 - {C604B37E-9D0E-4484-8778-E8B31B0E1B3A}.Release|ARM64.ActiveCfg = Release|ARM64 - {C604B37E-9D0E-4484-8778-E8B31B0E1B3A}.Release|ARM64.Build.0 = Release|ARM64 - {C604B37E-9D0E-4484-8778-E8B31B0E1B3A}.Release|x64.ActiveCfg = Release|x64 - {C604B37E-9D0E-4484-8778-E8B31B0E1B3A}.Release|x64.Build.0 = Release|x64 - {E599C30B-9DC8-4E5A-BF27-93D4CCEDE788}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {E599C30B-9DC8-4E5A-BF27-93D4CCEDE788}.Debug|ARM64.Build.0 = Debug|ARM64 - {E599C30B-9DC8-4E5A-BF27-93D4CCEDE788}.Debug|x64.ActiveCfg = Debug|x64 - {E599C30B-9DC8-4E5A-BF27-93D4CCEDE788}.Debug|x64.Build.0 = Debug|x64 - {E599C30B-9DC8-4E5A-BF27-93D4CCEDE788}.Release|ARM64.ActiveCfg = Release|ARM64 - {E599C30B-9DC8-4E5A-BF27-93D4CCEDE788}.Release|ARM64.Build.0 = Release|ARM64 - {E599C30B-9DC8-4E5A-BF27-93D4CCEDE788}.Release|x64.ActiveCfg = Release|x64 - {E599C30B-9DC8-4E5A-BF27-93D4CCEDE788}.Release|x64.Build.0 = Release|x64 - {00EE9BA6-4E8F-43CA-960D-D4882F0FBB97}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {00EE9BA6-4E8F-43CA-960D-D4882F0FBB97}.Debug|ARM64.Build.0 = Debug|ARM64 - {00EE9BA6-4E8F-43CA-960D-D4882F0FBB97}.Debug|x64.ActiveCfg = Debug|x64 - {00EE9BA6-4E8F-43CA-960D-D4882F0FBB97}.Debug|x64.Build.0 = Debug|x64 - {00EE9BA6-4E8F-43CA-960D-D4882F0FBB97}.Release|ARM64.ActiveCfg = Release|ARM64 - {00EE9BA6-4E8F-43CA-960D-D4882F0FBB97}.Release|ARM64.Build.0 = Release|ARM64 - {00EE9BA6-4E8F-43CA-960D-D4882F0FBB97}.Release|x64.ActiveCfg = Release|x64 - {00EE9BA6-4E8F-43CA-960D-D4882F0FBB97}.Release|x64.Build.0 = Release|x64 - {A1425B53-3D61-4679-8623-E64A0D3D0A48}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {A1425B53-3D61-4679-8623-E64A0D3D0A48}.Debug|ARM64.Build.0 = Debug|ARM64 - {A1425B53-3D61-4679-8623-E64A0D3D0A48}.Debug|x64.ActiveCfg = Debug|x64 - {A1425B53-3D61-4679-8623-E64A0D3D0A48}.Debug|x64.Build.0 = Debug|x64 - {A1425B53-3D61-4679-8623-E64A0D3D0A48}.Release|ARM64.ActiveCfg = Release|ARM64 - {A1425B53-3D61-4679-8623-E64A0D3D0A48}.Release|ARM64.Build.0 = Release|ARM64 - {A1425B53-3D61-4679-8623-E64A0D3D0A48}.Release|x64.ActiveCfg = Release|x64 - {A1425B53-3D61-4679-8623-E64A0D3D0A48}.Release|x64.Build.0 = Release|x64 - {9D7A6DE0-7D27-424D-ABAE-41B2161F9A03}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {9D7A6DE0-7D27-424D-ABAE-41B2161F9A03}.Debug|ARM64.Build.0 = Debug|ARM64 - {9D7A6DE0-7D27-424D-ABAE-41B2161F9A03}.Debug|ARM64.Deploy.0 = Debug|ARM64 - {9D7A6DE0-7D27-424D-ABAE-41B2161F9A03}.Debug|x64.ActiveCfg = Debug|x64 - {9D7A6DE0-7D27-424D-ABAE-41B2161F9A03}.Debug|x64.Build.0 = Debug|x64 - {9D7A6DE0-7D27-424D-ABAE-41B2161F9A03}.Debug|x64.Deploy.0 = Debug|x64 - {9D7A6DE0-7D27-424D-ABAE-41B2161F9A03}.Release|ARM64.ActiveCfg = Release|ARM64 - {9D7A6DE0-7D27-424D-ABAE-41B2161F9A03}.Release|ARM64.Build.0 = Release|ARM64 - {9D7A6DE0-7D27-424D-ABAE-41B2161F9A03}.Release|ARM64.Deploy.0 = Release|ARM64 - {9D7A6DE0-7D27-424D-ABAE-41B2161F9A03}.Release|x64.ActiveCfg = Release|x64 - {9D7A6DE0-7D27-424D-ABAE-41B2161F9A03}.Release|x64.Build.0 = Release|x64 - {9D7A6DE0-7D27-424D-ABAE-41B2161F9A03}.Release|x64.Deploy.0 = Release|x64 - {17A99C7C-0BFF-45BB-A9FD-63A0DDC105BB}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {17A99C7C-0BFF-45BB-A9FD-63A0DDC105BB}.Debug|ARM64.Build.0 = Debug|ARM64 - {17A99C7C-0BFF-45BB-A9FD-63A0DDC105BB}.Debug|x64.ActiveCfg = Debug|x64 - {17A99C7C-0BFF-45BB-A9FD-63A0DDC105BB}.Debug|x64.Build.0 = Debug|x64 - {17A99C7C-0BFF-45BB-A9FD-63A0DDC105BB}.Release|ARM64.ActiveCfg = Release|ARM64 - {17A99C7C-0BFF-45BB-A9FD-63A0DDC105BB}.Release|ARM64.Build.0 = Release|ARM64 - {17A99C7C-0BFF-45BB-A9FD-63A0DDC105BB}.Release|x64.ActiveCfg = Release|x64 - {17A99C7C-0BFF-45BB-A9FD-63A0DDC105BB}.Release|x64.Build.0 = Release|x64 - {AA9F0AF8-7924-4D59-BAA1-E36F1304E0DC}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {AA9F0AF8-7924-4D59-BAA1-E36F1304E0DC}.Debug|ARM64.Build.0 = Debug|ARM64 - {AA9F0AF8-7924-4D59-BAA1-E36F1304E0DC}.Debug|x64.ActiveCfg = Debug|x64 - {AA9F0AF8-7924-4D59-BAA1-E36F1304E0DC}.Debug|x64.Build.0 = Debug|x64 - {AA9F0AF8-7924-4D59-BAA1-E36F1304E0DC}.Release|ARM64.ActiveCfg = Release|ARM64 - {AA9F0AF8-7924-4D59-BAA1-E36F1304E0DC}.Release|ARM64.Build.0 = Release|ARM64 - {AA9F0AF8-7924-4D59-BAA1-E36F1304E0DC}.Release|x64.ActiveCfg = Release|x64 - {AA9F0AF8-7924-4D59-BAA1-E36F1304E0DC}.Release|x64.Build.0 = Release|x64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A5}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A5}.Debug|ARM64.Build.0 = Debug|ARM64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A5}.Debug|x64.ActiveCfg = Debug|x64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A5}.Debug|x64.Build.0 = Debug|x64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A5}.Release|ARM64.ActiveCfg = Release|ARM64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A5}.Release|ARM64.Build.0 = Release|ARM64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A5}.Release|x64.ActiveCfg = Release|x64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A5}.Release|x64.Build.0 = Release|x64 - {ED9A1AC6-AEB0-4569-A6E9-E1696182B545}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {ED9A1AC6-AEB0-4569-A6E9-E1696182B545}.Debug|ARM64.Build.0 = Debug|ARM64 - {ED9A1AC6-AEB0-4569-A6E9-E1696182B545}.Debug|x64.ActiveCfg = Debug|x64 - {ED9A1AC6-AEB0-4569-A6E9-E1696182B545}.Debug|x64.Build.0 = Debug|x64 - {ED9A1AC6-AEB0-4569-A6E9-E1696182B545}.Release|ARM64.ActiveCfg = Release|ARM64 - {ED9A1AC6-AEB0-4569-A6E9-E1696182B545}.Release|ARM64.Build.0 = Release|ARM64 - {ED9A1AC6-AEB0-4569-A6E9-E1696182B545}.Release|x64.ActiveCfg = Release|x64 - {ED9A1AC6-AEB0-4569-A6E9-E1696182B545}.Release|x64.Build.0 = Release|x64 - {5A5DD09D-723A-44D3-8F2B-293584C3D731}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {5A5DD09D-723A-44D3-8F2B-293584C3D731}.Debug|ARM64.Build.0 = Debug|ARM64 - {5A5DD09D-723A-44D3-8F2B-293584C3D731}.Debug|x64.ActiveCfg = Debug|x64 - {5A5DD09D-723A-44D3-8F2B-293584C3D731}.Debug|x64.Build.0 = Debug|x64 - {5A5DD09D-723A-44D3-8F2B-293584C3D731}.Release|ARM64.ActiveCfg = Release|ARM64 - {5A5DD09D-723A-44D3-8F2B-293584C3D731}.Release|ARM64.Build.0 = Release|ARM64 - {5A5DD09D-723A-44D3-8F2B-293584C3D731}.Release|x64.ActiveCfg = Release|x64 - {5A5DD09D-723A-44D3-8F2B-293584C3D731}.Release|x64.Build.0 = Release|x64 - {B3E869C4-8210-4EBD-A621-FF4C4AFCBFA9}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {B3E869C4-8210-4EBD-A621-FF4C4AFCBFA9}.Debug|ARM64.Build.0 = Debug|ARM64 - {B3E869C4-8210-4EBD-A621-FF4C4AFCBFA9}.Debug|x64.ActiveCfg = Debug|x64 - {B3E869C4-8210-4EBD-A621-FF4C4AFCBFA9}.Debug|x64.Build.0 = Debug|x64 - {B3E869C4-8210-4EBD-A621-FF4C4AFCBFA9}.Release|ARM64.ActiveCfg = Release|ARM64 - {B3E869C4-8210-4EBD-A621-FF4C4AFCBFA9}.Release|ARM64.Build.0 = Release|ARM64 - {B3E869C4-8210-4EBD-A621-FF4C4AFCBFA9}.Release|x64.ActiveCfg = Release|x64 - {B3E869C4-8210-4EBD-A621-FF4C4AFCBFA9}.Release|x64.Build.0 = Release|x64 - {54F7C616-FD41-4E62-BFF9-015686914F4D}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {54F7C616-FD41-4E62-BFF9-015686914F4D}.Debug|ARM64.Build.0 = Debug|ARM64 - {54F7C616-FD41-4E62-BFF9-015686914F4D}.Debug|x64.ActiveCfg = Debug|x64 - {54F7C616-FD41-4E62-BFF9-015686914F4D}.Debug|x64.Build.0 = Debug|x64 - {54F7C616-FD41-4E62-BFF9-015686914F4D}.Release|ARM64.ActiveCfg = Release|ARM64 - {54F7C616-FD41-4E62-BFF9-015686914F4D}.Release|ARM64.Build.0 = Release|ARM64 - {54F7C616-FD41-4E62-BFF9-015686914F4D}.Release|x64.ActiveCfg = Release|x64 - {54F7C616-FD41-4E62-BFF9-015686914F4D}.Release|x64.Build.0 = Release|x64 - {143F13E3-D2E3-4D83-B035-356612D99956}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {143F13E3-D2E3-4D83-B035-356612D99956}.Debug|ARM64.Build.0 = Debug|ARM64 - {143F13E3-D2E3-4D83-B035-356612D99956}.Debug|x64.ActiveCfg = Debug|x64 - {143F13E3-D2E3-4D83-B035-356612D99956}.Debug|x64.Build.0 = Debug|x64 - {143F13E3-D2E3-4D83-B035-356612D99956}.Release|ARM64.ActiveCfg = Release|ARM64 - {143F13E3-D2E3-4D83-B035-356612D99956}.Release|ARM64.Build.0 = Release|ARM64 - {143F13E3-D2E3-4D83-B035-356612D99956}.Release|x64.ActiveCfg = Release|x64 - {143F13E3-D2E3-4D83-B035-356612D99956}.Release|x64.Build.0 = Release|x64 - {56CC2F10-6E41-453D-BE16-C593A5E58482}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {56CC2F10-6E41-453D-BE16-C593A5E58482}.Debug|ARM64.Build.0 = Debug|ARM64 - {56CC2F10-6E41-453D-BE16-C593A5E58482}.Debug|x64.ActiveCfg = Debug|x64 - {56CC2F10-6E41-453D-BE16-C593A5E58482}.Debug|x64.Build.0 = Debug|x64 - {56CC2F10-6E41-453D-BE16-C593A5E58482}.Release|ARM64.ActiveCfg = Release|ARM64 - {56CC2F10-6E41-453D-BE16-C593A5E58482}.Release|ARM64.Build.0 = Release|ARM64 - {56CC2F10-6E41-453D-BE16-C593A5E58482}.Release|x64.ActiveCfg = Release|x64 - {56CC2F10-6E41-453D-BE16-C593A5E58482}.Release|x64.Build.0 = Release|x64 - {CA5518ED-0458-4B09-8F53-4122B9888655}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {CA5518ED-0458-4B09-8F53-4122B9888655}.Debug|ARM64.Build.0 = Debug|ARM64 - {CA5518ED-0458-4B09-8F53-4122B9888655}.Debug|x64.ActiveCfg = Debug|x64 - {CA5518ED-0458-4B09-8F53-4122B9888655}.Debug|x64.Build.0 = Debug|x64 - {CA5518ED-0458-4B09-8F53-4122B9888655}.Release|ARM64.ActiveCfg = Release|ARM64 - {CA5518ED-0458-4B09-8F53-4122B9888655}.Release|ARM64.Build.0 = Release|ARM64 - {CA5518ED-0458-4B09-8F53-4122B9888655}.Release|x64.ActiveCfg = Release|x64 - {CA5518ED-0458-4B09-8F53-4122B9888655}.Release|x64.Build.0 = Release|x64 - {D6DCC3AE-18C0-488A-B978-BAA9E3CFF09D}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {D6DCC3AE-18C0-488A-B978-BAA9E3CFF09D}.Debug|ARM64.Build.0 = Debug|ARM64 - {D6DCC3AE-18C0-488A-B978-BAA9E3CFF09D}.Debug|x64.ActiveCfg = Debug|x64 - {D6DCC3AE-18C0-488A-B978-BAA9E3CFF09D}.Debug|x64.Build.0 = Debug|x64 - {D6DCC3AE-18C0-488A-B978-BAA9E3CFF09D}.Release|ARM64.ActiveCfg = Release|ARM64 - {D6DCC3AE-18C0-488A-B978-BAA9E3CFF09D}.Release|ARM64.Build.0 = Release|ARM64 - {D6DCC3AE-18C0-488A-B978-BAA9E3CFF09D}.Release|x64.ActiveCfg = Release|x64 - {D6DCC3AE-18C0-488A-B978-BAA9E3CFF09D}.Release|x64.Build.0 = Release|x64 - {2BBC9E33-21EC-401C-84DA-BB6590A9B2AA}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {2BBC9E33-21EC-401C-84DA-BB6590A9B2AA}.Debug|ARM64.Build.0 = Debug|ARM64 - {2BBC9E33-21EC-401C-84DA-BB6590A9B2AA}.Debug|x64.ActiveCfg = Debug|x64 - {2BBC9E33-21EC-401C-84DA-BB6590A9B2AA}.Debug|x64.Build.0 = Debug|x64 - {2BBC9E33-21EC-401C-84DA-BB6590A9B2AA}.Release|ARM64.ActiveCfg = Release|ARM64 - {2BBC9E33-21EC-401C-84DA-BB6590A9B2AA}.Release|ARM64.Build.0 = Release|ARM64 - {2BBC9E33-21EC-401C-84DA-BB6590A9B2AA}.Release|x64.ActiveCfg = Release|x64 - {2BBC9E33-21EC-401C-84DA-BB6590A9B2AA}.Release|x64.Build.0 = Release|x64 - {2833C9C6-AB32-4048-A5C7-A70898337B57}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {2833C9C6-AB32-4048-A5C7-A70898337B57}.Debug|ARM64.Build.0 = Debug|ARM64 - {2833C9C6-AB32-4048-A5C7-A70898337B57}.Debug|x64.ActiveCfg = Debug|x64 - {2833C9C6-AB32-4048-A5C7-A70898337B57}.Debug|x64.Build.0 = Debug|x64 - {2833C9C6-AB32-4048-A5C7-A70898337B57}.Release|ARM64.ActiveCfg = Release|ARM64 - {2833C9C6-AB32-4048-A5C7-A70898337B57}.Release|ARM64.Build.0 = Release|ARM64 - {2833C9C6-AB32-4048-A5C7-A70898337B57}.Release|x64.ActiveCfg = Release|x64 - {2833C9C6-AB32-4048-A5C7-A70898337B57}.Release|x64.Build.0 = Release|x64 - {50B82783-242F-42D2-BC03-B3430BF01354}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {50B82783-242F-42D2-BC03-B3430BF01354}.Debug|ARM64.Build.0 = Debug|ARM64 - {50B82783-242F-42D2-BC03-B3430BF01354}.Debug|x64.ActiveCfg = Debug|x64 - {50B82783-242F-42D2-BC03-B3430BF01354}.Debug|x64.Build.0 = Debug|x64 - {50B82783-242F-42D2-BC03-B3430BF01354}.Release|ARM64.ActiveCfg = Release|ARM64 - {50B82783-242F-42D2-BC03-B3430BF01354}.Release|ARM64.Build.0 = Release|ARM64 - {50B82783-242F-42D2-BC03-B3430BF01354}.Release|x64.ActiveCfg = Release|x64 - {50B82783-242F-42D2-BC03-B3430BF01354}.Release|x64.Build.0 = Release|x64 - {B5EB9FE9-37EF-47C3-B8B8-81AD3C2972C2}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {B5EB9FE9-37EF-47C3-B8B8-81AD3C2972C2}.Debug|ARM64.Build.0 = Debug|ARM64 - {B5EB9FE9-37EF-47C3-B8B8-81AD3C2972C2}.Debug|x64.ActiveCfg = Debug|x64 - {B5EB9FE9-37EF-47C3-B8B8-81AD3C2972C2}.Debug|x64.Build.0 = Debug|x64 - {B5EB9FE9-37EF-47C3-B8B8-81AD3C2972C2}.Release|ARM64.ActiveCfg = Release|ARM64 - {B5EB9FE9-37EF-47C3-B8B8-81AD3C2972C2}.Release|ARM64.Build.0 = Release|ARM64 - {B5EB9FE9-37EF-47C3-B8B8-81AD3C2972C2}.Release|x64.ActiveCfg = Release|x64 - {B5EB9FE9-37EF-47C3-B8B8-81AD3C2972C2}.Release|x64.Build.0 = Release|x64 - {A663E672-B26D-4EC0-BEAB-FE2E424AC46F}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {A663E672-B26D-4EC0-BEAB-FE2E424AC46F}.Debug|ARM64.Build.0 = Debug|ARM64 - {A663E672-B26D-4EC0-BEAB-FE2E424AC46F}.Debug|x64.ActiveCfg = Debug|x64 - {A663E672-B26D-4EC0-BEAB-FE2E424AC46F}.Debug|x64.Build.0 = Debug|x64 - {A663E672-B26D-4EC0-BEAB-FE2E424AC46F}.Release|ARM64.ActiveCfg = Release|ARM64 - {A663E672-B26D-4EC0-BEAB-FE2E424AC46F}.Release|ARM64.Build.0 = Release|ARM64 - {A663E672-B26D-4EC0-BEAB-FE2E424AC46F}.Release|x64.ActiveCfg = Release|x64 - {A663E672-B26D-4EC0-BEAB-FE2E424AC46F}.Release|x64.Build.0 = Release|x64 - {8A08D663-4995-40E3-B42C-3F910625F284}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {8A08D663-4995-40E3-B42C-3F910625F284}.Debug|ARM64.Build.0 = Debug|ARM64 - {8A08D663-4995-40E3-B42C-3F910625F284}.Debug|x64.ActiveCfg = Debug|x64 - {8A08D663-4995-40E3-B42C-3F910625F284}.Debug|x64.Build.0 = Debug|x64 - {8A08D663-4995-40E3-B42C-3F910625F284}.Release|ARM64.ActiveCfg = Release|ARM64 - {8A08D663-4995-40E3-B42C-3F910625F284}.Release|ARM64.Build.0 = Release|ARM64 - {8A08D663-4995-40E3-B42C-3F910625F284}.Release|x64.ActiveCfg = Release|x64 - {8A08D663-4995-40E3-B42C-3F910625F284}.Release|x64.Build.0 = Release|x64 - {923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Debug|ARM64.Build.0 = Debug|ARM64 - {923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Debug|x64.ActiveCfg = Debug|x64 - {923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Debug|x64.Build.0 = Debug|x64 - {923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Release|ARM64.ActiveCfg = Release|ARM64 - {923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Release|ARM64.Build.0 = Release|ARM64 - {923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Release|x64.ActiveCfg = Release|x64 - {923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Release|x64.Build.0 = Release|x64 - {D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Debug|ARM64.Build.0 = Debug|ARM64 - {D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Debug|x64.ActiveCfg = Debug|x64 - {D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Debug|x64.Build.0 = Debug|x64 - {D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Release|ARM64.ActiveCfg = Release|ARM64 - {D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Release|ARM64.Build.0 = Release|ARM64 - {D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Release|x64.ActiveCfg = Release|x64 - {D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Release|x64.Build.0 = Release|x64 - {D962A009-834F-4EEC-AABB-430DF8F98E39}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {D962A009-834F-4EEC-AABB-430DF8F98E39}.Debug|ARM64.Build.0 = Debug|ARM64 - {D962A009-834F-4EEC-AABB-430DF8F98E39}.Debug|x64.ActiveCfg = Debug|x64 - {D962A009-834F-4EEC-AABB-430DF8F98E39}.Debug|x64.Build.0 = Debug|x64 - {D962A009-834F-4EEC-AABB-430DF8F98E39}.Release|ARM64.ActiveCfg = Release|ARM64 - {D962A009-834F-4EEC-AABB-430DF8F98E39}.Release|ARM64.Build.0 = Release|ARM64 - {D962A009-834F-4EEC-AABB-430DF8F98E39}.Release|x64.ActiveCfg = Release|x64 - {D962A009-834F-4EEC-AABB-430DF8F98E39}.Release|x64.Build.0 = Release|x64 - {FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Debug|ARM64.Build.0 = Debug|ARM64 - {FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Debug|x64.ActiveCfg = Debug|x64 - {FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Debug|x64.Build.0 = Debug|x64 - {FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Release|ARM64.ActiveCfg = Release|ARM64 - {FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Release|ARM64.Build.0 = Release|ARM64 - {FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Release|x64.ActiveCfg = Release|x64 - {FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Release|x64.Build.0 = Release|x64 - {9CE59ED5-7087-4353-88EB-788038A73CEC}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {9CE59ED5-7087-4353-88EB-788038A73CEC}.Debug|ARM64.Build.0 = Debug|ARM64 - {9CE59ED5-7087-4353-88EB-788038A73CEC}.Debug|x64.ActiveCfg = Debug|x64 - {9CE59ED5-7087-4353-88EB-788038A73CEC}.Debug|x64.Build.0 = Debug|x64 - {9CE59ED5-7087-4353-88EB-788038A73CEC}.Release|ARM64.ActiveCfg = Release|ARM64 - {9CE59ED5-7087-4353-88EB-788038A73CEC}.Release|ARM64.Build.0 = Release|ARM64 - {9CE59ED5-7087-4353-88EB-788038A73CEC}.Release|x64.ActiveCfg = Release|x64 - {9CE59ED5-7087-4353-88EB-788038A73CEC}.Release|x64.Build.0 = Release|x64 - {FD86C06A-FB54-4D5E-9831-1CDADF60D45F}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {FD86C06A-FB54-4D5E-9831-1CDADF60D45F}.Debug|ARM64.Build.0 = Debug|Any CPU - {FD86C06A-FB54-4D5E-9831-1CDADF60D45F}.Debug|x64.ActiveCfg = Debug|Any CPU - {FD86C06A-FB54-4D5E-9831-1CDADF60D45F}.Debug|x64.Build.0 = Debug|Any CPU - {FD86C06A-FB54-4D5E-9831-1CDADF60D45F}.Release|ARM64.ActiveCfg = Release|Any CPU - {FD86C06A-FB54-4D5E-9831-1CDADF60D45F}.Release|ARM64.Build.0 = Release|Any CPU - {FD86C06A-FB54-4D5E-9831-1CDADF60D45F}.Release|x64.ActiveCfg = Release|Any CPU - {FD86C06A-FB54-4D5E-9831-1CDADF60D45F}.Release|x64.Build.0 = Release|Any CPU - {697C6AF9-0A48-49A9-866C-67DA12384015}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {697C6AF9-0A48-49A9-866C-67DA12384015}.Debug|ARM64.Build.0 = Debug|ARM64 - {697C6AF9-0A48-49A9-866C-67DA12384015}.Debug|x64.ActiveCfg = Debug|x64 - {697C6AF9-0A48-49A9-866C-67DA12384015}.Debug|x64.Build.0 = Debug|x64 - {697C6AF9-0A48-49A9-866C-67DA12384015}.Release|ARM64.ActiveCfg = Release|ARM64 - {697C6AF9-0A48-49A9-866C-67DA12384015}.Release|ARM64.Build.0 = Release|ARM64 - {697C6AF9-0A48-49A9-866C-67DA12384015}.Release|x64.ActiveCfg = Release|x64 - {697C6AF9-0A48-49A9-866C-67DA12384015}.Release|x64.Build.0 = Release|x64 - {9EBAA524-0EDA-470B-95D4-39383285CBB2}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {9EBAA524-0EDA-470B-95D4-39383285CBB2}.Debug|ARM64.Build.0 = Debug|ARM64 - {9EBAA524-0EDA-470B-95D4-39383285CBB2}.Debug|x64.ActiveCfg = Debug|x64 - {9EBAA524-0EDA-470B-95D4-39383285CBB2}.Debug|x64.Build.0 = Debug|x64 - {9EBAA524-0EDA-470B-95D4-39383285CBB2}.Release|ARM64.ActiveCfg = Release|ARM64 - {9EBAA524-0EDA-470B-95D4-39383285CBB2}.Release|ARM64.Build.0 = Release|ARM64 - {9EBAA524-0EDA-470B-95D4-39383285CBB2}.Release|x64.ActiveCfg = Release|x64 - {9EBAA524-0EDA-470B-95D4-39383285CBB2}.Release|x64.Build.0 = Release|x64 - {500DED3E-CFB5-4ED5-ACC6-02B3D6DC336D}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {500DED3E-CFB5-4ED5-ACC6-02B3D6DC336D}.Debug|ARM64.Build.0 = Debug|ARM64 - {500DED3E-CFB5-4ED5-ACC6-02B3D6DC336D}.Debug|x64.ActiveCfg = Debug|x64 - {500DED3E-CFB5-4ED5-ACC6-02B3D6DC336D}.Debug|x64.Build.0 = Debug|x64 - {500DED3E-CFB5-4ED5-ACC6-02B3D6DC336D}.Release|ARM64.ActiveCfg = Release|ARM64 - {500DED3E-CFB5-4ED5-ACC6-02B3D6DC336D}.Release|ARM64.Build.0 = Release|ARM64 - {500DED3E-CFB5-4ED5-ACC6-02B3D6DC336D}.Release|x64.ActiveCfg = Release|x64 - {500DED3E-CFB5-4ED5-ACC6-02B3D6DC336D}.Release|x64.Build.0 = Release|x64 - {D095BE44-1F2E-463E-A494-121892A75EA2}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {D095BE44-1F2E-463E-A494-121892A75EA2}.Debug|ARM64.Build.0 = Debug|ARM64 - {D095BE44-1F2E-463E-A494-121892A75EA2}.Debug|x64.ActiveCfg = Debug|x64 - {D095BE44-1F2E-463E-A494-121892A75EA2}.Debug|x64.Build.0 = Debug|x64 - {D095BE44-1F2E-463E-A494-121892A75EA2}.Release|ARM64.ActiveCfg = Release|ARM64 - {D095BE44-1F2E-463E-A494-121892A75EA2}.Release|ARM64.Build.0 = Release|ARM64 - {D095BE44-1F2E-463E-A494-121892A75EA2}.Release|x64.ActiveCfg = Release|x64 - {D095BE44-1F2E-463E-A494-121892A75EA2}.Release|x64.Build.0 = Release|x64 - {90F9FA90-2C20-4004-96E6-F3B78151F5A5}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {90F9FA90-2C20-4004-96E6-F3B78151F5A5}.Debug|ARM64.Build.0 = Debug|ARM64 - {90F9FA90-2C20-4004-96E6-F3B78151F5A5}.Debug|x64.ActiveCfg = Debug|x64 - {90F9FA90-2C20-4004-96E6-F3B78151F5A5}.Debug|x64.Build.0 = Debug|x64 - {90F9FA90-2C20-4004-96E6-F3B78151F5A5}.Release|ARM64.ActiveCfg = Release|ARM64 - {90F9FA90-2C20-4004-96E6-F3B78151F5A5}.Release|ARM64.Build.0 = Release|ARM64 - {90F9FA90-2C20-4004-96E6-F3B78151F5A5}.Release|x64.ActiveCfg = Release|x64 - {90F9FA90-2C20-4004-96E6-F3B78151F5A5}.Release|x64.Build.0 = Release|x64 - {F5E1146E-B7B3-4E11-85FD-270A500BD78C}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {F5E1146E-B7B3-4E11-85FD-270A500BD78C}.Debug|ARM64.Build.0 = Debug|ARM64 - {F5E1146E-B7B3-4E11-85FD-270A500BD78C}.Debug|x64.ActiveCfg = Debug|x64 - {F5E1146E-B7B3-4E11-85FD-270A500BD78C}.Debug|x64.Build.0 = Debug|x64 - {F5E1146E-B7B3-4E11-85FD-270A500BD78C}.Release|ARM64.ActiveCfg = Release|ARM64 - {F5E1146E-B7B3-4E11-85FD-270A500BD78C}.Release|ARM64.Build.0 = Release|ARM64 - {F5E1146E-B7B3-4E11-85FD-270A500BD78C}.Release|x64.ActiveCfg = Release|x64 - {F5E1146E-B7B3-4E11-85FD-270A500BD78C}.Release|x64.Build.0 = Release|x64 - {3157FA75-86CF-4EE2-8F62-C43F776493C6}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {3157FA75-86CF-4EE2-8F62-C43F776493C6}.Debug|ARM64.Build.0 = Debug|ARM64 - {3157FA75-86CF-4EE2-8F62-C43F776493C6}.Debug|x64.ActiveCfg = Debug|x64 - {3157FA75-86CF-4EE2-8F62-C43F776493C6}.Debug|x64.Build.0 = Debug|x64 - {3157FA75-86CF-4EE2-8F62-C43F776493C6}.Release|ARM64.ActiveCfg = Release|ARM64 - {3157FA75-86CF-4EE2-8F62-C43F776493C6}.Release|ARM64.Build.0 = Release|ARM64 - {3157FA75-86CF-4EE2-8F62-C43F776493C6}.Release|x64.ActiveCfg = Release|x64 - {3157FA75-86CF-4EE2-8F62-C43F776493C6}.Release|x64.Build.0 = Release|x64 - {51465DA1-C18B-4B99-93E1-ECF8E0FA0CBA}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {51465DA1-C18B-4B99-93E1-ECF8E0FA0CBA}.Debug|ARM64.Build.0 = Debug|Any CPU - {51465DA1-C18B-4B99-93E1-ECF8E0FA0CBA}.Debug|x64.ActiveCfg = Debug|Any CPU - {51465DA1-C18B-4B99-93E1-ECF8E0FA0CBA}.Debug|x64.Build.0 = Debug|Any CPU - {51465DA1-C18B-4B99-93E1-ECF8E0FA0CBA}.Release|ARM64.ActiveCfg = Release|Any CPU - {51465DA1-C18B-4B99-93E1-ECF8E0FA0CBA}.Release|ARM64.Build.0 = Release|Any CPU - {51465DA1-C18B-4B99-93E1-ECF8E0FA0CBA}.Release|x64.ActiveCfg = Release|Any CPU - {51465DA1-C18B-4B99-93E1-ECF8E0FA0CBA}.Release|x64.Build.0 = Release|Any CPU - {B9420661-B0E4-4241-ABD4-4A27A1F64250}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {B9420661-B0E4-4241-ABD4-4A27A1F64250}.Debug|ARM64.Build.0 = Debug|ARM64 - {B9420661-B0E4-4241-ABD4-4A27A1F64250}.Debug|x64.ActiveCfg = Debug|x64 - {B9420661-B0E4-4241-ABD4-4A27A1F64250}.Debug|x64.Build.0 = Debug|x64 - {B9420661-B0E4-4241-ABD4-4A27A1F64250}.Release|ARM64.ActiveCfg = Release|ARM64 - {B9420661-B0E4-4241-ABD4-4A27A1F64250}.Release|ARM64.Build.0 = Release|ARM64 - {B9420661-B0E4-4241-ABD4-4A27A1F64250}.Release|x64.ActiveCfg = Release|x64 - {B9420661-B0E4-4241-ABD4-4A27A1F64250}.Release|x64.Build.0 = Release|x64 - {CCB5E44F-84D9-4203-83C6-1C9EC9302BC7}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {CCB5E44F-84D9-4203-83C6-1C9EC9302BC7}.Debug|ARM64.Build.0 = Debug|ARM64 - {CCB5E44F-84D9-4203-83C6-1C9EC9302BC7}.Debug|x64.ActiveCfg = Debug|x64 - {CCB5E44F-84D9-4203-83C6-1C9EC9302BC7}.Debug|x64.Build.0 = Debug|x64 - {CCB5E44F-84D9-4203-83C6-1C9EC9302BC7}.Release|ARM64.ActiveCfg = Release|ARM64 - {CCB5E44F-84D9-4203-83C6-1C9EC9302BC7}.Release|ARM64.Build.0 = Release|ARM64 - {CCB5E44F-84D9-4203-83C6-1C9EC9302BC7}.Release|x64.ActiveCfg = Release|x64 - {CCB5E44F-84D9-4203-83C6-1C9EC9302BC7}.Release|x64.Build.0 = Release|x64 - {D949EC7D-48A9-4279-95D5-078E7FD1F048}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {D949EC7D-48A9-4279-95D5-078E7FD1F048}.Debug|ARM64.Build.0 = Debug|ARM64 - {D949EC7D-48A9-4279-95D5-078E7FD1F048}.Debug|x64.ActiveCfg = Debug|x64 - {D949EC7D-48A9-4279-95D5-078E7FD1F048}.Debug|x64.Build.0 = Debug|x64 - {D949EC7D-48A9-4279-95D5-078E7FD1F048}.Release|ARM64.ActiveCfg = Release|ARM64 - {D949EC7D-48A9-4279-95D5-078E7FD1F048}.Release|ARM64.Build.0 = Release|ARM64 - {D949EC7D-48A9-4279-95D5-078E7FD1F048}.Release|x64.ActiveCfg = Release|x64 - {D949EC7D-48A9-4279-95D5-078E7FD1F048}.Release|x64.Build.0 = Release|x64 - {3BAF9C81-A194-4925-A035-5E24A5D1E542}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {3BAF9C81-A194-4925-A035-5E24A5D1E542}.Debug|ARM64.Build.0 = Debug|ARM64 - {3BAF9C81-A194-4925-A035-5E24A5D1E542}.Debug|x64.ActiveCfg = Debug|x64 - {3BAF9C81-A194-4925-A035-5E24A5D1E542}.Debug|x64.Build.0 = Debug|x64 - {3BAF9C81-A194-4925-A035-5E24A5D1E542}.Release|ARM64.ActiveCfg = Release|ARM64 - {3BAF9C81-A194-4925-A035-5E24A5D1E542}.Release|ARM64.Build.0 = Release|ARM64 - {3BAF9C81-A194-4925-A035-5E24A5D1E542}.Release|x64.ActiveCfg = Release|x64 - {3BAF9C81-A194-4925-A035-5E24A5D1E542}.Release|x64.Build.0 = Release|x64 - {6B04803D-B418-4833-A67E-B0FC966636A5}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6B04803D-B418-4833-A67E-B0FC966636A5}.Debug|ARM64.Build.0 = Debug|ARM64 - {6B04803D-B418-4833-A67E-B0FC966636A5}.Debug|x64.ActiveCfg = Debug|x64 - {6B04803D-B418-4833-A67E-B0FC966636A5}.Debug|x64.Build.0 = Debug|x64 - {6B04803D-B418-4833-A67E-B0FC966636A5}.Release|ARM64.ActiveCfg = Release|ARM64 - {6B04803D-B418-4833-A67E-B0FC966636A5}.Release|ARM64.Build.0 = Release|ARM64 - {6B04803D-B418-4833-A67E-B0FC966636A5}.Release|x64.ActiveCfg = Release|x64 - {6B04803D-B418-4833-A67E-B0FC966636A5}.Release|x64.Build.0 = Release|x64 - {3940AD4D-F748-4BE4-9083-85769CD553EF}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {3940AD4D-F748-4BE4-9083-85769CD553EF}.Debug|ARM64.Build.0 = Debug|ARM64 - {3940AD4D-F748-4BE4-9083-85769CD553EF}.Debug|x64.ActiveCfg = Debug|x64 - {3940AD4D-F748-4BE4-9083-85769CD553EF}.Debug|x64.Build.0 = Debug|x64 - {3940AD4D-F748-4BE4-9083-85769CD553EF}.Release|ARM64.ActiveCfg = Release|ARM64 - {3940AD4D-F748-4BE4-9083-85769CD553EF}.Release|ARM64.Build.0 = Release|ARM64 - {3940AD4D-F748-4BE4-9083-85769CD553EF}.Release|x64.ActiveCfg = Release|x64 - {3940AD4D-F748-4BE4-9083-85769CD553EF}.Release|x64.Build.0 = Release|x64 - {F8FFFC12-A31A-4AFA-B3DF-14DCF42B5E38}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {F8FFFC12-A31A-4AFA-B3DF-14DCF42B5E38}.Debug|ARM64.Build.0 = Debug|ARM64 - {F8FFFC12-A31A-4AFA-B3DF-14DCF42B5E38}.Debug|x64.ActiveCfg = Debug|x64 - {F8FFFC12-A31A-4AFA-B3DF-14DCF42B5E38}.Debug|x64.Build.0 = Debug|x64 - {F8FFFC12-A31A-4AFA-B3DF-14DCF42B5E38}.Release|ARM64.ActiveCfg = Release|ARM64 - {F8FFFC12-A31A-4AFA-B3DF-14DCF42B5E38}.Release|ARM64.Build.0 = Release|ARM64 - {F8FFFC12-A31A-4AFA-B3DF-14DCF42B5E38}.Release|x64.ActiveCfg = Release|x64 - {F8FFFC12-A31A-4AFA-B3DF-14DCF42B5E38}.Release|x64.Build.0 = Release|x64 - {0014D652-901F-4456-8D65-06FC5F997FB0}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {0014D652-901F-4456-8D65-06FC5F997FB0}.Debug|ARM64.Build.0 = Debug|ARM64 - {0014D652-901F-4456-8D65-06FC5F997FB0}.Debug|x64.ActiveCfg = Debug|x64 - {0014D652-901F-4456-8D65-06FC5F997FB0}.Debug|x64.Build.0 = Debug|x64 - {0014D652-901F-4456-8D65-06FC5F997FB0}.Release|ARM64.ActiveCfg = Release|ARM64 - {0014D652-901F-4456-8D65-06FC5F997FB0}.Release|ARM64.Build.0 = Release|ARM64 - {0014D652-901F-4456-8D65-06FC5F997FB0}.Release|x64.ActiveCfg = Release|x64 - {0014D652-901F-4456-8D65-06FC5F997FB0}.Release|x64.Build.0 = Release|x64 - {799A50D8-DE89-4ED1-8FF8-AD5A9ED8C0CA}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {799A50D8-DE89-4ED1-8FF8-AD5A9ED8C0CA}.Debug|ARM64.Build.0 = Debug|ARM64 - {799A50D8-DE89-4ED1-8FF8-AD5A9ED8C0CA}.Debug|x64.ActiveCfg = Debug|x64 - {799A50D8-DE89-4ED1-8FF8-AD5A9ED8C0CA}.Debug|x64.Build.0 = Debug|x64 - {799A50D8-DE89-4ED1-8FF8-AD5A9ED8C0CA}.Release|ARM64.ActiveCfg = Release|ARM64 - {799A50D8-DE89-4ED1-8FF8-AD5A9ED8C0CA}.Release|ARM64.Build.0 = Release|ARM64 - {799A50D8-DE89-4ED1-8FF8-AD5A9ED8C0CA}.Release|x64.ActiveCfg = Release|x64 - {799A50D8-DE89-4ED1-8FF8-AD5A9ED8C0CA}.Release|x64.Build.0 = Release|x64 - {9D52FD25-EF90-4F9A-A015-91EFC5DAF54F}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {9D52FD25-EF90-4F9A-A015-91EFC5DAF54F}.Debug|ARM64.Build.0 = Debug|ARM64 - {9D52FD25-EF90-4F9A-A015-91EFC5DAF54F}.Debug|x64.ActiveCfg = Debug|x64 - {9D52FD25-EF90-4F9A-A015-91EFC5DAF54F}.Debug|x64.Build.0 = Debug|x64 - {9D52FD25-EF90-4F9A-A015-91EFC5DAF54F}.Release|ARM64.ActiveCfg = Release|ARM64 - {9D52FD25-EF90-4F9A-A015-91EFC5DAF54F}.Release|ARM64.Build.0 = Release|ARM64 - {9D52FD25-EF90-4F9A-A015-91EFC5DAF54F}.Release|x64.ActiveCfg = Release|x64 - {9D52FD25-EF90-4F9A-A015-91EFC5DAF54F}.Release|x64.Build.0 = Release|x64 - {C32D254F-7597-4CBE-BF74-D922D81CDF29}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {C32D254F-7597-4CBE-BF74-D922D81CDF29}.Debug|ARM64.Build.0 = Debug|ARM64 - {C32D254F-7597-4CBE-BF74-D922D81CDF29}.Debug|ARM64.Deploy.0 = Debug|ARM64 - {C32D254F-7597-4CBE-BF74-D922D81CDF29}.Debug|x64.ActiveCfg = Debug|x64 - {C32D254F-7597-4CBE-BF74-D922D81CDF29}.Debug|x64.Build.0 = Debug|x64 - {C32D254F-7597-4CBE-BF74-D922D81CDF29}.Debug|x64.Deploy.0 = Debug|x64 - {C32D254F-7597-4CBE-BF74-D922D81CDF29}.Release|ARM64.ActiveCfg = Release|ARM64 - {C32D254F-7597-4CBE-BF74-D922D81CDF29}.Release|ARM64.Build.0 = Release|ARM64 - {C32D254F-7597-4CBE-BF74-D922D81CDF29}.Release|ARM64.Deploy.0 = Release|ARM64 - {C32D254F-7597-4CBE-BF74-D922D81CDF29}.Release|x64.ActiveCfg = Release|x64 - {C32D254F-7597-4CBE-BF74-D922D81CDF29}.Release|x64.Build.0 = Release|x64 - {C32D254F-7597-4CBE-BF74-D922D81CDF29}.Release|x64.Deploy.0 = Release|x64 - {02DD46D3-F761-47D9-8894-2D6DA0124650}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {02DD46D3-F761-47D9-8894-2D6DA0124650}.Debug|ARM64.Build.0 = Debug|ARM64 - {02DD46D3-F761-47D9-8894-2D6DA0124650}.Debug|x64.ActiveCfg = Debug|x64 - {02DD46D3-F761-47D9-8894-2D6DA0124650}.Debug|x64.Build.0 = Debug|x64 - {02DD46D3-F761-47D9-8894-2D6DA0124650}.Release|ARM64.ActiveCfg = Release|ARM64 - {02DD46D3-F761-47D9-8894-2D6DA0124650}.Release|ARM64.Build.0 = Release|ARM64 - {02DD46D3-F761-47D9-8894-2D6DA0124650}.Release|x64.ActiveCfg = Release|x64 - {02DD46D3-F761-47D9-8894-2D6DA0124650}.Release|x64.Build.0 = Release|x64 - {8E23E173-7127-4A5F-9F93-3049F2B68047}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {8E23E173-7127-4A5F-9F93-3049F2B68047}.Debug|ARM64.Build.0 = Debug|ARM64 - {8E23E173-7127-4A5F-9F93-3049F2B68047}.Debug|x64.ActiveCfg = Debug|x64 - {8E23E173-7127-4A5F-9F93-3049F2B68047}.Debug|x64.Build.0 = Debug|x64 - {8E23E173-7127-4A5F-9F93-3049F2B68047}.Release|ARM64.ActiveCfg = Release|ARM64 - {8E23E173-7127-4A5F-9F93-3049F2B68047}.Release|ARM64.Build.0 = Release|ARM64 - {8E23E173-7127-4A5F-9F93-3049F2B68047}.Release|x64.ActiveCfg = Release|x64 - {8E23E173-7127-4A5F-9F93-3049F2B68047}.Release|x64.Build.0 = Release|x64 - {DFF88D16-D36F-40A4-A955-CDCAA76EF7B8}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {DFF88D16-D36F-40A4-A955-CDCAA76EF7B8}.Debug|ARM64.Build.0 = Debug|ARM64 - {DFF88D16-D36F-40A4-A955-CDCAA76EF7B8}.Debug|x64.ActiveCfg = Debug|x64 - {DFF88D16-D36F-40A4-A955-CDCAA76EF7B8}.Debug|x64.Build.0 = Debug|x64 - {DFF88D16-D36F-40A4-A955-CDCAA76EF7B8}.Release|ARM64.ActiveCfg = Release|ARM64 - {DFF88D16-D36F-40A4-A955-CDCAA76EF7B8}.Release|ARM64.Build.0 = Release|ARM64 - {DFF88D16-D36F-40A4-A955-CDCAA76EF7B8}.Release|x64.ActiveCfg = Release|x64 - {DFF88D16-D36F-40A4-A955-CDCAA76EF7B8}.Release|x64.Build.0 = Release|x64 - {C0974915-8A1D-4BF0-977B-9587D3807AB7}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {C0974915-8A1D-4BF0-977B-9587D3807AB7}.Debug|ARM64.Build.0 = Debug|ARM64 - {C0974915-8A1D-4BF0-977B-9587D3807AB7}.Debug|x64.ActiveCfg = Debug|x64 - {C0974915-8A1D-4BF0-977B-9587D3807AB7}.Debug|x64.Build.0 = Debug|x64 - {C0974915-8A1D-4BF0-977B-9587D3807AB7}.Release|ARM64.ActiveCfg = Release|ARM64 - {C0974915-8A1D-4BF0-977B-9587D3807AB7}.Release|ARM64.Build.0 = Release|ARM64 - {C0974915-8A1D-4BF0-977B-9587D3807AB7}.Release|x64.ActiveCfg = Release|x64 - {C0974915-8A1D-4BF0-977B-9587D3807AB7}.Release|x64.Build.0 = Release|x64 - {1D6893CB-BC0C-46A8-A76C-9728706CA51A}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {1D6893CB-BC0C-46A8-A76C-9728706CA51A}.Debug|ARM64.Build.0 = Debug|ARM64 - {1D6893CB-BC0C-46A8-A76C-9728706CA51A}.Debug|x64.ActiveCfg = Debug|x64 - {1D6893CB-BC0C-46A8-A76C-9728706CA51A}.Debug|x64.Build.0 = Debug|x64 - {1D6893CB-BC0C-46A8-A76C-9728706CA51A}.Release|ARM64.ActiveCfg = Release|ARM64 - {1D6893CB-BC0C-46A8-A76C-9728706CA51A}.Release|ARM64.Build.0 = Release|ARM64 - {1D6893CB-BC0C-46A8-A76C-9728706CA51A}.Release|x64.ActiveCfg = Release|x64 - {1D6893CB-BC0C-46A8-A76C-9728706CA51A}.Release|x64.Build.0 = Release|x64 - {8ACB33D9-C95B-47D4-8363-9731EE0930A0}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {8ACB33D9-C95B-47D4-8363-9731EE0930A0}.Debug|ARM64.Build.0 = Debug|ARM64 - {8ACB33D9-C95B-47D4-8363-9731EE0930A0}.Debug|x64.ActiveCfg = Debug|x64 - {8ACB33D9-C95B-47D4-8363-9731EE0930A0}.Debug|x64.Build.0 = Debug|x64 - {8ACB33D9-C95B-47D4-8363-9731EE0930A0}.Release|ARM64.ActiveCfg = Release|ARM64 - {8ACB33D9-C95B-47D4-8363-9731EE0930A0}.Release|ARM64.Build.0 = Release|ARM64 - {8ACB33D9-C95B-47D4-8363-9731EE0930A0}.Release|x64.ActiveCfg = Release|x64 - {8ACB33D9-C95B-47D4-8363-9731EE0930A0}.Release|x64.Build.0 = Release|x64 - {F055103B-F80B-4D0C-BF48-057C55620033}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {F055103B-F80B-4D0C-BF48-057C55620033}.Debug|ARM64.Build.0 = Debug|ARM64 - {F055103B-F80B-4D0C-BF48-057C55620033}.Debug|x64.ActiveCfg = Debug|x64 - {F055103B-F80B-4D0C-BF48-057C55620033}.Debug|x64.Build.0 = Debug|x64 - {F055103B-F80B-4D0C-BF48-057C55620033}.Release|ARM64.ActiveCfg = Release|ARM64 - {F055103B-F80B-4D0C-BF48-057C55620033}.Release|ARM64.Build.0 = Release|ARM64 - {F055103B-F80B-4D0C-BF48-057C55620033}.Release|x64.ActiveCfg = Release|x64 - {F055103B-F80B-4D0C-BF48-057C55620033}.Release|x64.Build.0 = Release|x64 - {B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332}.Debug|ARM64.Build.0 = Debug|ARM64 - {B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332}.Debug|x64.ActiveCfg = Debug|x64 - {B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332}.Debug|x64.Build.0 = Debug|x64 - {B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332}.Release|ARM64.ActiveCfg = Release|ARM64 - {B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332}.Release|ARM64.Build.0 = Release|ARM64 - {B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332}.Release|x64.ActiveCfg = Release|x64 - {B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332}.Release|x64.Build.0 = Release|x64 - {A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C}.Debug|ARM64.Build.0 = Debug|ARM64 - {A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C}.Debug|x64.ActiveCfg = Debug|x64 - {A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C}.Debug|x64.Build.0 = Debug|x64 - {A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C}.Release|ARM64.ActiveCfg = Release|ARM64 - {A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C}.Release|ARM64.Build.0 = Release|ARM64 - {A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C}.Release|x64.ActiveCfg = Release|x64 - {A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C}.Release|x64.Build.0 = Release|x64 - {9C53CC25-0623-4569-95BC-B05410675EE3}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {9C53CC25-0623-4569-95BC-B05410675EE3}.Debug|ARM64.Build.0 = Debug|ARM64 - {9C53CC25-0623-4569-95BC-B05410675EE3}.Debug|x64.ActiveCfg = Debug|x64 - {9C53CC25-0623-4569-95BC-B05410675EE3}.Debug|x64.Build.0 = Debug|x64 - {9C53CC25-0623-4569-95BC-B05410675EE3}.Release|ARM64.ActiveCfg = Release|ARM64 - {9C53CC25-0623-4569-95BC-B05410675EE3}.Release|ARM64.Build.0 = Release|ARM64 - {9C53CC25-0623-4569-95BC-B05410675EE3}.Release|x64.ActiveCfg = Release|x64 - {9C53CC25-0623-4569-95BC-B05410675EE3}.Release|x64.Build.0 = Release|x64 - {45285DF2-9742-4ECA-9AC9-58951FC26489}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {45285DF2-9742-4ECA-9AC9-58951FC26489}.Debug|ARM64.Build.0 = Debug|ARM64 - {45285DF2-9742-4ECA-9AC9-58951FC26489}.Debug|x64.ActiveCfg = Debug|x64 - {45285DF2-9742-4ECA-9AC9-58951FC26489}.Debug|x64.Build.0 = Debug|x64 - {45285DF2-9742-4ECA-9AC9-58951FC26489}.Release|ARM64.ActiveCfg = Release|ARM64 - {45285DF2-9742-4ECA-9AC9-58951FC26489}.Release|ARM64.Build.0 = Release|ARM64 - {45285DF2-9742-4ECA-9AC9-58951FC26489}.Release|x64.ActiveCfg = Release|x64 - {45285DF2-9742-4ECA-9AC9-58951FC26489}.Release|x64.Build.0 = Release|x64 - {3D63307B-9D27-44FD-B033-B26F39245B85}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {3D63307B-9D27-44FD-B033-B26F39245B85}.Debug|ARM64.Build.0 = Debug|ARM64 - {3D63307B-9D27-44FD-B033-B26F39245B85}.Debug|x64.ActiveCfg = Debug|x64 - {3D63307B-9D27-44FD-B033-B26F39245B85}.Debug|x64.Build.0 = Debug|x64 - {3D63307B-9D27-44FD-B033-B26F39245B85}.Release|ARM64.ActiveCfg = Release|ARM64 - {3D63307B-9D27-44FD-B033-B26F39245B85}.Release|ARM64.Build.0 = Release|ARM64 - {3D63307B-9D27-44FD-B033-B26F39245B85}.Release|x64.ActiveCfg = Release|x64 - {3D63307B-9D27-44FD-B033-B26F39245B85}.Release|x64.Build.0 = Release|x64 - {367D7543-7DBA-4381-99F1-BF6142A996C4}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {367D7543-7DBA-4381-99F1-BF6142A996C4}.Debug|ARM64.Build.0 = Debug|ARM64 - {367D7543-7DBA-4381-99F1-BF6142A996C4}.Debug|x64.ActiveCfg = Debug|x64 - {367D7543-7DBA-4381-99F1-BF6142A996C4}.Debug|x64.Build.0 = Debug|x64 - {367D7543-7DBA-4381-99F1-BF6142A996C4}.Release|ARM64.ActiveCfg = Release|ARM64 - {367D7543-7DBA-4381-99F1-BF6142A996C4}.Release|ARM64.Build.0 = Release|ARM64 - {367D7543-7DBA-4381-99F1-BF6142A996C4}.Release|x64.ActiveCfg = Release|x64 - {367D7543-7DBA-4381-99F1-BF6142A996C4}.Release|x64.Build.0 = Release|x64 - {2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Debug|ARM64.Build.0 = Debug|ARM64 - {2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Debug|x64.ActiveCfg = Debug|x64 - {2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Debug|x64.Build.0 = Debug|x64 - {2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Release|ARM64.ActiveCfg = Release|ARM64 - {2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Release|ARM64.Build.0 = Release|ARM64 - {2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Release|x64.ActiveCfg = Release|x64 - {2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96}.Release|x64.Build.0 = Release|x64 - {37D07516-4185-43A4-924F-3C7A5D95ECF6}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {37D07516-4185-43A4-924F-3C7A5D95ECF6}.Debug|ARM64.Build.0 = Debug|ARM64 - {37D07516-4185-43A4-924F-3C7A5D95ECF6}.Debug|x64.ActiveCfg = Debug|x64 - {37D07516-4185-43A4-924F-3C7A5D95ECF6}.Debug|x64.Build.0 = Debug|x64 - {37D07516-4185-43A4-924F-3C7A5D95ECF6}.Release|ARM64.ActiveCfg = Release|ARM64 - {37D07516-4185-43A4-924F-3C7A5D95ECF6}.Release|ARM64.Build.0 = Release|ARM64 - {37D07516-4185-43A4-924F-3C7A5D95ECF6}.Release|x64.ActiveCfg = Release|x64 - {37D07516-4185-43A4-924F-3C7A5D95ECF6}.Release|x64.Build.0 = Release|x64 - {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|ARM64.Build.0 = Debug|ARM64 - {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|x64.ActiveCfg = Debug|x64 - {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|x64.Build.0 = Debug|x64 - {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|ARM64.ActiveCfg = Release|ARM64 - {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|ARM64.Build.0 = Release|ARM64 - {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|x64.ActiveCfg = Release|x64 - {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|x64.Build.0 = Release|x64 - {66614C26-314C-4B91-9071-76133422CFEF}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {66614C26-314C-4B91-9071-76133422CFEF}.Debug|ARM64.Build.0 = Debug|ARM64 - {66614C26-314C-4B91-9071-76133422CFEF}.Debug|x64.ActiveCfg = Debug|x64 - {66614C26-314C-4B91-9071-76133422CFEF}.Debug|x64.Build.0 = Debug|x64 - {66614C26-314C-4B91-9071-76133422CFEF}.Release|ARM64.ActiveCfg = Release|ARM64 - {66614C26-314C-4B91-9071-76133422CFEF}.Release|ARM64.Build.0 = Release|ARM64 - {66614C26-314C-4B91-9071-76133422CFEF}.Release|x64.ActiveCfg = Release|x64 - {66614C26-314C-4B91-9071-76133422CFEF}.Release|x64.Build.0 = Release|x64 - {6CE438DF-C245-4997-A360-0A0939E4BA34}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6CE438DF-C245-4997-A360-0A0939E4BA34}.Debug|ARM64.Build.0 = Debug|ARM64 - {6CE438DF-C245-4997-A360-0A0939E4BA34}.Debug|x64.ActiveCfg = Debug|x64 - {6CE438DF-C245-4997-A360-0A0939E4BA34}.Debug|x64.Build.0 = Debug|x64 - {6CE438DF-C245-4997-A360-0A0939E4BA34}.Release|ARM64.ActiveCfg = Release|ARM64 - {6CE438DF-C245-4997-A360-0A0939E4BA34}.Release|ARM64.Build.0 = Release|ARM64 - {6CE438DF-C245-4997-A360-0A0939E4BA34}.Release|x64.ActiveCfg = Release|x64 - {6CE438DF-C245-4997-A360-0A0939E4BA34}.Release|x64.Build.0 = Release|x64 - {E09AA983-C755-474F-83D6-A5CDF528C070}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {E09AA983-C755-474F-83D6-A5CDF528C070}.Debug|ARM64.Build.0 = Debug|ARM64 - {E09AA983-C755-474F-83D6-A5CDF528C070}.Debug|x64.ActiveCfg = Debug|x64 - {E09AA983-C755-474F-83D6-A5CDF528C070}.Debug|x64.Build.0 = Debug|x64 - {E09AA983-C755-474F-83D6-A5CDF528C070}.Release|ARM64.ActiveCfg = Release|ARM64 - {E09AA983-C755-474F-83D6-A5CDF528C070}.Release|ARM64.Build.0 = Release|ARM64 - {E09AA983-C755-474F-83D6-A5CDF528C070}.Release|x64.ActiveCfg = Release|x64 - {E09AA983-C755-474F-83D6-A5CDF528C070}.Release|x64.Build.0 = Release|x64 - {6D56B64D-FF1F-488F-AFED-9B9854A5D399}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6D56B64D-FF1F-488F-AFED-9B9854A5D399}.Debug|ARM64.Build.0 = Debug|ARM64 - {6D56B64D-FF1F-488F-AFED-9B9854A5D399}.Debug|x64.ActiveCfg = Debug|x64 - {6D56B64D-FF1F-488F-AFED-9B9854A5D399}.Debug|x64.Build.0 = Debug|x64 - {6D56B64D-FF1F-488F-AFED-9B9854A5D399}.Release|ARM64.ActiveCfg = Release|ARM64 - {6D56B64D-FF1F-488F-AFED-9B9854A5D399}.Release|ARM64.Build.0 = Release|ARM64 - {6D56B64D-FF1F-488F-AFED-9B9854A5D399}.Release|x64.ActiveCfg = Release|x64 - {6D56B64D-FF1F-488F-AFED-9B9854A5D399}.Release|x64.Build.0 = Release|x64 - {92EC89E4-9972-453A-8A1A-3A9E230C146A}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {92EC89E4-9972-453A-8A1A-3A9E230C146A}.Debug|ARM64.Build.0 = Debug|ARM64 - {92EC89E4-9972-453A-8A1A-3A9E230C146A}.Debug|x64.ActiveCfg = Debug|x64 - {92EC89E4-9972-453A-8A1A-3A9E230C146A}.Debug|x64.Build.0 = Debug|x64 - {92EC89E4-9972-453A-8A1A-3A9E230C146A}.Release|ARM64.ActiveCfg = Release|ARM64 - {92EC89E4-9972-453A-8A1A-3A9E230C146A}.Release|ARM64.Build.0 = Release|ARM64 - {92EC89E4-9972-453A-8A1A-3A9E230C146A}.Release|x64.ActiveCfg = Release|x64 - {92EC89E4-9972-453A-8A1A-3A9E230C146A}.Release|x64.Build.0 = Release|x64 - {51939B4F-1F62-4BFF-A6A2-C08646E5BE95}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {51939B4F-1F62-4BFF-A6A2-C08646E5BE95}.Debug|ARM64.Build.0 = Debug|ARM64 - {51939B4F-1F62-4BFF-A6A2-C08646E5BE95}.Debug|x64.ActiveCfg = Debug|x64 - {51939B4F-1F62-4BFF-A6A2-C08646E5BE95}.Debug|x64.Build.0 = Debug|x64 - {51939B4F-1F62-4BFF-A6A2-C08646E5BE95}.Release|ARM64.ActiveCfg = Release|ARM64 - {51939B4F-1F62-4BFF-A6A2-C08646E5BE95}.Release|ARM64.Build.0 = Release|ARM64 - {51939B4F-1F62-4BFF-A6A2-C08646E5BE95}.Release|x64.ActiveCfg = Release|x64 - {51939B4F-1F62-4BFF-A6A2-C08646E5BE95}.Release|x64.Build.0 = Release|x64 - {D1160404-D3D1-497A-883A-4059C07C2273}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {D1160404-D3D1-497A-883A-4059C07C2273}.Debug|ARM64.Build.0 = Debug|ARM64 - {D1160404-D3D1-497A-883A-4059C07C2273}.Debug|x64.ActiveCfg = Debug|x64 - {D1160404-D3D1-497A-883A-4059C07C2273}.Debug|x64.Build.0 = Debug|x64 - {D1160404-D3D1-497A-883A-4059C07C2273}.Release|ARM64.ActiveCfg = Release|ARM64 - {D1160404-D3D1-497A-883A-4059C07C2273}.Release|ARM64.Build.0 = Release|ARM64 - {D1160404-D3D1-497A-883A-4059C07C2273}.Release|x64.ActiveCfg = Release|x64 - {D1160404-D3D1-497A-883A-4059C07C2273}.Release|x64.Build.0 = Release|x64 - {40F6D69D-E321-400F-A767-5628C7AE453D}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {40F6D69D-E321-400F-A767-5628C7AE453D}.Debug|ARM64.Build.0 = Debug|ARM64 - {40F6D69D-E321-400F-A767-5628C7AE453D}.Debug|x64.ActiveCfg = Debug|x64 - {40F6D69D-E321-400F-A767-5628C7AE453D}.Debug|x64.Build.0 = Debug|x64 - {40F6D69D-E321-400F-A767-5628C7AE453D}.Release|ARM64.ActiveCfg = Release|ARM64 - {40F6D69D-E321-400F-A767-5628C7AE453D}.Release|ARM64.Build.0 = Release|ARM64 - {40F6D69D-E321-400F-A767-5628C7AE453D}.Release|x64.ActiveCfg = Release|x64 - {40F6D69D-E321-400F-A767-5628C7AE453D}.Release|x64.Build.0 = Release|x64 - {305DD37E-C85D-4B08-AAFE-7381FA890463}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {305DD37E-C85D-4B08-AAFE-7381FA890463}.Debug|ARM64.Build.0 = Debug|ARM64 - {305DD37E-C85D-4B08-AAFE-7381FA890463}.Debug|x64.ActiveCfg = Debug|x64 - {305DD37E-C85D-4B08-AAFE-7381FA890463}.Debug|x64.Build.0 = Debug|x64 - {305DD37E-C85D-4B08-AAFE-7381FA890463}.Release|ARM64.ActiveCfg = Release|ARM64 - {305DD37E-C85D-4B08-AAFE-7381FA890463}.Release|ARM64.Build.0 = Release|ARM64 - {305DD37E-C85D-4B08-AAFE-7381FA890463}.Release|x64.ActiveCfg = Release|x64 - {305DD37E-C85D-4B08-AAFE-7381FA890463}.Release|x64.Build.0 = Release|x64 - {CA4D810F-C8F4-4B61-9DA9-71807E0B9F24}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {CA4D810F-C8F4-4B61-9DA9-71807E0B9F24}.Debug|ARM64.Build.0 = Debug|ARM64 - {CA4D810F-C8F4-4B61-9DA9-71807E0B9F24}.Debug|x64.ActiveCfg = Debug|x64 - {CA4D810F-C8F4-4B61-9DA9-71807E0B9F24}.Debug|x64.Build.0 = Debug|x64 - {CA4D810F-C8F4-4B61-9DA9-71807E0B9F24}.Release|ARM64.ActiveCfg = Release|ARM64 - {CA4D810F-C8F4-4B61-9DA9-71807E0B9F24}.Release|ARM64.Build.0 = Release|ARM64 - {CA4D810F-C8F4-4B61-9DA9-71807E0B9F24}.Release|x64.ActiveCfg = Release|x64 - {CA4D810F-C8F4-4B61-9DA9-71807E0B9F24}.Release|x64.Build.0 = Release|x64 - {14E62033-58D0-4A7D-8990-52F50A08BBBD}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {14E62033-58D0-4A7D-8990-52F50A08BBBD}.Debug|ARM64.Build.0 = Debug|ARM64 - {14E62033-58D0-4A7D-8990-52F50A08BBBD}.Debug|x64.ActiveCfg = Debug|x64 - {14E62033-58D0-4A7D-8990-52F50A08BBBD}.Debug|x64.Build.0 = Debug|x64 - {14E62033-58D0-4A7D-8990-52F50A08BBBD}.Release|ARM64.ActiveCfg = Release|ARM64 - {14E62033-58D0-4A7D-8990-52F50A08BBBD}.Release|ARM64.Build.0 = Release|ARM64 - {14E62033-58D0-4A7D-8990-52F50A08BBBD}.Release|x64.ActiveCfg = Release|x64 - {14E62033-58D0-4A7D-8990-52F50A08BBBD}.Release|x64.Build.0 = Release|x64 - {6515F03F-E56D-4DB4-B23D-AC4FB80DB36F}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6515F03F-E56D-4DB4-B23D-AC4FB80DB36F}.Debug|ARM64.Build.0 = Debug|ARM64 - {6515F03F-E56D-4DB4-B23D-AC4FB80DB36F}.Debug|x64.ActiveCfg = Debug|x64 - {6515F03F-E56D-4DB4-B23D-AC4FB80DB36F}.Debug|x64.Build.0 = Debug|x64 - {6515F03F-E56D-4DB4-B23D-AC4FB80DB36F}.Release|ARM64.ActiveCfg = Release|ARM64 - {6515F03F-E56D-4DB4-B23D-AC4FB80DB36F}.Release|ARM64.Build.0 = Release|ARM64 - {6515F03F-E56D-4DB4-B23D-AC4FB80DB36F}.Release|x64.ActiveCfg = Release|x64 - {6515F03F-E56D-4DB4-B23D-AC4FB80DB36F}.Release|x64.Build.0 = Release|x64 - {C846F7A7-792A-47D9-B0CB-417C900EE03D}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {C846F7A7-792A-47D9-B0CB-417C900EE03D}.Debug|ARM64.Build.0 = Debug|ARM64 - {C846F7A7-792A-47D9-B0CB-417C900EE03D}.Debug|ARM64.Deploy.0 = Debug|ARM64 - {C846F7A7-792A-47D9-B0CB-417C900EE03D}.Debug|x64.ActiveCfg = Debug|x64 - {C846F7A7-792A-47D9-B0CB-417C900EE03D}.Debug|x64.Build.0 = Debug|x64 - {C846F7A7-792A-47D9-B0CB-417C900EE03D}.Debug|x64.Deploy.0 = Debug|x64 - {C846F7A7-792A-47D9-B0CB-417C900EE03D}.Release|ARM64.ActiveCfg = Release|ARM64 - {C846F7A7-792A-47D9-B0CB-417C900EE03D}.Release|ARM64.Build.0 = Release|ARM64 - {C846F7A7-792A-47D9-B0CB-417C900EE03D}.Release|ARM64.Deploy.0 = Release|ARM64 - {C846F7A7-792A-47D9-B0CB-417C900EE03D}.Release|x64.ActiveCfg = Release|x64 - {C846F7A7-792A-47D9-B0CB-417C900EE03D}.Release|x64.Build.0 = Release|x64 - {C846F7A7-792A-47D9-B0CB-417C900EE03D}.Release|x64.Deploy.0 = Release|x64 - {C831231F-891C-4572-9694-45062534B42A}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {C831231F-891C-4572-9694-45062534B42A}.Debug|ARM64.Build.0 = Debug|ARM64 - {C831231F-891C-4572-9694-45062534B42A}.Debug|ARM64.Deploy.0 = Debug|ARM64 - {C831231F-891C-4572-9694-45062534B42A}.Debug|x64.ActiveCfg = Debug|x64 - {C831231F-891C-4572-9694-45062534B42A}.Debug|x64.Build.0 = Debug|x64 - {C831231F-891C-4572-9694-45062534B42A}.Debug|x64.Deploy.0 = Debug|x64 - {C831231F-891C-4572-9694-45062534B42A}.Release|ARM64.ActiveCfg = Release|ARM64 - {C831231F-891C-4572-9694-45062534B42A}.Release|ARM64.Build.0 = Release|ARM64 - {C831231F-891C-4572-9694-45062534B42A}.Release|ARM64.Deploy.0 = Release|ARM64 - {C831231F-891C-4572-9694-45062534B42A}.Release|x64.ActiveCfg = Release|x64 - {C831231F-891C-4572-9694-45062534B42A}.Release|x64.Build.0 = Release|x64 - {C831231F-891C-4572-9694-45062534B42A}.Release|x64.Deploy.0 = Release|x64 - {8FBDABA4-40EE-4C0E-9BC8-2F6444A6EF90}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {8FBDABA4-40EE-4C0E-9BC8-2F6444A6EF90}.Debug|ARM64.Build.0 = Debug|ARM64 - {8FBDABA4-40EE-4C0E-9BC8-2F6444A6EF90}.Debug|ARM64.Deploy.0 = Debug|ARM64 - {8FBDABA4-40EE-4C0E-9BC8-2F6444A6EF90}.Debug|x64.ActiveCfg = Debug|x64 - {8FBDABA4-40EE-4C0E-9BC8-2F6444A6EF90}.Debug|x64.Build.0 = Debug|x64 - {8FBDABA4-40EE-4C0E-9BC8-2F6444A6EF90}.Debug|x64.Deploy.0 = Debug|x64 - {8FBDABA4-40EE-4C0E-9BC8-2F6444A6EF90}.Release|ARM64.ActiveCfg = Release|ARM64 - {8FBDABA4-40EE-4C0E-9BC8-2F6444A6EF90}.Release|ARM64.Build.0 = Release|ARM64 - {8FBDABA4-40EE-4C0E-9BC8-2F6444A6EF90}.Release|ARM64.Deploy.0 = Release|ARM64 - {8FBDABA4-40EE-4C0E-9BC8-2F6444A6EF90}.Release|x64.ActiveCfg = Release|x64 - {8FBDABA4-40EE-4C0E-9BC8-2F6444A6EF90}.Release|x64.Build.0 = Release|x64 - {8FBDABA4-40EE-4C0E-9BC8-2F6444A6EF90}.Release|x64.Deploy.0 = Release|x64 - {C66020D1-CB10-4CF7-8715-84C97FD5E5E2}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {C66020D1-CB10-4CF7-8715-84C97FD5E5E2}.Debug|ARM64.Build.0 = Debug|ARM64 - {C66020D1-CB10-4CF7-8715-84C97FD5E5E2}.Debug|x64.ActiveCfg = Debug|x64 - {C66020D1-CB10-4CF7-8715-84C97FD5E5E2}.Debug|x64.Build.0 = Debug|x64 - {C66020D1-CB10-4CF7-8715-84C97FD5E5E2}.Release|ARM64.ActiveCfg = Release|ARM64 - {C66020D1-CB10-4CF7-8715-84C97FD5E5E2}.Release|ARM64.Build.0 = Release|ARM64 - {C66020D1-CB10-4CF7-8715-84C97FD5E5E2}.Release|x64.ActiveCfg = Release|x64 - {C66020D1-CB10-4CF7-8715-84C97FD5E5E2}.Release|x64.Build.0 = Release|x64 - {79775343-7A3D-445D-9104-3DD5B2893DF9}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {79775343-7A3D-445D-9104-3DD5B2893DF9}.Debug|ARM64.Build.0 = Debug|ARM64 - {79775343-7A3D-445D-9104-3DD5B2893DF9}.Debug|x64.ActiveCfg = Debug|x64 - {79775343-7A3D-445D-9104-3DD5B2893DF9}.Debug|x64.Build.0 = Debug|x64 - {79775343-7A3D-445D-9104-3DD5B2893DF9}.Release|ARM64.ActiveCfg = Release|ARM64 - {79775343-7A3D-445D-9104-3DD5B2893DF9}.Release|ARM64.Build.0 = Release|ARM64 - {79775343-7A3D-445D-9104-3DD5B2893DF9}.Release|x64.ActiveCfg = Release|x64 - {79775343-7A3D-445D-9104-3DD5B2893DF9}.Release|x64.Build.0 = Release|x64 - {0ADEB797-C8C7-4FFA-ACD5-2AF6CAD7ECD8}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {0ADEB797-C8C7-4FFA-ACD5-2AF6CAD7ECD8}.Debug|ARM64.Build.0 = Debug|ARM64 - {0ADEB797-C8C7-4FFA-ACD5-2AF6CAD7ECD8}.Debug|x64.ActiveCfg = Debug|x64 - {0ADEB797-C8C7-4FFA-ACD5-2AF6CAD7ECD8}.Debug|x64.Build.0 = Debug|x64 - {0ADEB797-C8C7-4FFA-ACD5-2AF6CAD7ECD8}.Release|ARM64.ActiveCfg = Release|ARM64 - {0ADEB797-C8C7-4FFA-ACD5-2AF6CAD7ECD8}.Release|ARM64.Build.0 = Release|ARM64 - {0ADEB797-C8C7-4FFA-ACD5-2AF6CAD7ECD8}.Release|x64.ActiveCfg = Release|x64 - {0ADEB797-C8C7-4FFA-ACD5-2AF6CAD7ECD8}.Release|x64.Build.0 = Release|x64 - {89D0E199-B17A-418C-B2F8-7375B6708357}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {89D0E199-B17A-418C-B2F8-7375B6708357}.Debug|ARM64.Build.0 = Debug|ARM64 - {89D0E199-B17A-418C-B2F8-7375B6708357}.Debug|x64.ActiveCfg = Debug|x64 - {89D0E199-B17A-418C-B2F8-7375B6708357}.Debug|x64.Build.0 = Debug|x64 - {89D0E199-B17A-418C-B2F8-7375B6708357}.Release|ARM64.ActiveCfg = Release|ARM64 - {89D0E199-B17A-418C-B2F8-7375B6708357}.Release|ARM64.Build.0 = Release|ARM64 - {89D0E199-B17A-418C-B2F8-7375B6708357}.Release|x64.ActiveCfg = Release|x64 - {89D0E199-B17A-418C-B2F8-7375B6708357}.Release|x64.Build.0 = Release|x64 - {0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}.Debug|ARM64.Build.0 = Debug|ARM64 - {0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}.Debug|x64.ActiveCfg = Debug|x64 - {0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}.Debug|x64.Build.0 = Debug|x64 - {0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}.Release|ARM64.ActiveCfg = Release|ARM64 - {0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}.Release|ARM64.Build.0 = Release|ARM64 - {0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}.Release|x64.ActiveCfg = Release|x64 - {0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}.Release|x64.Build.0 = Release|x64 - {453CBB73-A3CB-4D0B-8D24-6940B86FE21D}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {453CBB73-A3CB-4D0B-8D24-6940B86FE21D}.Debug|ARM64.Build.0 = Debug|ARM64 - {453CBB73-A3CB-4D0B-8D24-6940B86FE21D}.Debug|ARM64.Deploy.0 = Debug|ARM64 - {453CBB73-A3CB-4D0B-8D24-6940B86FE21D}.Debug|x64.ActiveCfg = Debug|x64 - {453CBB73-A3CB-4D0B-8D24-6940B86FE21D}.Debug|x64.Build.0 = Debug|x64 - {453CBB73-A3CB-4D0B-8D24-6940B86FE21D}.Debug|x64.Deploy.0 = Debug|x64 - {453CBB73-A3CB-4D0B-8D24-6940B86FE21D}.Release|ARM64.ActiveCfg = Release|ARM64 - {453CBB73-A3CB-4D0B-8D24-6940B86FE21D}.Release|ARM64.Build.0 = Release|ARM64 - {453CBB73-A3CB-4D0B-8D24-6940B86FE21D}.Release|ARM64.Deploy.0 = Release|ARM64 - {453CBB73-A3CB-4D0B-8D24-6940B86FE21D}.Release|x64.ActiveCfg = Release|x64 - {453CBB73-A3CB-4D0B-8D24-6940B86FE21D}.Release|x64.Build.0 = Release|x64 - {453CBB73-A3CB-4D0B-8D24-6940B86FE21D}.Release|x64.Deploy.0 = Release|x64 - {C0CE3B5E-16D3-495D-B335-CA791B660162}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {C0CE3B5E-16D3-495D-B335-CA791B660162}.Debug|ARM64.Build.0 = Debug|ARM64 - {C0CE3B5E-16D3-495D-B335-CA791B660162}.Debug|x64.ActiveCfg = Debug|x64 - {C0CE3B5E-16D3-495D-B335-CA791B660162}.Debug|x64.Build.0 = Debug|x64 - {C0CE3B5E-16D3-495D-B335-CA791B660162}.Release|ARM64.ActiveCfg = Release|ARM64 - {C0CE3B5E-16D3-495D-B335-CA791B660162}.Release|ARM64.Build.0 = Release|ARM64 - {C0CE3B5E-16D3-495D-B335-CA791B660162}.Release|x64.ActiveCfg = Release|x64 - {C0CE3B5E-16D3-495D-B335-CA791B660162}.Release|x64.Build.0 = Release|x64 - {3A9A7297-92C4-4F16-B6F9-8D4AB652C86C}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {3A9A7297-92C4-4F16-B6F9-8D4AB652C86C}.Debug|ARM64.Build.0 = Debug|ARM64 - {3A9A7297-92C4-4F16-B6F9-8D4AB652C86C}.Debug|x64.ActiveCfg = Debug|x64 - {3A9A7297-92C4-4F16-B6F9-8D4AB652C86C}.Debug|x64.Build.0 = Debug|x64 - {3A9A7297-92C4-4F16-B6F9-8D4AB652C86C}.Release|ARM64.ActiveCfg = Release|ARM64 - {3A9A7297-92C4-4F16-B6F9-8D4AB652C86C}.Release|ARM64.Build.0 = Release|ARM64 - {3A9A7297-92C4-4F16-B6F9-8D4AB652C86C}.Release|x64.ActiveCfg = Release|x64 - {3A9A7297-92C4-4F16-B6F9-8D4AB652C86C}.Release|x64.Build.0 = Release|x64 - {605E914B-7232-4789-AF46-BF5D3DDFC14E}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {605E914B-7232-4789-AF46-BF5D3DDFC14E}.Debug|ARM64.Build.0 = Debug|ARM64 - {605E914B-7232-4789-AF46-BF5D3DDFC14E}.Debug|x64.ActiveCfg = Debug|x64 - {605E914B-7232-4789-AF46-BF5D3DDFC14E}.Debug|x64.Build.0 = Debug|x64 - {605E914B-7232-4789-AF46-BF5D3DDFC14E}.Release|ARM64.ActiveCfg = Release|ARM64 - {605E914B-7232-4789-AF46-BF5D3DDFC14E}.Release|ARM64.Build.0 = Release|ARM64 - {605E914B-7232-4789-AF46-BF5D3DDFC14E}.Release|x64.ActiveCfg = Release|x64 - {605E914B-7232-4789-AF46-BF5D3DDFC14E}.Release|x64.Build.0 = Release|x64 - {E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9}.Debug|ARM64.Build.0 = Debug|ARM64 - {E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9}.Debug|ARM64.Deploy.0 = Debug|ARM64 - {E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9}.Debug|x64.ActiveCfg = Debug|x64 - {E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9}.Debug|x64.Build.0 = Debug|x64 - {E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9}.Debug|x64.Deploy.0 = Debug|x64 - {E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9}.Release|ARM64.ActiveCfg = Release|ARM64 - {E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9}.Release|ARM64.Build.0 = Release|ARM64 - {E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9}.Release|ARM64.Deploy.0 = Release|ARM64 - {E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9}.Release|x64.ActiveCfg = Release|x64 - {E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9}.Release|x64.Build.0 = Release|x64 - {E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9}.Release|x64.Deploy.0 = Release|x64 - {0A84F764-3A88-44CD-AA96-41BDBD48627B}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {0A84F764-3A88-44CD-AA96-41BDBD48627B}.Debug|ARM64.Build.0 = Debug|ARM64 - {0A84F764-3A88-44CD-AA96-41BDBD48627B}.Debug|x64.ActiveCfg = Debug|x64 - {0A84F764-3A88-44CD-AA96-41BDBD48627B}.Debug|x64.Build.0 = Debug|x64 - {0A84F764-3A88-44CD-AA96-41BDBD48627B}.Release|ARM64.ActiveCfg = Release|ARM64 - {0A84F764-3A88-44CD-AA96-41BDBD48627B}.Release|ARM64.Build.0 = Release|ARM64 - {0A84F764-3A88-44CD-AA96-41BDBD48627B}.Release|x64.ActiveCfg = Release|x64 - {0A84F764-3A88-44CD-AA96-41BDBD48627B}.Release|x64.Build.0 = Release|x64 - {E4585179-2AC1-4D5F-A3FF-CFC5392F694C}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {E4585179-2AC1-4D5F-A3FF-CFC5392F694C}.Debug|ARM64.Build.0 = Debug|ARM64 - {E4585179-2AC1-4D5F-A3FF-CFC5392F694C}.Debug|x64.ActiveCfg = Debug|x64 - {E4585179-2AC1-4D5F-A3FF-CFC5392F694C}.Debug|x64.Build.0 = Debug|x64 - {E4585179-2AC1-4D5F-A3FF-CFC5392F694C}.Release|ARM64.ActiveCfg = Release|ARM64 - {E4585179-2AC1-4D5F-A3FF-CFC5392F694C}.Release|ARM64.Build.0 = Release|ARM64 - {E4585179-2AC1-4D5F-A3FF-CFC5392F694C}.Release|x64.ActiveCfg = Release|x64 - {E4585179-2AC1-4D5F-A3FF-CFC5392F694C}.Release|x64.Build.0 = Release|x64 - {CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Debug|ARM64.Build.0 = Debug|ARM64 - {CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Debug|x64.ActiveCfg = Debug|x64 - {CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Debug|x64.Build.0 = Debug|x64 - {CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Release|ARM64.ActiveCfg = Release|ARM64 - {CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Release|ARM64.Build.0 = Release|ARM64 - {CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Release|x64.ActiveCfg = Release|x64 - {CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Release|x64.Build.0 = Release|x64 - {DCC6BD67-17BB-47AA-B507-FB0FE43A7449}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {DCC6BD67-17BB-47AA-B507-FB0FE43A7449}.Debug|ARM64.Build.0 = Debug|ARM64 - {DCC6BD67-17BB-47AA-B507-FB0FE43A7449}.Debug|ARM64.Deploy.0 = Debug|ARM64 - {DCC6BD67-17BB-47AA-B507-FB0FE43A7449}.Debug|x64.ActiveCfg = Debug|x64 - {DCC6BD67-17BB-47AA-B507-FB0FE43A7449}.Debug|x64.Build.0 = Debug|x64 - {DCC6BD67-17BB-47AA-B507-FB0FE43A7449}.Debug|x64.Deploy.0 = Debug|x64 - {DCC6BD67-17BB-47AA-B507-FB0FE43A7449}.Release|ARM64.ActiveCfg = Release|ARM64 - {DCC6BD67-17BB-47AA-B507-FB0FE43A7449}.Release|ARM64.Build.0 = Release|ARM64 - {DCC6BD67-17BB-47AA-B507-FB0FE43A7449}.Release|ARM64.Deploy.0 = Release|ARM64 - {DCC6BD67-17BB-47AA-B507-FB0FE43A7449}.Release|x64.ActiveCfg = Release|x64 - {DCC6BD67-17BB-47AA-B507-FB0FE43A7449}.Release|x64.Build.0 = Release|x64 - {DCC6BD67-17BB-47AA-B507-FB0FE43A7449}.Release|x64.Deploy.0 = Release|x64 - {A558C25D-2007-498E-8B6F-43405AFAE9E2}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {A558C25D-2007-498E-8B6F-43405AFAE9E2}.Debug|ARM64.Build.0 = Debug|ARM64 - {A558C25D-2007-498E-8B6F-43405AFAE9E2}.Debug|x64.ActiveCfg = Debug|x64 - {A558C25D-2007-498E-8B6F-43405AFAE9E2}.Debug|x64.Build.0 = Debug|x64 - {A558C25D-2007-498E-8B6F-43405AFAE9E2}.Release|ARM64.ActiveCfg = Release|ARM64 - {A558C25D-2007-498E-8B6F-43405AFAE9E2}.Release|ARM64.Build.0 = Release|ARM64 - {A558C25D-2007-498E-8B6F-43405AFAE9E2}.Release|x64.ActiveCfg = Release|x64 - {A558C25D-2007-498E-8B6F-43405AFAE9E2}.Release|x64.Build.0 = Release|x64 - {08F9155D-B6DC-46E5-9C83-AF60B655898B}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {08F9155D-B6DC-46E5-9C83-AF60B655898B}.Debug|ARM64.Build.0 = Debug|ARM64 - {08F9155D-B6DC-46E5-9C83-AF60B655898B}.Debug|x64.ActiveCfg = Debug|x64 - {08F9155D-B6DC-46E5-9C83-AF60B655898B}.Debug|x64.Build.0 = Debug|x64 - {08F9155D-B6DC-46E5-9C83-AF60B655898B}.Release|ARM64.ActiveCfg = Release|ARM64 - {08F9155D-B6DC-46E5-9C83-AF60B655898B}.Release|ARM64.Build.0 = Release|ARM64 - {08F9155D-B6DC-46E5-9C83-AF60B655898B}.Release|x64.ActiveCfg = Release|x64 - {08F9155D-B6DC-46E5-9C83-AF60B655898B}.Release|x64.Build.0 = Release|x64 - {4382A954-179A-4078-92AF-715187DFFF50}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {4382A954-179A-4078-92AF-715187DFFF50}.Debug|ARM64.Build.0 = Debug|ARM64 - {4382A954-179A-4078-92AF-715187DFFF50}.Debug|x64.ActiveCfg = Debug|x64 - {4382A954-179A-4078-92AF-715187DFFF50}.Debug|x64.Build.0 = Debug|x64 - {4382A954-179A-4078-92AF-715187DFFF50}.Release|ARM64.ActiveCfg = Release|ARM64 - {4382A954-179A-4078-92AF-715187DFFF50}.Release|ARM64.Build.0 = Release|ARM64 - {4382A954-179A-4078-92AF-715187DFFF50}.Release|x64.ActiveCfg = Release|x64 - {4382A954-179A-4078-92AF-715187DFFF50}.Release|x64.Build.0 = Release|x64 - {EBED240C-8702-452D-B764-6DB9DA9179AF}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {EBED240C-8702-452D-B764-6DB9DA9179AF}.Debug|ARM64.Build.0 = Debug|ARM64 - {EBED240C-8702-452D-B764-6DB9DA9179AF}.Debug|x64.ActiveCfg = Debug|x64 - {EBED240C-8702-452D-B764-6DB9DA9179AF}.Debug|x64.Build.0 = Debug|x64 - {EBED240C-8702-452D-B764-6DB9DA9179AF}.Release|ARM64.ActiveCfg = Release|ARM64 - {EBED240C-8702-452D-B764-6DB9DA9179AF}.Release|ARM64.Build.0 = Release|ARM64 - {EBED240C-8702-452D-B764-6DB9DA9179AF}.Release|x64.ActiveCfg = Release|x64 - {EBED240C-8702-452D-B764-6DB9DA9179AF}.Release|x64.Build.0 = Release|x64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A0}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A0}.Debug|ARM64.Build.0 = Debug|ARM64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A0}.Debug|x64.ActiveCfg = Debug|x64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A0}.Debug|x64.Build.0 = Debug|x64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A0}.Release|ARM64.ActiveCfg = Release|ARM64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A0}.Release|ARM64.Build.0 = Release|ARM64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A0}.Release|x64.ActiveCfg = Release|x64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A0}.Release|x64.Build.0 = Release|x64 - {5702B3CC-8575-48D5-83D8-15BB42269CD3}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {5702B3CC-8575-48D5-83D8-15BB42269CD3}.Debug|ARM64.Build.0 = Debug|ARM64 - {5702B3CC-8575-48D5-83D8-15BB42269CD3}.Debug|x64.ActiveCfg = Debug|x64 - {5702B3CC-8575-48D5-83D8-15BB42269CD3}.Debug|x64.Build.0 = Debug|x64 - {5702B3CC-8575-48D5-83D8-15BB42269CD3}.Release|ARM64.ActiveCfg = Release|ARM64 - {5702B3CC-8575-48D5-83D8-15BB42269CD3}.Release|ARM64.Build.0 = Release|ARM64 - {5702B3CC-8575-48D5-83D8-15BB42269CD3}.Release|x64.ActiveCfg = Release|x64 - {5702B3CC-8575-48D5-83D8-15BB42269CD3}.Release|x64.Build.0 = Release|x64 - {64B88F02-CD88-4ED8-9624-989A800230F9}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {64B88F02-CD88-4ED8-9624-989A800230F9}.Debug|ARM64.Build.0 = Debug|ARM64 - {64B88F02-CD88-4ED8-9624-989A800230F9}.Debug|x64.ActiveCfg = Debug|x64 - {64B88F02-CD88-4ED8-9624-989A800230F9}.Debug|x64.Build.0 = Debug|x64 - {64B88F02-CD88-4ED8-9624-989A800230F9}.Release|ARM64.ActiveCfg = Release|ARM64 - {64B88F02-CD88-4ED8-9624-989A800230F9}.Release|ARM64.Build.0 = Release|ARM64 - {64B88F02-CD88-4ED8-9624-989A800230F9}.Release|x64.ActiveCfg = Release|x64 - {64B88F02-CD88-4ED8-9624-989A800230F9}.Release|x64.Build.0 = Release|x64 - {5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Debug|ARM64.Build.0 = Debug|ARM64 - {5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Debug|x64.ActiveCfg = Debug|x64 - {5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Debug|x64.Build.0 = Debug|x64 - {5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Release|ARM64.ActiveCfg = Release|ARM64 - {5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Release|ARM64.Build.0 = Release|ARM64 - {5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Release|x64.ActiveCfg = Release|x64 - {5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Release|x64.Build.0 = Release|x64 - {2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}.Debug|x64.ActiveCfg = Debug|x64 - {2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}.Debug|x64.Build.0 = Debug|x64 - {2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}.Release|ARM64.ActiveCfg = Release|ARM64 - {2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}.Release|x64.ActiveCfg = Release|x64 - {2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}.Release|x64.Build.0 = Release|x64 - {9E0CBC06-F29A-4810-B93C-97D53863B95E}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {9E0CBC06-F29A-4810-B93C-97D53863B95E}.Debug|ARM64.Build.0 = Debug|ARM64 - {9E0CBC06-F29A-4810-B93C-97D53863B95E}.Debug|x64.ActiveCfg = Debug|x64 - {9E0CBC06-F29A-4810-B93C-97D53863B95E}.Debug|x64.Build.0 = Debug|x64 - {9E0CBC06-F29A-4810-B93C-97D53863B95E}.Release|ARM64.ActiveCfg = Release|ARM64 - {9E0CBC06-F29A-4810-B93C-97D53863B95E}.Release|ARM64.Build.0 = Release|ARM64 - {9E0CBC06-F29A-4810-B93C-97D53863B95E}.Release|x64.ActiveCfg = Release|x64 - {9E0CBC06-F29A-4810-B93C-97D53863B95E}.Release|x64.Build.0 = Release|x64 - {F6088A11-1C9E-4420-AA90-CF7E78DD7F1C}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {F6088A11-1C9E-4420-AA90-CF7E78DD7F1C}.Debug|ARM64.Build.0 = Debug|ARM64 - {F6088A11-1C9E-4420-AA90-CF7E78DD7F1C}.Debug|x64.ActiveCfg = Debug|x64 - {F6088A11-1C9E-4420-AA90-CF7E78DD7F1C}.Debug|x64.Build.0 = Debug|x64 - {F6088A11-1C9E-4420-AA90-CF7E78DD7F1C}.Release|ARM64.ActiveCfg = Release|ARM64 - {F6088A11-1C9E-4420-AA90-CF7E78DD7F1C}.Release|ARM64.Build.0 = Release|ARM64 - {F6088A11-1C9E-4420-AA90-CF7E78DD7F1C}.Release|x64.ActiveCfg = Release|x64 - {F6088A11-1C9E-4420-AA90-CF7E78DD7F1C}.Release|x64.Build.0 = Release|x64 - {47B0678C-806B-4FE1-9F50-46BA88989532}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {47B0678C-806B-4FE1-9F50-46BA88989532}.Debug|ARM64.Build.0 = Debug|ARM64 - {47B0678C-806B-4FE1-9F50-46BA88989532}.Debug|x64.ActiveCfg = Debug|x64 - {47B0678C-806B-4FE1-9F50-46BA88989532}.Debug|x64.Build.0 = Debug|x64 - {47B0678C-806B-4FE1-9F50-46BA88989532}.Release|ARM64.ActiveCfg = Release|ARM64 - {47B0678C-806B-4FE1-9F50-46BA88989532}.Release|ARM64.Build.0 = Release|ARM64 - {47B0678C-806B-4FE1-9F50-46BA88989532}.Release|x64.ActiveCfg = Release|x64 - {47B0678C-806B-4FE1-9F50-46BA88989532}.Release|x64.Build.0 = Release|x64 - {9BC1C986-1E97-4D07-A7B1-CE226C239EFA}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {9BC1C986-1E97-4D07-A7B1-CE226C239EFA}.Debug|ARM64.Build.0 = Debug|ARM64 - {9BC1C986-1E97-4D07-A7B1-CE226C239EFA}.Debug|x64.ActiveCfg = Debug|x64 - {9BC1C986-1E97-4D07-A7B1-CE226C239EFA}.Debug|x64.Build.0 = Debug|x64 - {9BC1C986-1E97-4D07-A7B1-CE226C239EFA}.Release|ARM64.ActiveCfg = Release|ARM64 - {9BC1C986-1E97-4D07-A7B1-CE226C239EFA}.Release|ARM64.Build.0 = Release|ARM64 - {9BC1C986-1E97-4D07-A7B1-CE226C239EFA}.Release|x64.ActiveCfg = Release|x64 - {9BC1C986-1E97-4D07-A7B1-CE226C239EFA}.Release|x64.Build.0 = Release|x64 - {99CA1509-FB73-456E-AFAF-AB89C017BD72}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {99CA1509-FB73-456E-AFAF-AB89C017BD72}.Debug|ARM64.Build.0 = Debug|ARM64 - {99CA1509-FB73-456E-AFAF-AB89C017BD72}.Debug|x64.ActiveCfg = Debug|x64 - {99CA1509-FB73-456E-AFAF-AB89C017BD72}.Debug|x64.Build.0 = Debug|x64 - {99CA1509-FB73-456E-AFAF-AB89C017BD72}.Release|ARM64.ActiveCfg = Release|ARM64 - {99CA1509-FB73-456E-AFAF-AB89C017BD72}.Release|ARM64.Build.0 = Release|ARM64 - {99CA1509-FB73-456E-AFAF-AB89C017BD72}.Release|x64.ActiveCfg = Release|x64 - {99CA1509-FB73-456E-AFAF-AB89C017BD72}.Release|x64.Build.0 = Release|x64 - {61CBF221-9452-4934-B685-146285E080D7}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {61CBF221-9452-4934-B685-146285E080D7}.Debug|ARM64.Build.0 = Debug|ARM64 - {61CBF221-9452-4934-B685-146285E080D7}.Debug|x64.ActiveCfg = Debug|x64 - {61CBF221-9452-4934-B685-146285E080D7}.Debug|x64.Build.0 = Debug|x64 - {61CBF221-9452-4934-B685-146285E080D7}.Release|ARM64.ActiveCfg = Release|ARM64 - {61CBF221-9452-4934-B685-146285E080D7}.Release|ARM64.Build.0 = Release|ARM64 - {61CBF221-9452-4934-B685-146285E080D7}.Release|x64.ActiveCfg = Release|x64 - {61CBF221-9452-4934-B685-146285E080D7}.Release|x64.Build.0 = Release|x64 - {38F187B2-6638-5A40-072F-DBE5E54070A0}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {38F187B2-6638-5A40-072F-DBE5E54070A0}.Debug|ARM64.Build.0 = Debug|ARM64 - {38F187B2-6638-5A40-072F-DBE5E54070A0}.Debug|x64.ActiveCfg = Debug|x64 - {38F187B2-6638-5A40-072F-DBE5E54070A0}.Debug|x64.Build.0 = Debug|x64 - {38F187B2-6638-5A40-072F-DBE5E54070A0}.Release|ARM64.ActiveCfg = Release|ARM64 - {38F187B2-6638-5A40-072F-DBE5E54070A0}.Release|ARM64.Build.0 = Release|ARM64 - {38F187B2-6638-5A40-072F-DBE5E54070A0}.Release|x64.ActiveCfg = Release|x64 - {38F187B2-6638-5A40-072F-DBE5E54070A0}.Release|x64.Build.0 = Release|x64 - {DA0744BC-E822-680E-9CEB-D0FBA903A8EE}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {DA0744BC-E822-680E-9CEB-D0FBA903A8EE}.Debug|ARM64.Build.0 = Debug|ARM64 - {DA0744BC-E822-680E-9CEB-D0FBA903A8EE}.Debug|x64.ActiveCfg = Debug|x64 - {DA0744BC-E822-680E-9CEB-D0FBA903A8EE}.Debug|x64.Build.0 = Debug|x64 - {DA0744BC-E822-680E-9CEB-D0FBA903A8EE}.Release|ARM64.ActiveCfg = Release|ARM64 - {DA0744BC-E822-680E-9CEB-D0FBA903A8EE}.Release|ARM64.Build.0 = Release|ARM64 - {DA0744BC-E822-680E-9CEB-D0FBA903A8EE}.Release|x64.ActiveCfg = Release|x64 - {DA0744BC-E822-680E-9CEB-D0FBA903A8EE}.Release|x64.Build.0 = Release|x64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Debug|ARM64.Build.0 = Debug|ARM64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Debug|x64.ActiveCfg = Debug|x64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Debug|x64.Build.0 = Debug|x64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Release|ARM64.ActiveCfg = Release|ARM64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Release|ARM64.Build.0 = Release|ARM64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Release|x64.ActiveCfg = Release|x64 - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Release|x64.Build.0 = Release|x64 - {43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Debug|ARM64.Build.0 = Debug|ARM64 - {43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Debug|x64.ActiveCfg = Debug|x64 - {43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Debug|x64.Build.0 = Debug|x64 - {43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Release|ARM64.ActiveCfg = Release|ARM64 - {43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Release|ARM64.Build.0 = Release|ARM64 - {43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Release|x64.ActiveCfg = Release|x64 - {43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Release|x64.Build.0 = Release|x64 - {2CF78CF7-8FEB-4BE1-9591-55FA25B48FC6}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {2CF78CF7-8FEB-4BE1-9591-55FA25B48FC6}.Debug|ARM64.Build.0 = Debug|ARM64 - {2CF78CF7-8FEB-4BE1-9591-55FA25B48FC6}.Debug|x64.ActiveCfg = Debug|x64 - {2CF78CF7-8FEB-4BE1-9591-55FA25B48FC6}.Debug|x64.Build.0 = Debug|x64 - {2CF78CF7-8FEB-4BE1-9591-55FA25B48FC6}.Release|ARM64.ActiveCfg = Release|ARM64 - {2CF78CF7-8FEB-4BE1-9591-55FA25B48FC6}.Release|ARM64.Build.0 = Release|ARM64 - {2CF78CF7-8FEB-4BE1-9591-55FA25B48FC6}.Release|x64.ActiveCfg = Release|x64 - {2CF78CF7-8FEB-4BE1-9591-55FA25B48FC6}.Release|x64.Build.0 = Release|x64 - {14AFD976-B4D2-49D0-9E6C-AA93CC061B8A}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {14AFD976-B4D2-49D0-9E6C-AA93CC061B8A}.Debug|ARM64.Build.0 = Debug|ARM64 - {14AFD976-B4D2-49D0-9E6C-AA93CC061B8A}.Debug|x64.ActiveCfg = Debug|x64 - {14AFD976-B4D2-49D0-9E6C-AA93CC061B8A}.Debug|x64.Build.0 = Debug|x64 - {14AFD976-B4D2-49D0-9E6C-AA93CC061B8A}.Release|ARM64.ActiveCfg = Release|ARM64 - {14AFD976-B4D2-49D0-9E6C-AA93CC061B8A}.Release|ARM64.Build.0 = Release|ARM64 - {14AFD976-B4D2-49D0-9E6C-AA93CC061B8A}.Release|x64.ActiveCfg = Release|x64 - {14AFD976-B4D2-49D0-9E6C-AA93CC061B8A}.Release|x64.Build.0 = Release|x64 - {9D3F3793-EFE3-4525-8782-238015DABA62}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {9D3F3793-EFE3-4525-8782-238015DABA62}.Debug|ARM64.Build.0 = Debug|ARM64 - {9D3F3793-EFE3-4525-8782-238015DABA62}.Debug|x64.ActiveCfg = Debug|x64 - {9D3F3793-EFE3-4525-8782-238015DABA62}.Debug|x64.Build.0 = Debug|x64 - {9D3F3793-EFE3-4525-8782-238015DABA62}.Release|ARM64.ActiveCfg = Release|ARM64 - {9D3F3793-EFE3-4525-8782-238015DABA62}.Release|ARM64.Build.0 = Release|ARM64 - {9D3F3793-EFE3-4525-8782-238015DABA62}.Release|x64.ActiveCfg = Release|x64 - {9D3F3793-EFE3-4525-8782-238015DABA62}.Release|x64.Build.0 = Release|x64 - {24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Debug|ARM64.Build.0 = Debug|ARM64 - {24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Debug|x64.ActiveCfg = Debug|x64 - {24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Debug|x64.Build.0 = Debug|x64 - {24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Release|ARM64.ActiveCfg = Release|ARM64 - {24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Release|ARM64.Build.0 = Release|ARM64 - {24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Release|x64.ActiveCfg = Release|x64 - {24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Release|x64.Build.0 = Release|x64 - {070AC093-C9F2-20AD-0BCD-F318FC2761EA}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {070AC093-C9F2-20AD-0BCD-F318FC2761EA}.Debug|ARM64.Build.0 = Debug|ARM64 - {070AC093-C9F2-20AD-0BCD-F318FC2761EA}.Debug|x64.ActiveCfg = Debug|x64 - {070AC093-C9F2-20AD-0BCD-F318FC2761EA}.Debug|x64.Build.0 = Debug|x64 - {070AC093-C9F2-20AD-0BCD-F318FC2761EA}.Release|ARM64.ActiveCfg = Release|ARM64 - {070AC093-C9F2-20AD-0BCD-F318FC2761EA}.Release|ARM64.Build.0 = Release|ARM64 - {070AC093-C9F2-20AD-0BCD-F318FC2761EA}.Release|x64.ActiveCfg = Release|x64 - {070AC093-C9F2-20AD-0BCD-F318FC2761EA}.Release|x64.Build.0 = Release|x64 - {4122388B-59E4-CDB0-0338-EA6881DF86F0}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {4122388B-59E4-CDB0-0338-EA6881DF86F0}.Debug|ARM64.Build.0 = Debug|ARM64 - {4122388B-59E4-CDB0-0338-EA6881DF86F0}.Debug|x64.ActiveCfg = Debug|x64 - {4122388B-59E4-CDB0-0338-EA6881DF86F0}.Debug|x64.Build.0 = Debug|x64 - {4122388B-59E4-CDB0-0338-EA6881DF86F0}.Release|ARM64.ActiveCfg = Release|ARM64 - {4122388B-59E4-CDB0-0338-EA6881DF86F0}.Release|ARM64.Build.0 = Release|ARM64 - {4122388B-59E4-CDB0-0338-EA6881DF86F0}.Release|x64.ActiveCfg = Release|x64 - {4122388B-59E4-CDB0-0338-EA6881DF86F0}.Release|x64.Build.0 = Release|x64 - {988C9FAF-5AEC-EB15-578D-FED0DF52BF55}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {988C9FAF-5AEC-EB15-578D-FED0DF52BF55}.Debug|ARM64.Build.0 = Debug|ARM64 - {988C9FAF-5AEC-EB15-578D-FED0DF52BF55}.Debug|x64.ActiveCfg = Debug|x64 - {988C9FAF-5AEC-EB15-578D-FED0DF52BF55}.Debug|x64.Build.0 = Debug|x64 - {988C9FAF-5AEC-EB15-578D-FED0DF52BF55}.Release|ARM64.ActiveCfg = Release|ARM64 - {988C9FAF-5AEC-EB15-578D-FED0DF52BF55}.Release|ARM64.Build.0 = Release|ARM64 - {988C9FAF-5AEC-EB15-578D-FED0DF52BF55}.Release|x64.ActiveCfg = Release|x64 - {988C9FAF-5AEC-EB15-578D-FED0DF52BF55}.Release|x64.Build.0 = Release|x64 - {6748A29D-DA6A-033A-825B-752295FF6AA0}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6748A29D-DA6A-033A-825B-752295FF6AA0}.Debug|ARM64.Build.0 = Debug|ARM64 - {6748A29D-DA6A-033A-825B-752295FF6AA0}.Debug|x64.ActiveCfg = Debug|x64 - {6748A29D-DA6A-033A-825B-752295FF6AA0}.Debug|x64.Build.0 = Debug|x64 - {6748A29D-DA6A-033A-825B-752295FF6AA0}.Release|ARM64.ActiveCfg = Release|ARM64 - {6748A29D-DA6A-033A-825B-752295FF6AA0}.Release|ARM64.Build.0 = Release|ARM64 - {6748A29D-DA6A-033A-825B-752295FF6AA0}.Release|x64.ActiveCfg = Release|x64 - {6748A29D-DA6A-033A-825B-752295FF6AA0}.Release|x64.Build.0 = Release|x64 - {6EABCF9A-6526-441F-932F-658B1DC3E403}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6EABCF9A-6526-441F-932F-658B1DC3E403}.Debug|ARM64.Build.0 = Debug|ARM64 - {6EABCF9A-6526-441F-932F-658B1DC3E403}.Debug|x64.ActiveCfg = Debug|x64 - {6EABCF9A-6526-441F-932F-658B1DC3E403}.Debug|x64.Build.0 = Debug|x64 - {6EABCF9A-6526-441F-932F-658B1DC3E403}.Release|ARM64.ActiveCfg = Release|ARM64 - {6EABCF9A-6526-441F-932F-658B1DC3E403}.Release|ARM64.Build.0 = Release|ARM64 - {6EABCF9A-6526-441F-932F-658B1DC3E403}.Release|x64.ActiveCfg = Release|x64 - {6EABCF9A-6526-441F-932F-658B1DC3E403}.Release|x64.Build.0 = Release|x64 - {69D76A76-6EF6-4846-94CD-EAAF0CAC9F15}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {69D76A76-6EF6-4846-94CD-EAAF0CAC9F15}.Debug|ARM64.Build.0 = Debug|ARM64 - {69D76A76-6EF6-4846-94CD-EAAF0CAC9F15}.Debug|x64.ActiveCfg = Debug|x64 - {69D76A76-6EF6-4846-94CD-EAAF0CAC9F15}.Debug|x64.Build.0 = Debug|x64 - {69D76A76-6EF6-4846-94CD-EAAF0CAC9F15}.Release|ARM64.ActiveCfg = Release|ARM64 - {69D76A76-6EF6-4846-94CD-EAAF0CAC9F15}.Release|ARM64.Build.0 = Release|ARM64 - {69D76A76-6EF6-4846-94CD-EAAF0CAC9F15}.Release|x64.ActiveCfg = Release|x64 - {69D76A76-6EF6-4846-94CD-EAAF0CAC9F15}.Release|x64.Build.0 = Release|x64 - {9BAFFC28-E1EF-4C14-A101-EEBFC0A50D83}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {9BAFFC28-E1EF-4C14-A101-EEBFC0A50D83}.Debug|ARM64.Build.0 = Debug|ARM64 - {9BAFFC28-E1EF-4C14-A101-EEBFC0A50D83}.Debug|x64.ActiveCfg = Debug|x64 - {9BAFFC28-E1EF-4C14-A101-EEBFC0A50D83}.Debug|x64.Build.0 = Debug|x64 - {9BAFFC28-E1EF-4C14-A101-EEBFC0A50D83}.Release|ARM64.ActiveCfg = Release|ARM64 - {9BAFFC28-E1EF-4C14-A101-EEBFC0A50D83}.Release|ARM64.Build.0 = Release|ARM64 - {9BAFFC28-E1EF-4C14-A101-EEBFC0A50D83}.Release|x64.ActiveCfg = Release|x64 - {9BAFFC28-E1EF-4C14-A101-EEBFC0A50D83}.Release|x64.Build.0 = Release|x64 - {806BF185-8B89-5BE1-9AA1-DA5BC9487DB9}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {806BF185-8B89-5BE1-9AA1-DA5BC9487DB9}.Debug|ARM64.Build.0 = Debug|ARM64 - {806BF185-8B89-5BE1-9AA1-DA5BC9487DB9}.Debug|x64.ActiveCfg = Debug|x64 - {806BF185-8B89-5BE1-9AA1-DA5BC9487DB9}.Debug|x64.Build.0 = Debug|x64 - {806BF185-8B89-5BE1-9AA1-DA5BC9487DB9}.Release|ARM64.ActiveCfg = Release|ARM64 - {806BF185-8B89-5BE1-9AA1-DA5BC9487DB9}.Release|ARM64.Build.0 = Release|ARM64 - {806BF185-8B89-5BE1-9AA1-DA5BC9487DB9}.Release|x64.ActiveCfg = Release|x64 - {806BF185-8B89-5BE1-9AA1-DA5BC9487DB9}.Release|x64.Build.0 = Release|x64 - {F93C2817-C846-4259-84D8-B39A6B57C8DE}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {F93C2817-C846-4259-84D8-B39A6B57C8DE}.Debug|ARM64.Build.0 = Debug|ARM64 - {F93C2817-C846-4259-84D8-B39A6B57C8DE}.Debug|x64.ActiveCfg = Debug|x64 - {F93C2817-C846-4259-84D8-B39A6B57C8DE}.Debug|x64.Build.0 = Debug|x64 - {F93C2817-C846-4259-84D8-B39A6B57C8DE}.Release|ARM64.ActiveCfg = Release|ARM64 - {F93C2817-C846-4259-84D8-B39A6B57C8DE}.Release|ARM64.Build.0 = Release|ARM64 - {F93C2817-C846-4259-84D8-B39A6B57C8DE}.Release|x64.ActiveCfg = Release|x64 - {F93C2817-C846-4259-84D8-B39A6B57C8DE}.Release|x64.Build.0 = Release|x64 - {E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Debug|ARM64.Build.0 = Debug|ARM64 - {E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Debug|x64.ActiveCfg = Debug|x64 - {E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Debug|x64.Build.0 = Debug|x64 - {E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Release|ARM64.ActiveCfg = Release|ARM64 - {E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Release|ARM64.Build.0 = Release|ARM64 - {E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Release|x64.ActiveCfg = Release|x64 - {E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Release|x64.Build.0 = Release|x64 - {E816D7AD-4688-4ECB-97CC-3D8E798F3826}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {E816D7AD-4688-4ECB-97CC-3D8E798F3826}.Debug|ARM64.Build.0 = Debug|ARM64 - {E816D7AD-4688-4ECB-97CC-3D8E798F3826}.Debug|x64.ActiveCfg = Debug|x64 - {E816D7AD-4688-4ECB-97CC-3D8E798F3826}.Debug|x64.Build.0 = Debug|x64 - {E816D7AD-4688-4ECB-97CC-3D8E798F3826}.Release|ARM64.ActiveCfg = Release|ARM64 - {E816D7AD-4688-4ECB-97CC-3D8E798F3826}.Release|ARM64.Build.0 = Release|ARM64 - {E816D7AD-4688-4ECB-97CC-3D8E798F3826}.Release|x64.ActiveCfg = Release|x64 - {E816D7AD-4688-4ECB-97CC-3D8E798F3826}.Release|x64.Build.0 = Release|x64 - {E816D7AE-4688-4ECB-97CC-3D8E798F3827}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {E816D7AE-4688-4ECB-97CC-3D8E798F3827}.Debug|ARM64.Build.0 = Debug|ARM64 - {E816D7AE-4688-4ECB-97CC-3D8E798F3827}.Debug|x64.ActiveCfg = Debug|x64 - {E816D7AE-4688-4ECB-97CC-3D8E798F3827}.Debug|x64.Build.0 = Debug|x64 - {E816D7AE-4688-4ECB-97CC-3D8E798F3827}.Release|ARM64.ActiveCfg = Release|ARM64 - {E816D7AE-4688-4ECB-97CC-3D8E798F3827}.Release|ARM64.Build.0 = Release|ARM64 - {E816D7AE-4688-4ECB-97CC-3D8E798F3827}.Release|x64.ActiveCfg = Release|x64 - {E816D7AE-4688-4ECB-97CC-3D8E798F3827}.Release|x64.Build.0 = Release|x64 - {E816D7AF-4688-4ECB-97CC-3D8E798F3828}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {E816D7AF-4688-4ECB-97CC-3D8E798F3828}.Debug|ARM64.Build.0 = Debug|ARM64 - {E816D7AF-4688-4ECB-97CC-3D8E798F3828}.Debug|x64.ActiveCfg = Debug|x64 - {E816D7AF-4688-4ECB-97CC-3D8E798F3828}.Debug|x64.Build.0 = Debug|x64 - {E816D7AF-4688-4ECB-97CC-3D8E798F3828}.Release|ARM64.ActiveCfg = Release|ARM64 - {E816D7AF-4688-4ECB-97CC-3D8E798F3828}.Release|ARM64.Build.0 = Release|ARM64 - {E816D7AF-4688-4ECB-97CC-3D8E798F3828}.Release|x64.ActiveCfg = Release|x64 - {E816D7AF-4688-4ECB-97CC-3D8E798F3828}.Release|x64.Build.0 = Release|x64 - {E816D7B0-4688-4ECB-97CC-3D8E798F3829}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {E816D7B0-4688-4ECB-97CC-3D8E798F3829}.Debug|ARM64.Build.0 = Debug|ARM64 - {E816D7B0-4688-4ECB-97CC-3D8E798F3829}.Debug|x64.ActiveCfg = Debug|x64 - {E816D7B0-4688-4ECB-97CC-3D8E798F3829}.Debug|x64.Build.0 = Debug|x64 - {E816D7B0-4688-4ECB-97CC-3D8E798F3829}.Release|ARM64.ActiveCfg = Release|ARM64 - {E816D7B0-4688-4ECB-97CC-3D8E798F3829}.Release|ARM64.Build.0 = Release|ARM64 - {E816D7B0-4688-4ECB-97CC-3D8E798F3829}.Release|x64.ActiveCfg = Release|x64 - {E816D7B0-4688-4ECB-97CC-3D8E798F3829}.Release|x64.Build.0 = Release|x64 - {00D8659C-2068-40B6-8B86-759CD6284BBB}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {00D8659C-2068-40B6-8B86-759CD6284BBB}.Debug|ARM64.Build.0 = Debug|ARM64 - {00D8659C-2068-40B6-8B86-759CD6284BBB}.Debug|x64.ActiveCfg = Debug|x64 - {00D8659C-2068-40B6-8B86-759CD6284BBB}.Debug|x64.Build.0 = Debug|x64 - {00D8659C-2068-40B6-8B86-759CD6284BBB}.Release|ARM64.ActiveCfg = Release|ARM64 - {00D8659C-2068-40B6-8B86-759CD6284BBB}.Release|ARM64.Build.0 = Release|ARM64 - {00D8659C-2068-40B6-8B86-759CD6284BBB}.Release|x64.ActiveCfg = Release|x64 - {00D8659C-2068-40B6-8B86-759CD6284BBB}.Release|x64.Build.0 = Release|x64 - {38177D56-6AD1-4ADF-88C9-2843A7932166}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {38177D56-6AD1-4ADF-88C9-2843A7932166}.Debug|ARM64.Build.0 = Debug|ARM64 - {38177D56-6AD1-4ADF-88C9-2843A7932166}.Debug|x64.ActiveCfg = Debug|x64 - {38177D56-6AD1-4ADF-88C9-2843A7932166}.Debug|x64.Build.0 = Debug|x64 - {38177D56-6AD1-4ADF-88C9-2843A7932166}.Release|ARM64.ActiveCfg = Release|ARM64 - {38177D56-6AD1-4ADF-88C9-2843A7932166}.Release|ARM64.Build.0 = Release|ARM64 - {38177D56-6AD1-4ADF-88C9-2843A7932166}.Release|x64.ActiveCfg = Release|x64 - {38177D56-6AD1-4ADF-88C9-2843A7932166}.Release|x64.Build.0 = Release|x64 - {08E71C67-6A7E-4CA1-B04E-2FB336410BAC}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {08E71C67-6A7E-4CA1-B04E-2FB336410BAC}.Debug|ARM64.Build.0 = Debug|ARM64 - {08E71C67-6A7E-4CA1-B04E-2FB336410BAC}.Debug|x64.ActiveCfg = Debug|x64 - {08E71C67-6A7E-4CA1-B04E-2FB336410BAC}.Debug|x64.Build.0 = Debug|x64 - {08E71C67-6A7E-4CA1-B04E-2FB336410BAC}.Release|ARM64.ActiveCfg = Release|ARM64 - {08E71C67-6A7E-4CA1-B04E-2FB336410BAC}.Release|ARM64.Build.0 = Release|ARM64 - {08E71C67-6A7E-4CA1-B04E-2FB336410BAC}.Release|x64.ActiveCfg = Release|x64 - {08E71C67-6A7E-4CA1-B04E-2FB336410BAC}.Release|x64.Build.0 = Release|x64 - {66C069F8-C548-4CA6-8CDE-239104D68E88}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {66C069F8-C548-4CA6-8CDE-239104D68E88}.Debug|ARM64.Build.0 = Debug|ARM64 - {66C069F8-C548-4CA6-8CDE-239104D68E88}.Debug|x64.ActiveCfg = Debug|x64 - {66C069F8-C548-4CA6-8CDE-239104D68E88}.Debug|x64.Build.0 = Debug|x64 - {66C069F8-C548-4CA6-8CDE-239104D68E88}.Release|ARM64.ActiveCfg = Release|ARM64 - {66C069F8-C548-4CA6-8CDE-239104D68E88}.Release|ARM64.Build.0 = Release|ARM64 - {66C069F8-C548-4CA6-8CDE-239104D68E88}.Release|x64.ActiveCfg = Release|x64 - {66C069F8-C548-4CA6-8CDE-239104D68E88}.Release|x64.Build.0 = Release|x64 - {94CDC147-6137-45E9-AEDE-17FF809607C0}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {94CDC147-6137-45E9-AEDE-17FF809607C0}.Debug|ARM64.Build.0 = Debug|ARM64 - {94CDC147-6137-45E9-AEDE-17FF809607C0}.Debug|x64.ActiveCfg = Debug|x64 - {94CDC147-6137-45E9-AEDE-17FF809607C0}.Debug|x64.Build.0 = Debug|x64 - {94CDC147-6137-45E9-AEDE-17FF809607C0}.Release|ARM64.ActiveCfg = Release|ARM64 - {94CDC147-6137-45E9-AEDE-17FF809607C0}.Release|ARM64.Build.0 = Release|ARM64 - {94CDC147-6137-45E9-AEDE-17FF809607C0}.Release|x64.ActiveCfg = Release|x64 - {94CDC147-6137-45E9-AEDE-17FF809607C0}.Release|x64.Build.0 = Release|x64 - {A24BF1AF-79AA-4896-BAE3-CCBBE0380A78}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {A24BF1AF-79AA-4896-BAE3-CCBBE0380A78}.Debug|ARM64.Build.0 = Debug|ARM64 - {A24BF1AF-79AA-4896-BAE3-CCBBE0380A78}.Debug|x64.ActiveCfg = Debug|x64 - {A24BF1AF-79AA-4896-BAE3-CCBBE0380A78}.Debug|x64.Build.0 = Debug|x64 - {A24BF1AF-79AA-4896-BAE3-CCBBE0380A78}.Release|ARM64.ActiveCfg = Release|ARM64 - {A24BF1AF-79AA-4896-BAE3-CCBBE0380A78}.Release|ARM64.Build.0 = Release|ARM64 - {A24BF1AF-79AA-4896-BAE3-CCBBE0380A78}.Release|x64.ActiveCfg = Release|x64 - {A24BF1AF-79AA-4896-BAE3-CCBBE0380A78}.Release|x64.Build.0 = Release|x64 - {E816D7B1-4688-4ECB-97CC-3D8E798F3830}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {E816D7B1-4688-4ECB-97CC-3D8E798F3830}.Debug|ARM64.Build.0 = Debug|ARM64 - {E816D7B1-4688-4ECB-97CC-3D8E798F3830}.Debug|x64.ActiveCfg = Debug|x64 - {E816D7B1-4688-4ECB-97CC-3D8E798F3830}.Debug|x64.Build.0 = Debug|x64 - {E816D7B1-4688-4ECB-97CC-3D8E798F3830}.Release|ARM64.ActiveCfg = Release|ARM64 - {E816D7B1-4688-4ECB-97CC-3D8E798F3830}.Release|ARM64.Build.0 = Release|ARM64 - {E816D7B1-4688-4ECB-97CC-3D8E798F3830}.Release|x64.ActiveCfg = Release|x64 - {E816D7B1-4688-4ECB-97CC-3D8E798F3830}.Release|x64.Build.0 = Release|x64 - {E816D7B3-4688-4ECB-97CC-3D8E798F3832}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {E816D7B3-4688-4ECB-97CC-3D8E798F3832}.Debug|ARM64.Build.0 = Debug|ARM64 - {E816D7B3-4688-4ECB-97CC-3D8E798F3832}.Debug|x64.ActiveCfg = Debug|x64 - {E816D7B3-4688-4ECB-97CC-3D8E798F3832}.Debug|x64.Build.0 = Debug|x64 - {E816D7B3-4688-4ECB-97CC-3D8E798F3832}.Release|ARM64.ActiveCfg = Release|ARM64 - {E816D7B3-4688-4ECB-97CC-3D8E798F3832}.Release|ARM64.Build.0 = Release|ARM64 - {E816D7B3-4688-4ECB-97CC-3D8E798F3832}.Release|x64.ActiveCfg = Release|x64 - {E816D7B3-4688-4ECB-97CC-3D8E798F3832}.Release|x64.Build.0 = Release|x64 - {E816D7B2-4688-4ECB-97CC-3D8E798F3831}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {E816D7B2-4688-4ECB-97CC-3D8E798F3831}.Debug|ARM64.Build.0 = Debug|ARM64 - {E816D7B2-4688-4ECB-97CC-3D8E798F3831}.Debug|x64.ActiveCfg = Debug|x64 - {E816D7B2-4688-4ECB-97CC-3D8E798F3831}.Debug|x64.Build.0 = Debug|x64 - {E816D7B2-4688-4ECB-97CC-3D8E798F3831}.Release|ARM64.ActiveCfg = Release|ARM64 - {E816D7B2-4688-4ECB-97CC-3D8E798F3831}.Release|ARM64.Build.0 = Release|ARM64 - {E816D7B2-4688-4ECB-97CC-3D8E798F3831}.Release|x64.ActiveCfg = Release|x64 - {E816D7B2-4688-4ECB-97CC-3D8E798F3831}.Release|x64.Build.0 = Release|x64 - {E816D7B4-4688-4ECB-97CC-3D8E798F3833}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {E816D7B4-4688-4ECB-97CC-3D8E798F3833}.Debug|ARM64.Build.0 = Debug|ARM64 - {E816D7B4-4688-4ECB-97CC-3D8E798F3833}.Debug|x64.ActiveCfg = Debug|x64 - {E816D7B4-4688-4ECB-97CC-3D8E798F3833}.Debug|x64.Build.0 = Debug|x64 - {E816D7B4-4688-4ECB-97CC-3D8E798F3833}.Release|ARM64.ActiveCfg = Release|ARM64 - {E816D7B4-4688-4ECB-97CC-3D8E798F3833}.Release|ARM64.Build.0 = Release|ARM64 - {E816D7B4-4688-4ECB-97CC-3D8E798F3833}.Release|x64.ActiveCfg = Release|x64 - {E816D7B4-4688-4ECB-97CC-3D8E798F3833}.Release|x64.Build.0 = Release|x64 - {48A1DB8C-5DF8-4FB3-9E14-2B67F3F2D8B5}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {48A1DB8C-5DF8-4FB3-9E14-2B67F3F2D8B5}.Debug|ARM64.Build.0 = Debug|ARM64 - {48A1DB8C-5DF8-4FB3-9E14-2B67F3F2D8B5}.Debug|x64.ActiveCfg = Debug|x64 - {48A1DB8C-5DF8-4FB3-9E14-2B67F3F2D8B5}.Debug|x64.Build.0 = Debug|x64 - {48A1DB8C-5DF8-4FB3-9E14-2B67F3F2D8B5}.Release|ARM64.ActiveCfg = Release|ARM64 - {48A1DB8C-5DF8-4FB3-9E14-2B67F3F2D8B5}.Release|ARM64.Build.0 = Release|ARM64 - {48A1DB8C-5DF8-4FB3-9E14-2B67F3F2D8B5}.Release|x64.ActiveCfg = Release|x64 - {48A1DB8C-5DF8-4FB3-9E14-2B67F3F2D8B5}.Release|x64.Build.0 = Release|x64 - {F5333ED7-06D8-4AB3-953A-36D63F08CB6F}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {F5333ED7-06D8-4AB3-953A-36D63F08CB6F}.Debug|ARM64.Build.0 = Debug|ARM64 - {F5333ED7-06D8-4AB3-953A-36D63F08CB6F}.Debug|ARM64.Deploy.0 = Debug|ARM64 - {F5333ED7-06D8-4AB3-953A-36D63F08CB6F}.Debug|x64.ActiveCfg = Debug|x64 - {F5333ED7-06D8-4AB3-953A-36D63F08CB6F}.Debug|x64.Build.0 = Debug|x64 - {F5333ED7-06D8-4AB3-953A-36D63F08CB6F}.Debug|x64.Deploy.0 = Debug|x64 - {F5333ED7-06D8-4AB3-953A-36D63F08CB6F}.Release|ARM64.ActiveCfg = Release|ARM64 - {F5333ED7-06D8-4AB3-953A-36D63F08CB6F}.Release|ARM64.Build.0 = Release|ARM64 - {F5333ED7-06D8-4AB3-953A-36D63F08CB6F}.Release|ARM64.Deploy.0 = Release|ARM64 - {F5333ED7-06D8-4AB3-953A-36D63F08CB6F}.Release|x64.ActiveCfg = Release|x64 - {F5333ED7-06D8-4AB3-953A-36D63F08CB6F}.Release|x64.Build.0 = Release|x64 - {F5333ED7-06D8-4AB3-953A-36D63F08CB6F}.Release|x64.Deploy.0 = Release|x64 - {4E0FCF69-B06B-D272-76BF-ED3A559B4EDA}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {4E0FCF69-B06B-D272-76BF-ED3A559B4EDA}.Debug|ARM64.Build.0 = Debug|ARM64 - {4E0FCF69-B06B-D272-76BF-ED3A559B4EDA}.Debug|x64.ActiveCfg = Debug|x64 - {4E0FCF69-B06B-D272-76BF-ED3A559B4EDA}.Debug|x64.Build.0 = Debug|x64 - {4E0FCF69-B06B-D272-76BF-ED3A559B4EDA}.Release|ARM64.ActiveCfg = Release|ARM64 - {4E0FCF69-B06B-D272-76BF-ED3A559B4EDA}.Release|ARM64.Build.0 = Release|ARM64 - {4E0FCF69-B06B-D272-76BF-ED3A559B4EDA}.Release|x64.ActiveCfg = Release|x64 - {4E0FCF69-B06B-D272-76BF-ED3A559B4EDA}.Release|x64.Build.0 = Release|x64 - {45354F4F-1414-45CE-B600-51CD1209FD19}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {45354F4F-1414-45CE-B600-51CD1209FD19}.Debug|ARM64.Build.0 = Debug|ARM64 - {45354F4F-1414-45CE-B600-51CD1209FD19}.Debug|x64.ActiveCfg = Debug|x64 - {45354F4F-1414-45CE-B600-51CD1209FD19}.Debug|x64.Build.0 = Debug|x64 - {45354F4F-1414-45CE-B600-51CD1209FD19}.Release|ARM64.ActiveCfg = Release|ARM64 - {45354F4F-1414-45CE-B600-51CD1209FD19}.Release|ARM64.Build.0 = Release|ARM64 - {45354F4F-1414-45CE-B600-51CD1209FD19}.Release|x64.ActiveCfg = Release|x64 - {45354F4F-1414-45CE-B600-51CD1209FD19}.Release|x64.Build.0 = Release|x64 - {A66E9270-5D93-EC9C-F06E-CE7295BB9A6C}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {A66E9270-5D93-EC9C-F06E-CE7295BB9A6C}.Debug|ARM64.Build.0 = Debug|ARM64 - {A66E9270-5D93-EC9C-F06E-CE7295BB9A6C}.Debug|x64.ActiveCfg = Debug|x64 - {A66E9270-5D93-EC9C-F06E-CE7295BB9A6C}.Debug|x64.Build.0 = Debug|x64 - {A66E9270-5D93-EC9C-F06E-CE7295BB9A6C}.Release|ARM64.ActiveCfg = Release|ARM64 - {A66E9270-5D93-EC9C-F06E-CE7295BB9A6C}.Release|ARM64.Build.0 = Release|ARM64 - {A66E9270-5D93-EC9C-F06E-CE7295BB9A6C}.Release|x64.ActiveCfg = Release|x64 - {A66E9270-5D93-EC9C-F06E-CE7295BB9A6C}.Release|x64.Build.0 = Release|x64 - {2B3FB837-23DE-629F-82C6-42304E7083C9}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {2B3FB837-23DE-629F-82C6-42304E7083C9}.Debug|ARM64.Build.0 = Debug|ARM64 - {2B3FB837-23DE-629F-82C6-42304E7083C9}.Debug|x64.ActiveCfg = Debug|x64 - {2B3FB837-23DE-629F-82C6-42304E7083C9}.Debug|x64.Build.0 = Debug|x64 - {2B3FB837-23DE-629F-82C6-42304E7083C9}.Release|ARM64.ActiveCfg = Release|ARM64 - {2B3FB837-23DE-629F-82C6-42304E7083C9}.Release|ARM64.Build.0 = Release|ARM64 - {2B3FB837-23DE-629F-82C6-42304E7083C9}.Release|x64.ActiveCfg = Release|x64 - {2B3FB837-23DE-629F-82C6-42304E7083C9}.Release|x64.Build.0 = Release|x64 - {DB34808A-FF91-D06E-A426-AFB5A8BD583B}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {DB34808A-FF91-D06E-A426-AFB5A8BD583B}.Debug|ARM64.Build.0 = Debug|ARM64 - {DB34808A-FF91-D06E-A426-AFB5A8BD583B}.Debug|x64.ActiveCfg = Debug|x64 - {DB34808A-FF91-D06E-A426-AFB5A8BD583B}.Debug|x64.Build.0 = Debug|x64 - {DB34808A-FF91-D06E-A426-AFB5A8BD583B}.Release|ARM64.ActiveCfg = Release|ARM64 - {DB34808A-FF91-D06E-A426-AFB5A8BD583B}.Release|ARM64.Build.0 = Release|ARM64 - {DB34808A-FF91-D06E-A426-AFB5A8BD583B}.Release|x64.ActiveCfg = Release|x64 - {DB34808A-FF91-D06E-A426-AFB5A8BD583B}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {3BB8493E-D18E-4485-A320-CB40F90F55AE} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD} - {9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9} = {264B412F-DB8B-4CF8-A74B-96998B183045} - {1A066C63-64B3-45F8-92FE-664E1CCE8077} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {5CCC8468-DEC8-4D36-99D4-5C891BEBD481} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD} - {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {B25AC7A5-FB9F-4789-B392-D5C85E948670} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3} - {51920F1F-C28C-4ADF-8660-4238766796C2} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3} - {A3935CF4-46C5-4A88-84D3-6B12E16E6BA2} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3} - {2151F984-E006-4A9F-92EF-C6DDE3DC8413} = {66E1534A-1587-42B2-912F-45C994D32904} - {89F34AF7-1C34-4A72-AA6E-534BCF972BD9} = {38BDB927-829B-4C65-9CD9-93FB05D66D65} - {6C7F47CC-2151-44A3-A546-41C70025132C} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {2BE46397-4DFA-414C-9BD4-41E4BBF8CB34} = {6C7F47CC-2151-44A3-A546-41C70025132C} - {0B43679E-EDFA-4DA0-AD30-F4628B308B1B} = {6C7F47CC-2151-44A3-A546-41C70025132C} - {E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8} = {0E556541-6A45-42CB-AE49-EE5A9BE05E7C} - {17DA04DF-E393-4397-9CF0-84DABE11032E} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {38BDB927-829B-4C65-9CD9-93FB05D66D65} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {8AFFA899-0B73-49EC-8C50-0FADDA57B2FC} = {38BDB927-829B-4C65-9CD9-93FB05D66D65} - {C140A3EF-6DBF-4084-9D4C-4EB5A99FEE68} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {4FD29318-A8AB-4D8F-AA47-60BC241B8DA3} = {C140A3EF-6DBF-4084-9D4C-4EB5A99FEE68} - {8451ECDD-2EA4-4966-BB0A-7BBC40138E80} = {C140A3EF-6DBF-4084-9D4C-4EB5A99FEE68} - {FF742965-9A80-41A5-B042-D6C7D3A21708} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F} - {4AFC9975-2456-4C70-94A4-84073C1CED93} = {C140A3EF-6DBF-4084-9D4C-4EB5A99FEE68} - {59BD9891-3837-438A-958D-ADC7F91F6F7E} = {4AFC9975-2456-4C70-94A4-84073C1CED93} - {4D971245-7A70-41D5-BAA0-DDB5684CAF51} = {4AFC9975-2456-4C70-94A4-84073C1CED93} - {74F1B9ED-F59C-4FE7-B473-7B453E30837E} = {4AFC9975-2456-4C70-94A4-84073C1CED93} - {FDB3555B-58EF-4AE6-B5F1-904719637AB4} = {4AFC9975-2456-4C70-94A4-84073C1CED93} - {C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0} = {4AFC9975-2456-4C70-94A4-84073C1CED93} - {F8B870EB-D5F5-45BA-9CF7-A5C459818820} = {4AFC9975-2456-4C70-94A4-84073C1CED93} - {E364F67B-BB12-4E91-B639-355866EBCD8B} = {C140A3EF-6DBF-4084-9D4C-4EB5A99FEE68} - {F97E5003-F263-4D4A-A964-0F1F3C82DEF2} = {C140A3EF-6DBF-4084-9D4C-4EB5A99FEE68} - {2F305555-C296-497E-AC20-5FA1B237996A} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {AF2349B8-E5B6-4004-9502-687C1C7730B1} = {2F305555-C296-497E-AC20-5FA1B237996A} - {6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB} = {2F305555-C296-497E-AC20-5FA1B237996A} - {A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704} - {DA425894-6E13-404F-8DCB-78584EC0557A} = {2F305555-C296-497E-AC20-5FA1B237996A} - {060D75DA-2D1C-48E6-A4A1-6F0718B64661} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704} - {748417CA-F17E-487F-9411-CAFB6D3F4877} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704} - {217DF501-135C-4E38-BFC8-99D4821032EA} = {2F305555-C296-497E-AC20-5FA1B237996A} - {B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A} = {C3081D9A-1586-441A-B5F4-ED815B3719C1} - {787B8AA6-CA93-4C84-96FE-DF31110AD1C4} = {4AFC9975-2456-4C70-94A4-84073C1CED93} - {08C8C05F-0362-41BC-818C-724572DF8B06} = {C140A3EF-6DBF-4084-9D4C-4EB5A99FEE68} - {5D00D290-4016-4CFE-9E41-1E7C724509BA} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {4AED67B6-55FD-486F-B917-E543DEE2CB3C} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {42851751-CBC8-45A6-97F5-7A0753F7B4D1} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F} - {1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704} - {8FFE09DA-FA4F-4EE1-B3A2-AD5497FBD1AD} = {2F305555-C296-497E-AC20-5FA1B237996A} - {655C9AF2-18D3-4DA6-80E4-85504A7722BA} = {1D78B84B-CA39-406C-98F4-71F7EC266CC0} - {BA58206B-1493-4C75-BFEA-A85768A1E156} = {1D78B84B-CA39-406C-98F4-71F7EC266CC0} - {1D78B84B-CA39-406C-98F4-71F7EC266CC0} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {03276A39-D4E9-417C-8FFD-200B0EE5E871} = {4AFC9975-2456-4C70-94A4-84073C1CED93} - {B81FB7B6-D30E-428F-908A-41422EFC1172} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F} - {0F85E674-34AE-443D-954C-8321EB8B93B1} = {E885E71F-0B34-4A03-B13B-20F4E05E90BB} - {632BBE62-5421-49EA-835A-7FFA4F499BD6} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F} - {7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F} = {E4E03FE0-94FD-47C7-88C5-F17D0AA549D3} - {FD8EB419-FF9C-4D88-BB6F-BF6CED37747B} = {4AFC9975-2456-4C70-94A4-84073C1CED93} - {DA5A6FE9-0040-40CC-83CC-764AE5306590} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F} - {0351ADA4-0C32-4652-9BA0-41F7B602372B} = {4AFC9975-2456-4C70-94A4-84073C1CED93} - {D9B8FC84-322A-4F9F-BBB9-20915C47DDFD} = {E4E03FE0-94FD-47C7-88C5-F17D0AA549D3} - {6955446D-23F7-4023-9BB3-8657F904AF99} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {58736667-1027-4AD7-BFDF-7A3A6474103A} = {5A7818A8-109C-4E1C-850D-1A654E234B0E} - {D92131D6-7610-4D60-A7DB-1C169783F83B} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525} = {D92131D6-7610-4D60-A7DB-1C169783F83B} - {031AC72E-FA28-4AB7-B690-6F7B9C28AA73} = {D92131D6-7610-4D60-A7DB-1C169783F83B} - {0B593A6C-4143-4337-860E-DB5710FB87DB} = {D92131D6-7610-4D60-A7DB-1C169783F83B} - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {5A7818A8-109C-4E1C-850D-1A654E234B0E} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {E4E03FE0-94FD-47C7-88C5-F17D0AA549D3} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {7319089E-46D6-4400-BC65-E39BDF1416EE} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {CABA8DFB-823B-4BF2-93AC-3F31984150D9} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {98537082-0FDB-40DE-ABD8-0DC5A4269BAB} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {B39DC643-4663-475E-B329-03F0C9918D48} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {8F62026A-294B-41C6-8839-87463613F216} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {C3A17DCA-217B-462C-BB0C-BE086AF80081} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {69E1EE8D-143A-4060-9129-4658ACF14AAF} = {2F305555-C296-497E-AC20-5FA1B237996A} - {ECC20689-002A-4354-95A6-B58DF089C6FF} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704} - {4BABF3FE-3451-42FD-873F-3C332E18DCEF} = {4AFC9975-2456-4C70-94A4-84073C1CED93} - {0648DF05-5DDA-4BE1-B5F2-584926EBDB65} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F} - {BA661F5B-1D5A-4FFC-9BF1-FC39DF280BDD} = {38BDB927-829B-4C65-9CD9-93FB05D66D65} - {E496B7FC-1E99-4BAB-849B-0E8367040B02} = {38BDB927-829B-4C65-9CD9-93FB05D66D65} - {7F4B3A60-BC27-45A7-8000-68B0B6EA7466} = {D9BD324E-1D80-44AA-8E7B-73EB00944434} - {8DF78B53-200E-451F-9328-01EB907193AE} = {38BDB927-829B-4C65-9CD9-93FB05D66D65} - {23D2070D-E4AD-4ADD-85A7-083D9C76AD49} = {38BDB927-829B-4C65-9CD9-93FB05D66D65} - {62173D9A-6724-4C00-A1C8-FB646480A9EC} = {D9BD324E-1D80-44AA-8E7B-73EB00944434} - {127F38E0-40AA-4594-B955-5616BF206882} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {5E7360A8-D048-4ED3-8F09-0BFD64C5529A} = {127F38E0-40AA-4594-B955-5616BF206882} - {D940E07F-532C-4FF3-883F-790DA014F19A} = {127F38E0-40AA-4594-B955-5616BF206882} - {BB23A474-5058-4F75-8FA3-5FE3DE53CDF4} = {4AFC9975-2456-4C70-94A4-84073C1CED93} - {3E424AD2-19E5-4AE6-B833-F53963EB5FC1} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F} - {106CBECA-0701-4FC3-838C-9DF816A19AE2} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {2D604C07-51FC-46BB-9EB7-75AECC7F5E81} = {106CBECA-0701-4FC3-838C-9DF816A19AE2} - {2EDB3EB4-FA92-4BFF-B2D8-566584837231} = {106CBECA-0701-4FC3-838C-9DF816A19AE2} - {48804216-2A0E-4168-A6D8-9CD068D14227} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD} - {FF1D7936-842A-4BBB-8BEA-E9FE796DE700} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD} - {5043CECE-E6A7-4867-9CBE-02D27D83747A} = {4AFC9975-2456-4C70-94A4-84073C1CED93} - {11491FD8-F921-48BF-880C-7FEA185B80A1} = {2F305555-C296-497E-AC20-5FA1B237996A} - {F40C3397-1834-4530-B2D9-8F8B8456BCDF} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704} - {A2D583F0-B70C-4462-B1F0-8E81AFB7BA85} = {4AFC9975-2456-4C70-94A4-84073C1CED93} - {4ED320BC-BA04-4D42-8D15-CBE62151F08B} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F} - {322566EF-20DC-43A6-B9F8-616AF942579A} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {E94FD11C-0591-456F-899F-EFC0CA548336} = {322566EF-20DC-43A6-B9F8-616AF942579A} - {782A61BE-9D85-4081-B35C-1CCC9DCC1E88} = {322566EF-20DC-43A6-B9F8-616AF942579A} - {809AA252-E17A-4FA2-B0A1-0450976B763F} = {2F305555-C296-497E-AC20-5FA1B237996A} - {133281D8-1BCE-4D07-B31E-796612A9609E} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704} - {805306FF-A562-4415-8DEF-E493BDC45918} = {2F305555-C296-497E-AC20-5FA1B237996A} - {FCF3E52D-B80A-4FC3-98FD-6391354F0EE3} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704} - {60CD2D4F-C3B9-4897-9821-FCA5098B41CE} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {1DC3BE92-CE89-43FB-8110-9C043A2FE7A2} = {60CD2D4F-C3B9-4897-9821-FCA5098B41CE} - {48A0A19E-A0BE-4256-ACF8-CC3B80291AF9} = {60CD2D4F-C3B9-4897-9821-FCA5098B41CE} - {9F94B303-5E21-4364-9362-64426F8DB932} = {4AFC9975-2456-4C70-94A4-84073C1CED93} - {EAE14C0E-7A6B-45DA-9080-A7D8C077BA6E} = {322566EF-20DC-43A6-B9F8-616AF942579A} - {F7C8C0F1-5431-4347-89D0-8E5354F93CF2} = {2F305555-C296-497E-AC20-5FA1B237996A} - {F1F6B6B6-9F18-4A17-8B5C-97DF552C53DC} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704} - {04B193D7-3E21-46B8-A958-89B63A8A69DE} = {2F305555-C296-497E-AC20-5FA1B237996A} - {5BDBD6C9-A31F-4CEB-871A-5E9E709197EF} = {4AFC9975-2456-4C70-94A4-84073C1CED93} - {FD464B4C-2F68-4D06-91E7-4208146C41F5} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F} - {8FE5A5EE-1B59-401C-9FB3-B04ECD3E29C1} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F} - {020A7474-3601-4160-A159-D7B70B77B15F} = {C3081D9A-1586-441A-B5F4-ED815B3719C1} - {27718999-C175-450A-861C-89F911E16A88} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3} - {1DBBB112-4BB1-444B-8EBB-E66555C76BA6} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3} - {5A1DB2F0-0715-4B3B-98E6-79BC41540045} = {4AFC9975-2456-4C70-94A4-84073C1CED93} - {93B72A06-C8BD-484F-A6F7-C9F280B150BF} = {6C7F47CC-2151-44A3-A546-41C70025132C} - {18B3DB45-4FFE-4D01-97D6-5223FEEE1853} = {6C7F47CC-2151-44A3-A546-41C70025132C} - {0F14491C-6369-4C45-AAA8-135814E66E6B} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {34A354C5-23C7-4343-916C-C52DAF4FC39D} = {0F14491C-6369-4C45-AAA8-135814E66E6B} - {3264DF53-C805-4B0C-867C-FCEAF7AEF762} = {0F14491C-6369-4C45-AAA8-135814E66E6B} - {31CAD28E-778A-441C-85BC-40AB3EAA2A10} = {0F14491C-6369-4C45-AAA8-135814E66E6B} - {A50C70A6-2DA0-4027-B90E-B1A40755A8A5} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {25C91A4E-BA4E-467A-85CD-8B62545BF674} = {A50C70A6-2DA0-4027-B90E-B1A40755A8A5} - {6AB6A2D6-F859-4A82-9184-0BD29C9F07D1} = {A50C70A6-2DA0-4027-B90E-B1A40755A8A5} - {B1234567-1234-1234-1234-123456789ABC} = {A50C70A6-2DA0-4027-B90E-B1A40755A8A5} - {212AD910-8488-4036-BE20-326931B75FB2} = {4AFC9975-2456-4C70-94A4-84073C1CED93} - {7AC943C9-52E8-44CF-9083-744D8049667B} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {54A93AF7-60C7-4F6C-99D2-FBB1F75F853A} = {7AC943C9-52E8-44CF-9083-744D8049667B} - {92C39820-9F84-4529-BC7D-22AAE514D63B} = {7AC943C9-52E8-44CF-9083-744D8049667B} - {515554D1-D004-4F7F-A107-2211FC0F6B2C} = {7AC943C9-52E8-44CF-9083-744D8049667B} - {C97D9A5D-206C-454E-997E-009E227D7F02} = {0F14491C-6369-4C45-AAA8-135814E66E6B} - {31D1C81D-765F-4446-AA62-E743F6325049} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA} - {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {E2D03E0F-7A75-4813-9F4B-D8763D43FD3A} = {1C48CD47-D610-463A-A53C-AF82DD6C47E7} - {B41B888C-7DB8-4747-B262-4062E05A230D} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA} - {AB82E5DD-C32D-4F28-9746-2C780846188E} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {57175EC7-92A5-4C1E-8244-E3FBCA2A81DE} = {AB82E5DD-C32D-4F28-9746-2C780846188E} - {E69B044A-2F8A-45AA-AD0B-256C59421807} = {AB82E5DD-C32D-4F28-9746-2C780846188E} - {C604B37E-9D0E-4484-8778-E8B31B0E1B3A} = {AB82E5DD-C32D-4F28-9746-2C780846188E} - {E599C30B-9DC8-4E5A-BF27-93D4CCEDE788} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {00EE9BA6-4E8F-43CA-960D-D4882F0FBB97} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {17B4FA70-001E-4D33-BBBB-0D142DBC2E20} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {A1425B53-3D61-4679-8623-E64A0D3D0A48} = {17B4FA70-001E-4D33-BBBB-0D142DBC2E20} - {9D7A6DE0-7D27-424D-ABAE-41B2161F9A03} = {17B4FA70-001E-4D33-BBBB-0D142DBC2E20} - {17A99C7C-0BFF-45BB-A9FD-63A0DDC105BB} = {17B4FA70-001E-4D33-BBBB-0D142DBC2E20} - {AA9F0AF8-7924-4D59-BAA1-E36F1304E0DC} = {17B4FA70-001E-4D33-BBBB-0D142DBC2E20} - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A5} = {17B4FA70-001E-4D33-BBBB-0D142DBC2E20} - {ED9A1AC6-AEB0-4569-A6E9-E1696182B545} = {2F305555-C296-497E-AC20-5FA1B237996A} - {5A5DD09D-723A-44D3-8F2B-293584C3D731} = {2F305555-C296-497E-AC20-5FA1B237996A} - {B3E869C4-8210-4EBD-A621-FF4C4AFCBFA9} = {2F305555-C296-497E-AC20-5FA1B237996A} - {54F7C616-FD41-4E62-BFF9-015686914F4D} = {2F305555-C296-497E-AC20-5FA1B237996A} - {143F13E3-D2E3-4D83-B035-356612D99956} = {2F305555-C296-497E-AC20-5FA1B237996A} - {56CC2F10-6E41-453D-BE16-C593A5E58482} = {2F305555-C296-497E-AC20-5FA1B237996A} - {CA5518ED-0458-4B09-8F53-4122B9888655} = {2F305555-C296-497E-AC20-5FA1B237996A} - {D6DCC3AE-18C0-488A-B978-BAA9E3CFF09D} = {2F305555-C296-497E-AC20-5FA1B237996A} - {2BBC9E33-21EC-401C-84DA-BB6590A9B2AA} = {2F305555-C296-497E-AC20-5FA1B237996A} - {B6C42F16-73EB-477E-8B0D-4E6CF6C20AAC} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {2833C9C6-AB32-4048-A5C7-A70898337B57} = {B6C42F16-73EB-477E-8B0D-4E6CF6C20AAC} - {50B82783-242F-42D2-BC03-B3430BF01354} = {B6C42F16-73EB-477E-8B0D-4E6CF6C20AAC} - {B5EB9FE9-37EF-47C3-B8B8-81AD3C2972C2} = {B6C42F16-73EB-477E-8B0D-4E6CF6C20AAC} - {A663E672-B26D-4EC0-BEAB-FE2E424AC46F} = {B6C42F16-73EB-477E-8B0D-4E6CF6C20AAC} - {8A08D663-4995-40E3-B42C-3F910625F284} = {322566EF-20DC-43A6-B9F8-616AF942579A} - {923DF87C-CA99-4D1C-B1D2-959174E95BFA} = {322566EF-20DC-43A6-B9F8-616AF942579A} - {D5E42C63-57C5-4EF6-AECE-1E2FCA725B77} = {2C318EC3-BA86-4372-B1BC-DB0F33C208B2} - {D962A009-834F-4EEC-AABB-430DF8F98E39} = {322566EF-20DC-43A6-B9F8-616AF942579A} - {9873BA05-4C41-4819-9283-CF45D795431B} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {FC373B24-3293-453C-AAF5-CF2909DCEE6A} = {9873BA05-4C41-4819-9283-CF45D795431B} - {9CE59ED5-7087-4353-88EB-788038A73CEC} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {FD86C06A-FB54-4D5E-9831-1CDADF60D45F} = {929C1324-22E8-4412-A9A8-80E85F3985A5} - {697C6AF9-0A48-49A9-866C-67DA12384015} = {929C1324-22E8-4412-A9A8-80E85F3985A5} - {929C1324-22E8-4412-A9A8-80E85F3985A5} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {9EBAA524-0EDA-470B-95D4-39383285CBB2} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {500DED3E-CFB5-4ED5-ACC6-02B3D6DC336D} = {4AFC9975-2456-4C70-94A4-84073C1CED93} - {D095BE44-1F2E-463E-A494-121892A75EA2} = {4AFC9975-2456-4C70-94A4-84073C1CED93} - {90F9FA90-2C20-4004-96E6-F3B78151F5A5} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F} - {3B227528-4BA6-4CAF-B44A-A10C78A64849} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {F5E1146E-B7B3-4E11-85FD-270A500BD78C} = {3B227528-4BA6-4CAF-B44A-A10C78A64849} - {3157FA75-86CF-4EE2-8F62-C43F776493C6} = {3B227528-4BA6-4CAF-B44A-A10C78A64849} - {4C0D0746-BE5B-49EE-BD5D-A7811628AE8B} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {538ED0BB-B863-4B20-98CC-BCDF7FA0B68A} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {51465DA1-C18B-4B99-93E1-ECF8E0FA0CBA} = {538ED0BB-B863-4B20-98CC-BCDF7FA0B68A} - {B9420661-B0E4-4241-ABD4-4A27A1F64250} = {538ED0BB-B863-4B20-98CC-BCDF7FA0B68A} - {CCB5E44F-84D9-4203-83C6-1C9EC9302BC7} = {2F305555-C296-497E-AC20-5FA1B237996A} - {D949EC7D-48A9-4279-95D5-078E7FD1F048} = {2F305555-C296-497E-AC20-5FA1B237996A} - {3BAF9C81-A194-4925-A035-5E24A5D1E542} = {2F305555-C296-497E-AC20-5FA1B237996A} - {6B04803D-B418-4833-A67E-B0FC966636A5} = {2F305555-C296-497E-AC20-5FA1B237996A} - {3940AD4D-F748-4BE4-9083-85769CD553EF} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704} - {F8FFFC12-A31A-4AFA-B3DF-14DCF42B5E38} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704} - {0014D652-901F-4456-8D65-06FC5F997FB0} = {4C0D0746-BE5B-49EE-BD5D-A7811628AE8B} - {799A50D8-DE89-4ED1-8FF8-AD5A9ED8C0CA} = {AB82E5DD-C32D-4F28-9746-2C780846188E} - {9D52FD25-EF90-4F9A-A015-91EFC5DAF54F} = {AB82E5DD-C32D-4F28-9746-2C780846188E} - {C32D254F-7597-4CBE-BF74-D922D81CDF29} = {9873BA05-4C41-4819-9283-CF45D795431B} - {02DD46D3-F761-47D9-8894-2D6DA0124650} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA} - {8E23E173-7127-4A5F-9F93-3049F2B68047} = {929C1324-22E8-4412-A9A8-80E85F3985A5} - {DFF88D16-D36F-40A4-A955-CDCAA76EF7B8} = {538ED0BB-B863-4B20-98CC-BCDF7FA0B68A} - {C0974915-8A1D-4BF0-977B-9587D3807AB7} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD} - {1D6893CB-BC0C-46A8-A76C-9728706CA51A} = {557C4636-D7E1-4838-A504-7D19B725EE95} - {8ACB33D9-C95B-47D4-8363-9731EE0930A0} = {CA716AE6-FE5C-40AC-BB8F-2C87912687AC} - {CA716AE6-FE5C-40AC-BB8F-2C87912687AC} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {F055103B-F80B-4D0C-BF48-057C55620033} = {5A7818A8-109C-4E1C-850D-1A654E234B0E} - {A2221D7E-55E7-4BEA-90D1-4F162D670BBF} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {BE126CBB-AE12-406A-9837-A05ACFCA57A7} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF} - {14CB58B7-D280-4A7A-95DE-4B2DF14EA000} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF} - {B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF} - {A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C} = {68328142-5B31-4715-BCBB-7B6345EE0971} - {9C53CC25-0623-4569-95BC-B05410675EE3} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF} - {45285DF2-9742-4ECA-9AC9-58951FC26489} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF} - {3D63307B-9D27-44FD-B033-B26F39245B85} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF} - {367D7543-7DBA-4381-99F1-BF6142A996C4} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF} - {2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF} - {37D07516-4185-43A4-924F-3C7A5D95ECF6} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF} - {8F021B46-362B-485C-BFBA-CCF83E820CBD} = {8F62026A-294B-41C6-8839-87463613F216} - {66614C26-314C-4B91-9071-76133422CFEF} = {BFFB607F-7C78-434B-86B9-DA4C8196A1B5} - {3846508C-77EB-4034-A702-F8BB263C4F79} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2} = {3846508C-77EB-4034-A702-F8BB263C4F79} - {6CE438DF-C245-4997-A360-0A0939E4BA34} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2} - {E09AA983-C755-474F-83D6-A5CDF528C070} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2} - {6D56B64D-FF1F-488F-AFED-9B9854A5D399} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2} - {92EC89E4-9972-453A-8A1A-3A9E230C146A} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2} - {51939B4F-1F62-4BFF-A6A2-C08646E5BE95} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2} - {D1160404-D3D1-497A-883A-4059C07C2273} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2} - {40F6D69D-E321-400F-A767-5628C7AE453D} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2} - {F3D09629-59A2-4924-A4B9-D6BFAA2C1B49} = {3846508C-77EB-4034-A702-F8BB263C4F79} - {305DD37E-C85D-4B08-AAFE-7381FA890463} = {F3D09629-59A2-4924-A4B9-D6BFAA2C1B49} - {CA4D810F-C8F4-4B61-9DA9-71807E0B9F24} = {F3D09629-59A2-4924-A4B9-D6BFAA2C1B49} - {14E62033-58D0-4A7D-8990-52F50A08BBBD} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} - {6515F03F-E56D-4DB4-B23D-AC4FB80DB36F} = {7520A2FE-00A2-49B8-83ED-DB216E874C04} - {071E18A4-A530-46B8-AB7D-B862EE55E24E} = {3846508C-77EB-4034-A702-F8BB263C4F79} - {C846F7A7-792A-47D9-B0CB-417C900EE03D} = {071E18A4-A530-46B8-AB7D-B862EE55E24E} - {C831231F-891C-4572-9694-45062534B42A} = {071E18A4-A530-46B8-AB7D-B862EE55E24E} - {7520A2FE-00A2-49B8-83ED-DB216E874C04} = {3846508C-77EB-4034-A702-F8BB263C4F79} - {8FBDABA4-40EE-4C0E-9BC8-2F6444A6EF90} = {7520A2FE-00A2-49B8-83ED-DB216E874C04} - {C66020D1-CB10-4CF7-8715-84C97FD5E5E2} = {7520A2FE-00A2-49B8-83ED-DB216E874C04} - {79775343-7A3D-445D-9104-3DD5B2893DF9} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2} - {0ADEB797-C8C7-4FFA-ACD5-2AF6CAD7ECD8} = {3846508C-77EB-4034-A702-F8BB263C4F79} - {89D0E199-B17A-418C-B2F8-7375B6708357} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF} - {0DB0F63A-D2F8-4DA3-A650-2D0B8724218E} = {CA716AE6-FE5C-40AC-BB8F-2C87912687AC} - {453CBB73-A3CB-4D0B-8D24-6940B86FE21D} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2} - {C0CE3B5E-16D3-495D-B335-CA791B660162} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2} - {3A9A7297-92C4-4F16-B6F9-8D4AB652C86C} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2} - {605E914B-7232-4789-AF46-BF5D3DDFC14E} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2} - {E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2} - {DD6E12FE-5509-4ABC-ACC2-3D6DC98A238C} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {0A84F764-3A88-44CD-AA96-41BDBD48627B} = {DD6E12FE-5509-4ABC-ACC2-3D6DC98A238C} - {E4585179-2AC1-4D5F-A3FF-CFC5392F694C} = {DD6E12FE-5509-4ABC-ACC2-3D6DC98A238C} - {CA7D8106-30B9-4AEC-9D05-B69B31B8C461} = {DD6E12FE-5509-4ABC-ACC2-3D6DC98A238C} - {DCC6BD67-17BB-47AA-B507-FB0FE43A7449} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2} - {A558C25D-2007-498E-8B6F-43405AFAE9E2} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {08F9155D-B6DC-46E5-9C83-AF60B655898B} = {38BDB927-829B-4C65-9CD9-93FB05D66D65} - {4382A954-179A-4078-92AF-715187DFFF50} = {38BDB927-829B-4C65-9CD9-93FB05D66D65} - {EBED240C-8702-452D-B764-6DB9DA9179AF} = {1C48CD47-D610-463A-A53C-AF82DD6C47E7} - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A0} = {1C48CD47-D610-463A-A53C-AF82DD6C47E7} - {5702B3CC-8575-48D5-83D8-15BB42269CD3} = {8131151D-B0E9-4E18-84A5-E5F946C4480A} - {64B88F02-CD88-4ED8-9624-989A800230F9} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2} - {5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2} = {3846508C-77EB-4034-A702-F8BB263C4F79} - {2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E} = {66E1534A-1587-42B2-912F-45C994D32904} - {9E0CBC06-F29A-4810-B93C-97D53863B95E} = {2F305555-C296-497E-AC20-5FA1B237996A} - {F6088A11-1C9E-4420-AA90-CF7E78DD7F1C} = {2F305555-C296-497E-AC20-5FA1B237996A} - {47B0678C-806B-4FE1-9F50-46BA88989532} = {2F305555-C296-497E-AC20-5FA1B237996A} - {9BC1C986-1E97-4D07-A7B1-CE226C239EFA} = {2F305555-C296-497E-AC20-5FA1B237996A} - {99CA1509-FB73-456E-AFAF-AB89C017BD72} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704} - {61CBF221-9452-4934-B685-146285E080D7} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704} - {38F187B2-6638-5A40-072F-DBE5E54070A0} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {DA0744BC-E822-680E-9CEB-D0FBA903A8EE} = {C3081D9A-1586-441A-B5F4-ED815B3719C1} - {4E0AE3A4-2EE0-44D7-A2D0-8769977254A1} = {2C318EC3-BA86-4372-B1BC-DB0F33C208B2} - {43E779F3-D83C-48B1-BA8D-1912DBD76FC9} = {68328142-5B31-4715-BCBB-7B6345EE0971} - {2CF78CF7-8FEB-4BE1-9591-55FA25B48FC6} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {14AFD976-B4D2-49D0-9E6C-AA93CC061B8A} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {9D3F3793-EFE3-4525-8782-238015DABA62} = {66E1534A-1587-42B2-912F-45C994D32904} - {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {3846508C-77EB-4034-A702-F8BB263C4F79} - {24133F7F-C1D1-DE04-EFA8-F5D5467FE027} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} - {0E556541-6A45-42CB-AE49-EE5A9BE05E7C} = {6C7F47CC-2151-44A3-A546-41C70025132C} - {27D9CB3A-46D1-402C-9273-F88CB8AC42F7} = {9873BA05-4C41-4819-9283-CF45D795431B} - {B9617A31-0F0A-4397-851D-BF2FBEE32D7F} = {C140A3EF-6DBF-4084-9D4C-4EB5A99FEE68} - {1C48CD47-D610-463A-A53C-AF82DD6C47E7} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA} - {D9BD324E-1D80-44AA-8E7B-73EB00944434} = {38BDB927-829B-4C65-9CD9-93FB05D66D65} - {8EF25507-2575-4ADE-BF7E-D23376903AB8} = {3846508C-77EB-4034-A702-F8BB263C4F79} - {070AC093-C9F2-20AD-0BCD-F318FC2761EA} = {B1234567-1234-1234-1234-123456789ABC} - {2C318EC3-BA86-4372-B1BC-DB0F33C208B2} = {322566EF-20DC-43A6-B9F8-616AF942579A} - {BFFB607F-7C78-434B-86B9-DA4C8196A1B5} = {B6C42F16-73EB-477E-8B0D-4E6CF6C20AAC} - {66E1534A-1587-42B2-912F-45C994D32904} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3} - {E885E71F-0B34-4A03-B13B-20F4E05E90BB} = {C3081D9A-1586-441A-B5F4-ED815B3719C1} - {264B412F-DB8B-4CF8-A74B-96998B183045} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD} - {3527BF37-DFC5-4309-A032-29278CA21328} = {1D78B84B-CA39-406C-98F4-71F7EC266CC0} - {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704} = {2F305555-C296-497E-AC20-5FA1B237996A} - {68328142-5B31-4715-BCBB-7B6345EE0971} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF} - {4122388B-59E4-CDB0-0338-EA6881DF86F0} = {27D9CB3A-46D1-402C-9273-F88CB8AC42F7} - {988C9FAF-5AEC-EB15-578D-FED0DF52BF55} = {27D9CB3A-46D1-402C-9273-F88CB8AC42F7} - {6748A29D-DA6A-033A-825B-752295FF6AA0} = {8EF25507-2575-4ADE-BF7E-D23376903AB8} - {6EABCF9A-6526-441F-932F-658B1DC3E403} = {264B412F-DB8B-4CF8-A74B-96998B183045} - {69D76A76-6EF6-4846-94CD-EAAF0CAC9F15} = {264B412F-DB8B-4CF8-A74B-96998B183045} - {9BAFFC28-E1EF-4C14-A101-EEBFC0A50D83} = {264B412F-DB8B-4CF8-A74B-96998B183045} - {806BF185-8B89-5BE1-9AA1-DA5BC9487DB9} = {264B412F-DB8B-4CF8-A74B-96998B183045} - {F93C2817-C846-4259-84D8-B39A6B57C8DE} = {3527BF37-DFC5-4309-A032-29278CA21328} - {8131151D-B0E9-4E18-84A5-E5F946C4480A} = {929C1324-22E8-4412-A9A8-80E85F3985A5} - {E816D7AC-4688-4ECB-97CC-3D8E798F3825} = {8EF25507-2575-4ADE-BF7E-D23376903AB8} - {E816D7AD-4688-4ECB-97CC-3D8E798F3826} = {8EF25507-2575-4ADE-BF7E-D23376903AB8} - {E816D7AE-4688-4ECB-97CC-3D8E798F3827} = {8EF25507-2575-4ADE-BF7E-D23376903AB8} - {E816D7AF-4688-4ECB-97CC-3D8E798F3828} = {8EF25507-2575-4ADE-BF7E-D23376903AB8} - {E816D7B0-4688-4ECB-97CC-3D8E798F3829} = {8EF25507-2575-4ADE-BF7E-D23376903AB8} - {00D8659C-2068-40B6-8B86-759CD6284BBB} = {8EF25507-2575-4ADE-BF7E-D23376903AB8} - {5B201255-53C8-490B-A34F-01F05D48A477} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {38177D56-6AD1-4ADF-88C9-2843A7932166} = {5B201255-53C8-490B-A34F-01F05D48A477} - {08E71C67-6A7E-4CA1-B04E-2FB336410BAC} = {5B201255-53C8-490B-A34F-01F05D48A477} - {E11826E1-76DF-42AC-985C-164CC2EE57A1} = {7AC943C9-52E8-44CF-9083-744D8049667B} - {66C069F8-C548-4CA6-8CDE-239104D68E88} = {E11826E1-76DF-42AC-985C-164CC2EE57A1} - {9605B84E-FAC4-477B-B9EC-0753177EE6A8} = {557C4636-D7E1-4838-A504-7D19B725EE95} - {94CDC147-6137-45E9-AEDE-17FF809607C0} = {9605B84E-FAC4-477B-B9EC-0753177EE6A8} - {A24BF1AF-79AA-4896-BAE3-CCBBE0380A78} = {9605B84E-FAC4-477B-B9EC-0753177EE6A8} - {E816D7B1-4688-4ECB-97CC-3D8E798F3830} = {8EF25507-2575-4ADE-BF7E-D23376903AB8} - {E816D7B3-4688-4ECB-97CC-3D8E798F3832} = {8EF25507-2575-4ADE-BF7E-D23376903AB8} - {E816D7B2-4688-4ECB-97CC-3D8E798F3831} = {8EF25507-2575-4ADE-BF7E-D23376903AB8} - {E816D7B4-4688-4ECB-97CC-3D8E798F3833} = {8EF25507-2575-4ADE-BF7E-D23376903AB8} - {48A1DB8C-5DF8-4FB3-9E14-2B67F3F2D8B5} = {322566EF-20DC-43A6-B9F8-616AF942579A} - {3DCCD936-D085-4869-A1DE-CA6A64152C94} = {5B201255-53C8-490B-A34F-01F05D48A477} - {F5333ED7-06D8-4AB3-953A-36D63F08CB6F} = {3DCCD936-D085-4869-A1DE-CA6A64152C94} - {4E0FCF69-B06B-D272-76BF-ED3A559B4EDA} = {8EF25507-2575-4ADE-BF7E-D23376903AB8} - {45354F4F-1414-45CE-B600-51CD1209FD19} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {A66E9270-5D93-EC9C-F06E-CE7295BB9A6C} = {8EF25507-2575-4ADE-BF7E-D23376903AB8} - {2B3FB837-23DE-629F-82C6-42304E7083C9} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2} - {DB34808A-FF91-D06E-A426-AFB5A8BD583B} = {8EF25507-2575-4ADE-BF7E-D23376903AB8} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0} - EndGlobalSection -EndGlobal diff --git a/PowerToys.slnx b/PowerToys.slnx new file mode 100644 index 0000000000..1884b2d58b --- /dev/null +++ b/PowerToys.slnx @@ -0,0 +1,1045 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/devdocs/commands.md b/doc/devdocs/commands.md new file mode 100644 index 0000000000..811625284e --- /dev/null +++ b/doc/devdocs/commands.md @@ -0,0 +1,34 @@ +# Issue/PR commands + +The PowerToys repository uses some special keywords to help manage issues and pull requests. Here is a list of the most important commands you can use in issue and PR descriptions or comments. + +| Command | Description | +|---------|-------------| +| `/azp run` | Triggers the Azure Pipelines CI build for the current PR. Useful if you want to re-run the build without creating a new commit. | +| `/bugreport` / `/reportbug` | Adds a comment with a manual for the Bug Report Tool, which helps users collect logs and system information for debugging purposes. It requests to upload this file and adds the `Needs-Author-Feedback` label. | +| `/feedbackhub` | Adds a comment with a link to the Feedback Hub app on Windows, where users can submit feedback about PowerToys. Closes the issue and adds the `Resolution-Please File on Feedback Hub` label. | +| `/dup #...` / `/duplicate #...` / `/dup https://...` / `/duplicate https://...` | Marks the current issue as a duplicate of another issue. It closes the current issue and applies the `Resolution-Duplicate` label. Replace `#...` with the issue number or a link to the issue. | +| `/needinfo` | Adds the `Needs-Author-Feedback` label to the issue or PR, indicating that more information is needed from the author. | +| `/helped` | Closes the issue and adds the `Resolution-Helped User` label. Furthermore a comment is added with a link to the PowerToys user documentation. | +| `/loc` | Adds a comment informing the user that the issue was forwarded to the localization team and will soon be fixed. It adds the `Loc-Sent To Team` label. | + +## Defining new commands + +Most of these commands are using the [Microsoft GitHub Policy Service](https://github.com/apps/microsoft-github-policy-service) bot. Its commands are defined in the [PowerToys policy configuration file](/.github/policies/resourceManagement.yml). + +## Other automated tasks + +### Automatic labeling + +The bot can automatically apply the correct `product-...` label for any opened issue. + +> [!NOTE] +> This feature is currently only available for the Workspaces module as a test. + +### The `Needs-Author-Feedback` label + +If an issue has this label and had no activity for 5 days, the bot will post a comment reminding the author to provide the needed information. It also adds the `Status-No recent activity` label. If no further activity occurs for another 5 days, the bot will close the issue. + +### Filtering users that want to contribute + +If a user utters their intention to contribute (e.g., by using the phrase "I want to contribute" in an issue or PR), the bot will add a comment with a link to the ["Would you like to contribute to PowerToys?" thread](https://github.com/microsoft/PowerToys/issues/28769). diff --git a/doc/devdocs/core/installer.md b/doc/devdocs/core/installer.md index 5bcbb0f87c..90af7668c2 100644 --- a/doc/devdocs/core/installer.md +++ b/doc/devdocs/core/installer.md @@ -134,7 +134,7 @@ If you prefer, you can alternatively build prerequisite projects for the install #### Locally compiling the installer -1. Open `installer\PowerToysSetup.sln` +1. Open `installer\PowerToysSetup.slnx` 1. In Visual Studio, in the `Solutions Configuration` drop-down menu select `Release` 1. From the `Build` menu choose `Build Solution`. @@ -144,9 +144,9 @@ To build the installer from the command line, run `Developer Command Prompt for ``` git clean -xfd -e *exe -- .\installer\ -MSBuild -t:restore .\installer\PowerToysSetup.sln -p:RestorePackagesConfig=true /p:Platform="x64" /p:Configuration=Release -MSBuild -t:Restore -m .\installer\PowerToysSetup.sln /t:PowerToysInstallerVNext /p:Configuration=Release /p:Platform="x64" -MSBuild -t:Restore -m .\installer\PowerToysSetup.sln /t:PowerToysBootstrapperVNext /p:Configuration=Release /p:Platform="x64" +MSBuild -t:restore .\installer\PowerToysSetup.slnx -p:RestorePackagesConfig=true /p:Platform="x64" /p:Configuration=Release +MSBuild -t:Restore -m .\installer\PowerToysSetup.slnx /t:PowerToysInstallerVNext /p:Configuration=Release /p:Platform="x64" +MSBuild -t:Restore -m .\installer\PowerToysSetup.slnx /t:PowerToysBootstrapperVNext /p:Configuration=Release /p:Platform="x64" ``` ### Supported arguments for the .EXE Bootstrapper installer diff --git a/doc/devdocs/core/settings/settings-implementation.md b/doc/devdocs/core/settings/settings-implementation.md index defe59a3fa..65d0d27c73 100644 --- a/doc/devdocs/core/settings/settings-implementation.md +++ b/doc/devdocs/core/settings/settings-implementation.md @@ -38,7 +38,7 @@ For C# modules, the settings are accessed through the `SettingsUtils` class in t using Microsoft.PowerToys.Settings.UI.Library; // Read settings -var settings = SettingsUtils.GetSettings("ModuleName"); +var settings = SettingsUtils.Default.GetSettings("ModuleName"); bool enabled = settings.Enabled; ``` @@ -49,7 +49,7 @@ using Microsoft.PowerToys.Settings.UI.Library; // Write settings settings.Enabled = true; -SettingsUtils.SaveSettings(settings.ToJsonString(), "ModuleName"); +SettingsUtils.Default.SaveSettings(settings.ToJsonString(), "ModuleName"); ``` ## Settings Handling in Modules diff --git a/doc/devdocs/development/debugging.md b/doc/devdocs/development/debugging.md index c3e0fdac89..3756dd9396 100644 --- a/doc/devdocs/development/debugging.md +++ b/doc/devdocs/development/debugging.md @@ -19,7 +19,7 @@ You can build the entire solution from the command line, which is sometimes fast 2. Navigate to the repository root directory 3. Run the following command(don't forget to set the correct platform): ```pwsh - msbuild -restore -p:RestorePackagesConfig=true -p:Platform=ARM64 -m PowerToys.sln /tl /p:NuGetInteractive="true" + msbuild -restore -p:RestorePackagesConfig=true -p:Platform=ARM64 -m PowerToys.slnx /tl /p:NuGetInteractive="true" ``` 4. This process should complete in approximately 13-14 minutes for a full build diff --git a/doc/devdocs/development/dev-with-vscode.md b/doc/devdocs/development/dev-with-vscode.md index 4b1b7def24..bd2f894f79 100644 --- a/doc/devdocs/development/dev-with-vscode.md +++ b/doc/devdocs/development/dev-with-vscode.md @@ -42,10 +42,10 @@ Or reach out to "tools\build\BUILD-GUIDELINES.md" ### Sample plain msbuild command ```powershell # Restore: -msbuild powertoys.sln -t:restore -p:configuration=debug -p:platform=x64 -m +msbuild powertoys.slnx -t:restore -p:configuration=debug -p:platform=x64 -m -# Build powertoys sln -msbuild powertoys.sln -p:configuration=debug -p:platform=x64 -m +# Build powertoys slnx +msbuild powertoys.slnx -p:configuration=debug -p:platform=x64 -m # dotnet project msbuild src\settings-ui\Settings.UI\PowerToys.Settings.csproj -p:Platform=x64 -p:Configuration=Debug -m @@ -122,7 +122,7 @@ Similar for attach to managed code. | Task | Command / Action | Notes | |------|------------------|-------| -| Clean | `git clean -xdf` (careful) or `msbuild /t:Clean PowerToys.sln` | Deep clean removes packages & build outputs | +| Clean | `git clean -xdf` (careful) or `msbuild /t:Clean PowerToys.slnx` | Deep clean removes packages & build outputs | | Rebuild single project | `msbuild path\to\proj.vcxproj /t:Rebuild -p:Platform=x64 -p:Configuration=Debug` | Faster than whole solution | | Generate installer (rare in inner loop) | See `tools\build\build-installer.ps1` | Usually not needed for local debug | -| Resource conversion errors | Re-run restore + build | Triggers custom PowerShell targets | \ No newline at end of file +| Resource conversion errors | Re-run restore + build | Triggers custom PowerShell targets | diff --git a/doc/devdocs/style.md b/doc/devdocs/development/style.md similarity index 100% rename from doc/devdocs/style.md rename to doc/devdocs/development/style.md diff --git a/doc/devdocs/development/ui-tests.md b/doc/devdocs/development/ui-tests.md index 63bddb0591..941f9dacd4 100644 --- a/doc/devdocs/development/ui-tests.md +++ b/doc/devdocs/development/ui-tests.md @@ -12,7 +12,7 @@ - Exit PowerToys if it's running. -- Open `PowerToys.sln` in Visual Studio and build the solution. +- Open `PowerToys.slnx` in Visual Studio and build the solution. - Run tests in the Test Explorer (`Test > Test Explorer` or `Ctrl+E, T`). diff --git a/doc/devdocs/localization.md b/doc/devdocs/localization.md deleted file mode 100644 index f9e7e50a67..0000000000 --- a/doc/devdocs/localization.md +++ /dev/null @@ -1,165 +0,0 @@ -# Localization - -> **NOTE**: THIS DOCUMENT IS OUTDATED. -> Follow [issue 15243](https://github.com/microsoft/PowerToys/issues/15243) for updates. - -## Table of Contents -1. [Localization on the pipeline (CDPX)](#localization-on-the-pipeline-cdpx) - 1. [UWP Special case](#uwp-special-case) -2. [Enabling localization on a new project](#enabling-localization-on-a-new-project) - 1. [C++](#c) - 2. [C#](#c-1) - 3. [UWP](#uwp) -3. [Lcl Files](#lcl-files) -4. [Possible Issues in localization PRs (LEGO)](#possible-issues-in-localization-prs-lego) -5. [Enabling localized MSI for a new project](#enabling-localized-msi-for-a-new-project) - -## Localization on the pipeline (CDPX) -[The localization step](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/pipeline.user.windows.yml#L45-L52) is run on the pipeline before the solution is built. This step runs the [build-localization](https://github.com/microsoft/PowerToys/blob/main/.pipelines/build-localization.cmd) script, which generates resx files for all the projects with localization enabled using the `Localization.XLoc` package. - -The [`Localization.XLoc`](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/build-localization.cmd#L24-L25) tool is run on the repo root, and it checks for all occurrences of `LocProject.json`. Each localized project has a `LocProject.json` file in the project root, which contains the location of the English resx file, list of languages for localization, and the output path where the localized resx files are to be copied to. In addition to this, some other parameters can be set, such as whether the language ID should be added as a folder in the file path or in the file name. When the CDPX pipeline is run, the localization team is notified of changes in the English resx files. For each project with localization enabled, a `loc` folder (see [this](https://github.com/microsoft/PowerToys/tree/main/src/modules/launcher/Microsoft.Launcher/loc) for example) is created in the same directory as the `LocProject.json` file. The folder contains language specific folders which in turn have a nested folder path equivalent to `OutputPath` in the `LocProject.json`. Each of these folders contain one `lcl` file. The `lcl` files contain the English resources along with their translation for that language. These are described in more detail in the [Lcl files section](#lcl-files). Once the `.resx` files are generated, they will be used during the `Build PowerToys` step for localized versions of the modules. - -Since the localization script requires certain nuget packages, the [`restore-localization`](https://github.com/microsoft/PowerToys/blob/main/.pipelines/restore-localization.cmd) script is run before running `build-localization` to install all the required packages. This script must [run in the `restore` step](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/pipeline.user.windows.yml#L37-L39) of pipeline because [the host is network isolated](https://onebranch.visualstudio.com/Pipeline/_wiki/wikis/Pipeline.wiki/2066/Consuming-Packages-in-a-CDPx-Pipeline?anchor=overview) at the `build` step. The [Toolset package source](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/pipeline.user.windows.yml#L23) is used for this. - -The process and variables that can be tweaked on the pipeline are described in more detail on [onebranch (account required) under Localization](https://onebranch.visualstudio.com/Pipeline/_wiki/wikis/Pipeline.wiki/290/Localization). - -The localized resource dlls for C# projects are added to the MSI only for build on the pipeline. This is done by checking if the [`IsPipeline` variable is defined](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/installer/PowerToysSetup/Product.wxs#L804-L805), which gets defined before [building the installer on the pipeline](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/.pipelines/build-installer.cmd#L4). This is done because the localized resx files are only present on the pipeline, and not having this check would result in the installer project failing to build locally. - -## Enabling localization on a new project -To enable localization on a new project, the first step is to create a file `LocProject.json` in the project root. - -For example, for a project in the folder `src\path` where the resx file is present in `resources\Resources.resx`, the LocProject.json file will contain the following: -``` -{ - "Projects": [ - { - "LanguageSet": "Azure_Languages", - "LocItems": [ - { - "SourceFile": "src\\path\\resources\\Resources.resx", - "CopyOption": "LangIDOnName", - "OutputPath": "src\\path\\resources" - } - ] - } - ] -} -``` -The rest of the steps depend on the project type and are covered in the sections below. The steps to add the localized files to the MSI can be found in [Enabling localized MSI for a new project](#Enabling-localized-MSI-for-a-new-project). - -### C++ -C++ projects do not support `resx` files, and instead use `rc` files along with `resource.h` files. The CDPX pipeline however doesn't support localizing `rc` files and the other alternative they support is directly translating the resources from the binary which makes it harder to maintain resources. To avoid this, a custom script has been added which expects a resx file and converts the entries to an rc file with a string table and adds resource declarations to a resource.h file so that the resources can be compiled with the C++ project. - -If you already have a .rc file, copy the string table to a separate txt file and run the [convert-stringtable-to-resx.ps1](https://github.com/microsoft/PowerToys/blob/main/tools/build/convert-stringtable-to-resx.ps1) script on it. This script is not very robust to input, and requires the data in a specific format, where `IDS_ResName L"ResourceValue"` and any number of spaces can be present in between. The script converts this file to the format expected by [`resgen`](https://learn.microsoft.com/dotnet/framework/tools/resgen-exe-resource-file-generator#Convert), which will convert it to resx. The resource names are changed from all uppercase to title case, and the `IDS_` prefix is removed. Escape characters might have to be manually replaced, for example .rc files would have escaped double quotes as `""`, so this should be replaced with just `"` before converting to the resx files. - -After generating the resx file, rename the existing rc and h files to ProjName.base.rc and resource.base.h. In the rc file remove the string table which is to be localized and in the .h file remove all `#define`s corresponding to localized resources. In the vcxproj of the C++ project, add the following build event: -``` - - - -``` - -This event runs a script which generates a resource.h and ProjName.rc in the `Generated Files` folder using the strings in all the resx files along with the existing information in resource.base.h and ProjName.base.rc. The script is [convert-resx-to-rc.ps1](https://github.com/microsoft/PowerToys/blob/main/tools/build/convert-resx-to-rc.ps1). The script uses [`resgen`](https://learn.microsoft.com/dotnet/framework/tools/resgen-exe-resource-file-generator#Convert) to convert the resx file to a string table expected in the .rc file format. When the resources are added to the rc file the `IDS_` prefix is added and resource names are in upper case (as it was originally). Any occurrences of `"` in the string resource is escaped as `""` to prevent build errors. The string tables are added to the rc file in the following format: -``` -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US - -STRINGTABLE -BEGIN - strings -END - -#endif -``` -Since there is no API to identify the `AFX_TARG_*`, `LANG_*` or `SUBLANG_*` values from each langId from the pipeline, these are hardcoded in the script (for each language) as done in [lines 50-77 of `convert-resx-to-rc.ps1`](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/tools/build/convert-resx-to-rc.ps1#L50-L77). **If any other languages are added in the future, this script will have to be updated.** In order to determine what are the language codes, you can open the rc file in Resource View, right click the string table and press `Insert Copy` and choose the corresponding language. This autogenerates the required code and can be used to figure out the language codes. The files also add the resource declarations to a resource.h file, starting from 101 by default(this can be changed by an optional argument). Since the output files will be generated in `Generated Files`, any includes in these two files will require an additional `..\` and wherever resource.h is used, it will have to be included as `Generated Files\resource.h`. While adding `resource.base.h` and `ProjName.base.rc` to the vcxproj, these should be modified to not participate in the build to avoid build errors: -``` - -``` - -Some rc/resource.h files might be used in multiple projects (for example, KBM). To ensure the projects build for these cases, the build event can be added to the entire directory so that the rc files are generated before any project is built. See [Directory.Build.targets](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/Directory.Build.targets) for an example. - -Check [this PR](https://github.com/microsoft/PowerToys/pull/6104) for an example for making these changes for a C++ project. - -### C# -Since C# projects natively support `resx` files, the only step required here is to include all the resx files in the build. For .NET Core projects this is done automatically and the .csproj does not need to be modified. For other projects, the following line needs to be added: -``` - -``` - -**Note:** Building with localized resources may cause a build warning `Referenced assembly 'mscorlib.dll' targets a different processor` which is a VS bug. More details can be found in [PowerToys issue #7269](https://github.com/microsoft/PowerToys/issues/7269). - -**Note:** If a project needs to be migrated from XAML resources to resx, the easiest way to convert the resources would be to change to format to `=` separates resources by either manually (by Ctrl+H on a text editor), or by a script, and then running [`resgen`](https://learn.microsoft.com/dotnet/framework/tools/resgen-exe-resource-file-generator#Convert) on `Developer Command Prompt for VS` to convert it to resx format. -``` -Calculator -Allows to do mathematical calculations.(Try 5*3-2 in Wox) -Not a number (NaN) -``` -to -``` -wox_plugin_calculator_plugin_name=Calculator -wox_plugin_calculator_plugin_description=Allows to do mathematical calculations.(Try 5*3-2 in Wox) -wox_plugin_calculator_not_a_number=Not a number (NaN) -``` -After adding the resx file to the project along with the resource generator, references to the strings will have to be replaced with `Properties.Resources.resName` rather than the custom APIs. Check [this PR](https://github.com/microsoft/PowerToys/pull/6165) for an example of the changes required. - -### UWP -UWP projects expect `resw` files rather than `resx` (the format is almost the same). Unlike other C# projects, the files are expected in the format `fullLangId\Resources.resw`. To include these files in the build, replace the following line in the csproj: -``` - -``` -to -``` - -``` - -## Lcl Files -Lcl files contain all the resources that are present in the English resx file, along with a translation if it has been added. - -For example, an entry for a resource in the lcl file looks like this: -``` - - - - - - - - - -``` -The `` element would not be present in the initial commits of the lcl files, as only the English version of the string would be present. - -**Note:** The CDPX Localization system has a fail-safe check on the lcl files, where if the English string value which is present inside `` does not match the value present in the English Resources.resx file then the translated value will not be copied to the localized resx file. This is present so that obsolete translations would not be loaded when the English resource has changed, and the English string will be used rather than the obsolete translation. - -## Possible Issues in localization PRs (LEGO) -Since the LEGO PRs update some of the strings in LCL files at a time, there can be multiple PRs which modify the same files, leading to merge conflicts. In most cases this would show up on GitHub as a merge conflict, but sometimes a bad git merge may occur, and the file could end up with incorrect formatting, such as two `` elements for a single resource. These can be fixed by ensuring the elements follow the format described in [this section](#lcl-files). To catch such errors, the build farm should be run for every LEGO PR and if any error occurs in the localization step, we should check the corresponding resx/lcl files for conflicts. - -## Enabling localized MSI for a new project -For C++ and UWP projects no additional files are generated with localization that need to be added to the MSI. For C++ projects all the resources are added to the dll/exe, while for UWP projects they are added to the `resources.pri` file (which is present even for an unlocalized project). To verify if the localized resources are added to the `resources.pri` file the following steps can be done: -- Open `Developer Command Prompt for VS` -- After navigating to the folder containing the pri file, run the following command: - - makepri.exe dump /if .\resources.pri -- Check the contents of the `resources.pri.xml` file that is generated from the command. The last section of the file will contain the resources with the strings in all the languages: -``` - - - Running as administrator - - - Running as administrator - - -``` - -For C# projects, satellite dlls are generated when the project is built. For a project named `ProjName`, files are created in the format `langId\ProjName.resources.dll` where `langId` is in the same format as the lcl files. The satellite dlls need to be included with the MSI, but they must be added only if the solution is built from the build farm, as the localized resx files will not be present on local machines (and that could cause local builds of the installer to fail). -This can be done by adding the directory name of the project to [Product.wxs near line 806](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/installer/PowerToysSetup/Product.wxs#L806) and a resource component for the project can be created in [Product.wxs near lines 845-847](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/installer/PowerToysSetup/Product.wxs#L845-L847) in this format: -``` - - - -``` - -We should also ensure the new dlls are signed by the pipeline. Currently all dlls of the form [`*.resources.dll` are signed](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/.pipelines/pipeline.user.windows.yml#L68). - -**Note:** The resource dlls should be added to the MSI project only after the initial commit with the lcl files has been done by the Localization team. Otherwise, the pipeline will fail as there wouldn't be any resx files to generate the dlls. diff --git a/doc/devdocs/modules/alwaysontop.md b/doc/devdocs/modules/alwaysontop.md index 2162245d83..d8948697f1 100644 --- a/doc/devdocs/modules/alwaysontop.md +++ b/doc/devdocs/modules/alwaysontop.md @@ -86,7 +86,7 @@ The module provides a user interface for configuring settings in the PowerToys S ### Building and Testing 1. Clone the repository: `git clone https://github.com/microsoft/PowerToys.git` -2. Open PowerToys.sln in Visual Studio +2. Open PowerToys.slnx in Visual Studio 3. Select the Release configuration and build the solution 4. Run PowerToys.exe from the output directory to test the module diff --git a/doc/devdocs/modules/fancyzones.md b/doc/devdocs/modules/fancyzones.md index 07ffe491f5..a4571eacd7 100644 --- a/doc/devdocs/modules/fancyzones.md +++ b/doc/devdocs/modules/fancyzones.md @@ -161,7 +161,7 @@ FancyZones is divided into several projects: ``` git clone https://github.com/microsoft/PowerToys.git ``` -2. Open `PowerToys.sln` in Visual Studio +2. Open `PowerToys.slnx` in Visual Studio 3. Select the Release configuration and build the solution 4. If you encounter build errors, try deleting the x64 output folder and rebuild @@ -244,7 +244,7 @@ UI tests are implemented using [Windows Application Driver](https://github.com/m - Exit PowerToys if it's running - Run WinAppDriver.exe from the installation directory. Skip this step if installed in the default directory (`C:\Program Files (x86)\Windows Application Driver`); in this case, it'll be launched automatically during tests. - - Open `PowerToys.sln` in Visual Studio and build the solution. + - Open `PowerToys.slnx` in Visual Studio and build the solution. - Run tests in the Test Explorer (`Test > Test Explorer` or `Ctrl+E, T`). >Note: notifications or other application windows, that are shown above the window under test, can disrupt the testing process. diff --git a/doc/devdocs/modules/keyboardmanager/debug.md b/doc/devdocs/modules/keyboardmanager/debug.md index 0efb3b0b3a..60b975da0f 100644 --- a/doc/devdocs/modules/keyboardmanager/debug.md +++ b/doc/devdocs/modules/keyboardmanager/debug.md @@ -11,7 +11,7 @@ Keyboard Manager consists of two main components: ## Development Environment Setup 1. Clone the PowerToys repository -2. Open `PowerToys.sln` in Visual Studio +2. Open `PowerToys.slnx` in Visual Studio 3. Ensure all NuGet packages are restored 4. Build the entire solution in Debug configuration @@ -91,4 +91,4 @@ If you encounter issues with multiple instances, check the mutex logic in `Keybo To debug both the Editor and Engine: 1. Launch the Engine first in debug mode -2. Attach the debugger to the Editor process when it starts \ No newline at end of file +2. Attach the debugger to the Editor process when it starts diff --git a/doc/devdocs/modules/lightswitch.md b/doc/devdocs/modules/lightswitch.md index 18192f7f23..eb5e07aea6 100644 --- a/doc/devdocs/modules/lightswitch.md +++ b/doc/devdocs/modules/lightswitch.md @@ -92,7 +92,7 @@ The module’s settings are exposed in the PowerToys Settings UI. Options includ 3. Build the solution: ```sh - msbuild -restore -p:RestorePackagesConfig=true -p:Platform=ARM64 -m PowerToys.sln + msbuild -restore -p:RestorePackagesConfig=true -p:Platform=ARM64 -m PowerToys.slnx ``` > Note: This may take some time. diff --git a/doc/devdocs/modules/screenruler.md b/doc/devdocs/modules/screenruler.md index 08bdda764a..d43d1639ea 100644 --- a/doc/devdocs/modules/screenruler.md +++ b/doc/devdocs/modules/screenruler.md @@ -53,7 +53,7 @@ The Screen Ruler module consists of several components: ### Building -1. Open PowerToys.sln in Visual Studio +1. Open PowerToys.slnx in Visual Studio 2. In the Solutions Configuration drop-down menu, select Release or Debug 3. From the Build menu, choose Build Solution 4. The executable app for Screen Ruler is named PowerToys.MeasureToolUI.exe diff --git a/doc/devdocs/modules/shortcut_guide.md b/doc/devdocs/modules/shortcut_guide.md index c8cefbc3f3..f150a4456c 100644 --- a/doc/devdocs/modules/shortcut_guide.md +++ b/doc/devdocs/modules/shortcut_guide.md @@ -19,7 +19,7 @@ Shortcut Guide is a PowerToy that displays an overlay of available keyboard shor ## Build and Debug Instructions ### Build -1. Open PowerToys.sln in Visual Studio +1. Open PowerToys.slnx in Visual Studio 2. Select Release or Debug in the Solutions Configuration drop-down menu 3. From the Build menu, choose Build Solution 4. The executable is named PowerToys.ShortcutGuide.exe diff --git a/doc/devdocs/readme.md b/doc/devdocs/readme.md index 75e03c0629..38df894d1a 100644 --- a/doc/devdocs/readme.md +++ b/doc/devdocs/readme.md @@ -38,6 +38,11 @@ Welcome to the PowerToys developer documentation. This documentation provides in - [Update Process](processes/update-process.md) - How PowerToys updates work - [GPO Implementation](processes/gpo.md) - Group Policy Objects implementation details +## Other Resources + +- [aka.ms links](akaLinks.md) - List of short links +- [Issue/PR commands](commands.md) - Special commands for managing issues and pull requests + ## Fork, Clone, Branch and Create your PR Once you've discussed your proposed feature/fix/etc. with a team member, and an approach or a spec has been written and approved, it's time to start development: @@ -80,7 +85,7 @@ Once you've discussed your proposed feature/fix/etc. with a team member, and an ### Install Visual Studio dependencies -1. Open the `PowerToys.sln` file. +1. Open the `PowerToys.slnx` file. 1. If you see a dialog that says `install extra components` in the solution explorer pane, click `install` ### Get Submodules to compile @@ -93,7 +98,7 @@ We have submodules that need to be initialized before you can compile most parts ### Compiling Source Code -- Open `PowerToys.sln` in Visual Studio. +- Open `PowerToys.slnx` in Visual Studio. - In the `Solutions Configuration` drop-down menu select `Release` or `Debug`. - From the `Build` menu choose `Build Solution`, or press Control+Shift+b on your keyboard. - The build process may take several minutes depending on your computer's performance. Once it completes, the PowerToys binaries will be in your repo under `x64\Release\`. @@ -107,10 +112,10 @@ Our installer is two parts, an EXE and an MSI. The EXE (Bootstrapper) contains The installer can only be compiled in `Release` mode; steps 1 and 2 must be performed before the MSI can be compiled. -1. Compile `PowerToys.sln`. Instructions are listed above. +1. Compile `PowerToys.slnx`. Instructions are listed above. 1. Compile `BugReportTool.sln` tool. Path from root: `tools\BugReportTool\BugReportTool.sln` (details listed below) 1. Compile `StylesReportTool.sln` tool. Path from root: `tools\StylesReportTool\StylesReportTool.sln` (details listed below) -1. Compile `PowerToysSetup.sln` Path from root: `installer\PowerToysSetup.sln` (details listed below) +1. Compile `PowerToysSetup.slnx` Path from root: `installer\PowerToysSetup.slnx` (details listed below) See [Installer](core/installer.md) for more details on building and debugging the installer. diff --git a/doc/thirdPartyRunPlugins.md b/doc/thirdPartyRunPlugins.md index a15cb542a8..9cfdc505ff 100644 --- a/doc/thirdPartyRunPlugins.md +++ b/doc/thirdPartyRunPlugins.md @@ -51,6 +51,7 @@ Contact the developers of a plugin directly for assistance with a specific plugi | [RandomGen](https://github.com/ruslanlap/PowerToysRun-RandomGen) | [ruslanlap](https://github.com/ruslanlap) | 🎲 Generate random data instantly with a single keystroke. Perfect for developers, testers, designers, and anyone who needs quick access to random data. Features include secure passwords, PINs, names, business data, dates, numbers, GUIDs, color codes, and more. Especially useful for designers who need random color codes and placeholder content. | | [Open With Cursor](https://github.com/VictorNoxx/PowerToys-Run-Cursor/) | [VictorNoxx](https://github.com/VictorNoxx) | Open Visual Studio, VS Code recents with Cursor AI | | [CheatSheets](https://github.com/ruslanlap/PowerToysRun-CheatSheets) | [ruslanlap](https://github.com/ruslanlap) | 📚 Find cheat sheets and command examples instantly from tldr pages, cheat.sh, and devhints.io. Features include favorites system, categories, offline mode, and smart caching. | +| [QuickAI](https://github.com/ruslanlap/PowerToysRun-QuickAi) | [ruslanlap](https://github.com/ruslanlap) | AI-powered assistance with instant, smart responses from multiple providers (Groq, Together, Fireworks, OpenRouter, Cohere) | ## Extending software plugins diff --git a/installer/PowerToysSetup.sln b/installer/PowerToysSetup.sln deleted file mode 100644 index 77d38c94ab..0000000000 --- a/installer/PowerToysSetup.sln +++ /dev/null @@ -1,96 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.1.32414.318 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spdlog", "..\src\logging\logging.vcxproj", "{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "logger", "..\src\common\logger\logger.vcxproj", "{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Version", "..\src\common\version\version.vcxproj", "{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EtwTrace", "..\src\common\Telemetry\EtwTrace\EtwTrace.vcxproj", "{8F021B46-362B-485C-BFBA-CCF83E820CBD}" -EndProject -Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "PowerToysInstallerVNext", "PowerToysSetupVNext\PowerToysInstallerVNext.wixproj", "{B6E94700-DF38-41F6-A3FD-18B69674AB1E}" -EndProject -Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "PowerToysBootstrapperVNext", "PowerToysSetupVNext\PowerToysBootstrapperVNext.wixproj", "{DA4E9744-80BE-424C-B0F5-AFD8757DB575}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerToysSetupCustomActionsVNext", "PowerToysSetupCustomActionsVNext\PowerToysSetupCustomActionsVNext.vcxproj", "{B3A354B0-1E54-4B55-A962-FB5AF9330C19}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SilentFilesInUseBAFunction", "PowerToysSetupVNext\SilentFilesInUseBA\SilentFilesInUseBAFunction.vcxproj", "{F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|ARM64 = Debug|ARM64 - Debug|x64 = Debug|x64 - Release|ARM64 = Release|ARM64 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|x64.ActiveCfg = Debug|x64 - {7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|x64.Build.0 = Debug|x64 - {7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|ARM64.ActiveCfg = Release|ARM64 - {7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|ARM64.Build.0 = Release|ARM64 - {7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|x64.ActiveCfg = Release|x64 - {7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|x64.Build.0 = Release|x64 - {D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Debug|x64.ActiveCfg = Debug|x64 - {D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Debug|x64.Build.0 = Debug|x64 - {D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|ARM64.ActiveCfg = Release|ARM64 - {D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|ARM64.Build.0 = Release|ARM64 - {D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|x64.ActiveCfg = Release|x64 - {D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|x64.Build.0 = Release|x64 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|ARM64.Build.0 = Debug|ARM64 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|x64.ActiveCfg = Debug|x64 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|x64.Build.0 = Debug|x64 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|ARM64.ActiveCfg = Release|ARM64 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|ARM64.Build.0 = Release|ARM64 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|x64.ActiveCfg = Release|x64 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|x64.Build.0 = Release|x64 - {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|ARM64.Build.0 = Debug|ARM64 - {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|x64.ActiveCfg = Debug|x64 - {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|x64.Build.0 = Debug|x64 - {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|ARM64.ActiveCfg = Release|ARM64 - {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|ARM64.Build.0 = Release|ARM64 - {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|x64.ActiveCfg = Release|x64 - {8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|x64.Build.0 = Release|x64 - {B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Debug|ARM64.Build.0 = Debug|ARM64 - {B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Debug|x64.ActiveCfg = Debug|x64 - {B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Debug|x64.Build.0 = Debug|x64 - {B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Release|ARM64.ActiveCfg = Release|ARM64 - {B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Release|ARM64.Build.0 = Release|ARM64 - {B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Release|x64.ActiveCfg = Release|x64 - {B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Release|x64.Build.0 = Release|x64 - {DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Debug|ARM64.Build.0 = Debug|ARM64 - {DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Debug|x64.ActiveCfg = Debug|x64 - {DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Debug|x64.Build.0 = Debug|x64 - {DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Release|ARM64.ActiveCfg = Release|ARM64 - {DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Release|ARM64.Build.0 = Release|ARM64 - {DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Release|x64.ActiveCfg = Release|x64 - {DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Release|x64.Build.0 = Release|x64 - {B3A354B0-1E54-4B55-A962-FB5AF9330C19}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {B3A354B0-1E54-4B55-A962-FB5AF9330C19}.Debug|x64.ActiveCfg = Debug|x64 - {B3A354B0-1E54-4B55-A962-FB5AF9330C19}.Debug|x64.Build.0 = Debug|x64 - {B3A354B0-1E54-4B55-A962-FB5AF9330C19}.Release|ARM64.ActiveCfg = Release|ARM64 - {B3A354B0-1E54-4B55-A962-FB5AF9330C19}.Release|ARM64.Build.0 = Release|ARM64 - {B3A354B0-1E54-4B55-A962-FB5AF9330C19}.Release|x64.ActiveCfg = Release|x64 - {B3A354B0-1E54-4B55-A962-FB5AF9330C19}.Release|x64.Build.0 = Release|x64 - {F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}.Debug|x64.ActiveCfg = Debug|x64 - {F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}.Debug|x64.Build.0 = Debug|x64 - {F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}.Release|ARM64.ActiveCfg = Release|ARM64 - {F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}.Release|ARM64.Build.0 = Release|ARM64 - {F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}.Release|x64.ActiveCfg = Release|x64 - {F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {B7A3DA30-D443-40FF-AC51-988AD41E3962} - EndGlobalSection -EndGlobal \ No newline at end of file diff --git a/installer/PowerToysSetup.slnx b/installer/PowerToysSetup.slnx new file mode 100644 index 0000000000..658310f9f6 --- /dev/null +++ b/installer/PowerToysSetup.slnx @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/common/UITestAutomation/SettingsConfigHelper.cs b/src/common/UITestAutomation/SettingsConfigHelper.cs index 55304d4dc0..81e5e3c180 100644 --- a/src/common/UITestAutomation/SettingsConfigHelper.cs +++ b/src/common/UITestAutomation/SettingsConfigHelper.cs @@ -21,7 +21,7 @@ namespace Microsoft.PowerToys.UITest public class SettingsConfigHelper { private static readonly JsonSerializerOptions IndentedJsonOptions = new() { WriteIndented = true }; - private static readonly SettingsUtils SettingsUtils = new SettingsUtils(); + private static readonly SettingsUtils SettingsUtils = SettingsUtils.Default; /// /// Configures global PowerToys settings to enable only specified modules and disable all others. diff --git a/src/common/utils/registry.h b/src/common/utils/registry.h index 059589352d..c9770bbea3 100644 --- a/src/common/utils/registry.h +++ b/src/common/utils/registry.h @@ -16,9 +16,54 @@ namespace registry { + namespace detail + { + struct on_exit + { + std::function f; + + on_exit(std::function f) : + f{ std::move(f) } {} + ~on_exit() { f(); } + }; + + template + struct overloaded : Ts... + { + using Ts::operator()...; + }; + + template + overloaded(Ts...) -> overloaded; + + inline const wchar_t* getScopeName(HKEY scope) + { + if (scope == HKEY_LOCAL_MACHINE) + { + return L"HKLM"; + } + else if (scope == HKEY_CURRENT_USER) + { + return L"HKCU"; + } + else if (scope == HKEY_CLASSES_ROOT) + { + return L"HKCR"; + } + else + { + return L"HK??"; + } + } + } + namespace install_scope { const wchar_t INSTALL_SCOPE_REG_KEY[] = L"Software\\Classes\\powertoys\\"; + const wchar_t UNINSTALL_REG_KEY[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; + + // Bundle UpgradeCode from PowerToys.wxs (with braces as stored in registry) + const wchar_t BUNDLE_UPGRADE_CODE[] = L"{6341382D-C0A9-4238-9188-BE9607E3FAB2}"; enum class InstallScope { @@ -26,8 +71,67 @@ namespace registry PerUser, }; + // Helper function to find PowerToys bundle in Windows Uninstall registry by BundleUpgradeCode + inline bool find_powertoys_bundle_in_uninstall_registry(HKEY rootKey) + { + HKEY uninstallKey{}; + if (RegOpenKeyExW(rootKey, UNINSTALL_REG_KEY, 0, KEY_READ, &uninstallKey) != ERROR_SUCCESS) + { + return false; + } + detail::on_exit closeUninstallKey{ [uninstallKey] { RegCloseKey(uninstallKey); } }; + + DWORD index = 0; + wchar_t subKeyName[256]; + + // Enumerate all subkeys under Uninstall + while (RegEnumKeyW(uninstallKey, index++, subKeyName, 256) == ERROR_SUCCESS) + { + HKEY productKey{}; + if (RegOpenKeyExW(uninstallKey, subKeyName, 0, KEY_READ, &productKey) != ERROR_SUCCESS) + { + continue; + } + detail::on_exit closeProductKey{ [productKey] { RegCloseKey(productKey); } }; + + // Check BundleUpgradeCode value (specific to WiX Bundle installations) + wchar_t bundleUpgradeCode[256]{}; + DWORD bundleUpgradeCodeSize = sizeof(bundleUpgradeCode); + + if (RegQueryValueExW(productKey, L"BundleUpgradeCode", nullptr, nullptr, + reinterpret_cast(bundleUpgradeCode), &bundleUpgradeCodeSize) == ERROR_SUCCESS) + { + if (_wcsicmp(bundleUpgradeCode, BUNDLE_UPGRADE_CODE) == 0) + { + return true; + } + } + } + + return false; + } + inline const InstallScope get_current_install_scope() { + // 1. Check HKCU Uninstall registry first (user-level bundle) + // Note: MSI components are always in HKLM regardless of install scope, + // but the Bundle entry will be in HKCU for per-user installations + if (find_powertoys_bundle_in_uninstall_registry(HKEY_CURRENT_USER)) + { + Logger::info(L"Found user-level PowerToys bundle via BundleUpgradeCode in HKCU"); + return InstallScope::PerUser; + } + + // 2. Check HKLM Uninstall registry (machine-level bundle) + if (find_powertoys_bundle_in_uninstall_registry(HKEY_LOCAL_MACHINE)) + { + Logger::info(L"Found machine-level PowerToys bundle via BundleUpgradeCode in HKLM"); + return InstallScope::PerMachine; + } + + // 3. Fallback to legacy custom registry key detection + Logger::info(L"PowerToys bundle not found in Uninstall registry, falling back to legacy detection"); + // Open HKLM key HKEY perMachineKey{}; if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, @@ -45,6 +149,7 @@ namespace registry &perUserKey) != ERROR_SUCCESS) { // both keys are missing + Logger::warn(L"No PowerToys installation detected, defaulting to PerMachine"); return InstallScope::PerMachine; } else @@ -96,47 +201,6 @@ namespace registry template inline constexpr bool always_false_v = false; - namespace detail - { - struct on_exit - { - std::function f; - - on_exit(std::function f) : - f{ std::move(f) } {} - ~on_exit() { f(); } - }; - - template - struct overloaded : Ts... - { - using Ts::operator()...; - }; - - template - overloaded(Ts...) -> overloaded; - - inline const wchar_t* getScopeName(HKEY scope) - { - if (scope == HKEY_LOCAL_MACHINE) - { - return L"HKLM"; - } - else if (scope == HKEY_CURRENT_USER) - { - return L"HKCU"; - } - else if (scope == HKEY_CLASSES_ROOT) - { - return L"HKCR"; - } - else - { - return L"HK??"; - } - } - } - struct ValueChange { using value_t = std::variant; diff --git a/src/dsc/v3/PowerToys.DSC.UnitTests/SettingsResourceTests/SettingsResourceModuleTest`1.cs b/src/dsc/v3/PowerToys.DSC.UnitTests/SettingsResourceTests/SettingsResourceModuleTest`1.cs index ad7eb1d200..8d43f48a77 100644 --- a/src/dsc/v3/PowerToys.DSC.UnitTests/SettingsResourceTests/SettingsResourceModuleTest`1.cs +++ b/src/dsc/v3/PowerToys.DSC.UnitTests/SettingsResourceTests/SettingsResourceModuleTest`1.cs @@ -18,7 +18,7 @@ namespace PowerToys.DSC.UnitTests.SettingsResourceTests; public abstract class SettingsResourceModuleTest : BaseDscTest where TSettingsConfig : ISettingsConfig, new() { - private readonly SettingsUtils _settingsUtils = new(); + private readonly SettingsUtils _settingsUtils = SettingsUtils.Default; private TSettingsConfig _originalSettings; protected TSettingsConfig DefaultSettings => new(); diff --git a/src/dsc/v3/PowerToys.DSC/Models/FunctionData/SettingsFunctionData`1.cs b/src/dsc/v3/PowerToys.DSC/Models/FunctionData/SettingsFunctionData`1.cs index 7fcce03d33..9d87b1e773 100644 --- a/src/dsc/v3/PowerToys.DSC/Models/FunctionData/SettingsFunctionData`1.cs +++ b/src/dsc/v3/PowerToys.DSC/Models/FunctionData/SettingsFunctionData`1.cs @@ -18,7 +18,7 @@ namespace PowerToys.DSC.Models.FunctionData; public sealed class SettingsFunctionData : BaseFunctionData, ISettingsFunctionData where TSettingsConfig : ISettingsConfig, new() { - private static readonly SettingsUtils _settingsUtils = new(); + private static readonly SettingsUtils _settingsUtils = SettingsUtils.Default; private static readonly TSettingsConfig _settingsConfig = new(); private readonly SettingsResourceObject _input; diff --git a/src/modules/AdvancedPaste/AdvancedPaste.UnitTests/ConvertersTests/HexColorToColorConverterTests.cs b/src/modules/AdvancedPaste/AdvancedPaste.UnitTests/ConvertersTests/HexColorToColorConverterTests.cs new file mode 100644 index 0000000000..b8915f278e --- /dev/null +++ b/src/modules/AdvancedPaste/AdvancedPaste.UnitTests/ConvertersTests/HexColorToColorConverterTests.cs @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using AdvancedPaste.Converters; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Windows.UI; + +namespace AdvancedPaste.UnitTests.ConvertersTests; + +[TestClass] +public sealed class HexColorToColorConverterTests +{ + [TestMethod] + public void TestConvert_ValidSixDigitHex_ReturnsColor() + { + Color? result = HexColorConverterHelper.ConvertHexColorToRgb("#FFBFAB"); + Assert.IsNotNull(result); + + var color = (Windows.UI.Color)result; + Assert.AreEqual(255, color.R); + Assert.AreEqual(191, color.G); + Assert.AreEqual(171, color.B); + Assert.AreEqual(255, color.A); + } + + [TestMethod] + public void TestConvert_ValidThreeDigitHex_ReturnsColor() + { + Color? result = HexColorConverterHelper.ConvertHexColorToRgb("#abc"); + Assert.IsNotNull(result); + + var color = (Windows.UI.Color)result; + + // #abc should expand to #aabbcc + Assert.AreEqual(170, color.R); // 0xaa + Assert.AreEqual(187, color.G); // 0xbb + Assert.AreEqual(204, color.B); // 0xcc + Assert.AreEqual(255, color.A); + } + + [TestMethod] + public void TestConvert_NullOrEmpty_ReturnsNull() + { + Assert.IsNull(HexColorConverterHelper.ConvertHexColorToRgb(null)); + Assert.IsNull(HexColorConverterHelper.ConvertHexColorToRgb(string.Empty)); + Assert.IsNull(HexColorConverterHelper.ConvertHexColorToRgb(" ")); + } + + [TestMethod] + public void TestConvert_InvalidHex_ReturnsNull() + { + Assert.IsNull(HexColorConverterHelper.ConvertHexColorToRgb("#GGGGGG")); + Assert.IsNull(HexColorConverterHelper.ConvertHexColorToRgb("#12345")); + } +} diff --git a/src/modules/AdvancedPaste/AdvancedPaste.UnitTests/HelpersTests/ClipboardItemHelperTests.cs b/src/modules/AdvancedPaste/AdvancedPaste.UnitTests/HelpersTests/ClipboardItemHelperTests.cs new file mode 100644 index 0000000000..2b2a2c7595 --- /dev/null +++ b/src/modules/AdvancedPaste/AdvancedPaste.UnitTests/HelpersTests/ClipboardItemHelperTests.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using AdvancedPaste.Helpers; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace AdvancedPaste.UnitTests.HelpersTests; + +[TestClass] +public sealed class ClipboardItemHelperTests +{ + [TestMethod] + [DataRow("#FFBFAB", true)] + [DataRow("#000000", true)] + [DataRow("#FFFFFF", true)] + [DataRow("#fff", true)] + [DataRow("#abc", true)] + [DataRow("#123456", true)] + [DataRow("#AbCdEf", true)] + [DataRow("FFBFAB", false)] // Missing # + [DataRow("#GGGGGG", false)] // Invalid hex characters + [DataRow("#12345", false)] // Wrong length + [DataRow("#1234567", false)] // Too long + [DataRow("", false)] + [DataRow(null, false)] + [DataRow(" #FFF ", true)] // Whitespace should be trimmed + [DataRow("Not a color", false)] + [DataRow("#", false)] + [DataRow("##FFFFFF", false)] + public void TestIsRgbHexColor(string input, bool expected) + { + bool result = ClipboardItemHelper.IsRgbHexColor(input); + Assert.AreEqual(expected, result, $"IsRgbHexColor(\"{input}\") should return {expected}"); + } +} diff --git a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Controls/ClipboardHistoryItemPreviewControl.xaml b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Controls/ClipboardHistoryItemPreviewControl.xaml index e008d35a9a..996f0c5b4f 100644 --- a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Controls/ClipboardHistoryItemPreviewControl.xaml +++ b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Controls/ClipboardHistoryItemPreviewControl.xaml @@ -11,6 +11,7 @@ mc:Ignorable="d"> + @@ -25,6 +26,26 @@ Source="{x:Bind ClipboardItem.Image, Mode=OneWay}" Stretch="UniformToFill" Visibility="{x:Bind HasImage, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" /> + + + + + + + + + ContentImage is not null; - public bool HasText => !string.IsNullOrEmpty(ContentText) && !HasImage; + public bool HasText => !string.IsNullOrEmpty(ContentText) && !HasImage && !HasColor; - public bool HasGlyph => !HasImage && !HasText && !string.IsNullOrEmpty(IconGlyph); + public bool HasGlyph => !HasImage && !HasText && !HasColor && !string.IsNullOrEmpty(IconGlyph); + + public bool HasColor => ClipboardItemHelper.IsRgbHexColor(ContentText); public ClipboardHistoryItemPreviewControl() { diff --git a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Converters/HexColorConverterHelper.cs b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Converters/HexColorConverterHelper.cs new file mode 100644 index 0000000000..388b4d3340 --- /dev/null +++ b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Converters/HexColorConverterHelper.cs @@ -0,0 +1,39 @@ +// 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. + +namespace AdvancedPaste.Converters +{ + public static class HexColorConverterHelper + { + public static Windows.UI.Color? ConvertHexColorToRgb(string hexColor) + { + try + { + // Remove # if present + var cleanHex = hexColor.TrimStart('#'); + + // Expand 3-digit hex to 6-digit (#ABC -> #AABBCC) + if (cleanHex.Length == 3) + { + cleanHex = $"{cleanHex[0]}{cleanHex[0]}{cleanHex[1]}{cleanHex[1]}{cleanHex[2]}{cleanHex[2]}"; + } + + if (cleanHex.Length == 6) + { + var r = System.Convert.ToByte(cleanHex.Substring(0, 2), 16); + var g = System.Convert.ToByte(cleanHex.Substring(2, 2), 16); + var b = System.Convert.ToByte(cleanHex.Substring(4, 2), 16); + + return Windows.UI.Color.FromArgb(255, r, g, b); + } + } + catch + { + // Invalid color format - return null + } + + return null; + } + } +} diff --git a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Converters/HexColorToBrushConverter.cs b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Converters/HexColorToBrushConverter.cs new file mode 100644 index 0000000000..436217462a --- /dev/null +++ b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Converters/HexColorToBrushConverter.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using Microsoft.UI.Xaml.Data; +using Microsoft.UI.Xaml.Media; + +namespace AdvancedPaste.Converters +{ + public sealed partial class HexColorToBrushConverter : IValueConverter + { + public object ConvertBack(object value, Type targetType, object parameter, string language) + => throw new NotSupportedException(); + + public object Convert(object value, Type targetType, object parameter, string language) + { + if (value is not string hexColor || string.IsNullOrWhiteSpace(hexColor)) + { + return null; + } + + Windows.UI.Color? color = HexColorConverterHelper.ConvertHexColorToRgb(hexColor); + + return color != null ? new SolidColorBrush((Windows.UI.Color)color) : null; + } + } +} diff --git a/src/modules/AdvancedPaste/AdvancedPaste/Helpers/ClipboardItemHelper.cs b/src/modules/AdvancedPaste/AdvancedPaste/Helpers/ClipboardItemHelper.cs index 9f824d3399..e4e18338c9 100644 --- a/src/modules/AdvancedPaste/AdvancedPaste/Helpers/ClipboardItemHelper.cs +++ b/src/modules/AdvancedPaste/AdvancedPaste/Helpers/ClipboardItemHelper.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Text.RegularExpressions; using System.Threading.Tasks; using AdvancedPaste.Models; using Microsoft.UI.Xaml.Media.Imaging; @@ -10,8 +11,11 @@ using Windows.ApplicationModel.DataTransfer; namespace AdvancedPaste.Helpers { - internal static class ClipboardItemHelper + internal static partial class ClipboardItemHelper { + // Compiled regex for better performance when checking multiple clipboard items + private static readonly Regex HexColorRegex = HexColorCompiledRegex(); + /// /// Creates a ClipboardItem from current clipboard data. /// @@ -55,6 +59,31 @@ namespace AdvancedPaste.Helpers return clipboardItem; } + /// + /// Checks if text is a valid RGB hex color (e.g., #FFBFAB or #fff). + /// + public static bool IsRgbHexColor(string text) + { + if (text == null) + { + return false; + } + + string trimmedText = text.Trim(); + if (trimmedText.Length > 7) + { + return false; + } + + if (string.IsNullOrWhiteSpace(trimmedText)) + { + return false; + } + + // Match #RGB or #RRGGBB format (case-insensitive) + return HexColorRegex.IsMatch(trimmedText); + } + /// /// Creates a BitmapImage from clipboard data. /// @@ -80,5 +109,8 @@ namespace AdvancedPaste.Helpers return null; } + + [GeneratedRegex(@"^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$")] + private static partial Regex HexColorCompiledRegex(); } } diff --git a/src/modules/Hosts/Hosts/Settings/UserSettings.cs b/src/modules/Hosts/Hosts/Settings/UserSettings.cs index 038823f0e2..bd69a336eb 100644 --- a/src/modules/Hosts/Hosts/Settings/UserSettings.cs +++ b/src/modules/Hosts/Hosts/Settings/UserSettings.cs @@ -62,7 +62,7 @@ namespace Hosts.Settings public UserSettings() { - _settingsUtils = new SettingsUtils(); + _settingsUtils = SettingsUtils.Default; var defaultSettings = new HostsProperties(); ShowStartupWarning = defaultSettings.ShowStartupWarning; LoopbackDuplicates = defaultSettings.LoopbackDuplicates; diff --git a/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.vcxproj b/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.vcxproj index 6de7c50b55..c71c81acec 100644 --- a/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.vcxproj +++ b/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.vcxproj @@ -1,14 +1,16 @@  - - - - - - - - - + + + PackageReference + + + native,Version=v0.0 + + + Windows + $(WindowsTargetPlatformVersion) + true true @@ -31,6 +33,11 @@ true true + + + + + DynamicLibrary @@ -38,7 +45,6 @@ true - @@ -118,9 +124,6 @@ true - - - {caba8dfb-823b-4bf2-93ac-3f31984150d9} @@ -142,42 +145,5 @@ - - - - - - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/modules/MeasureTool/MeasureToolCore/packages.config b/src/modules/MeasureTool/MeasureToolCore/packages.config deleted file mode 100644 index 6416ca5b16..0000000000 --- a/src/modules/MeasureTool/MeasureToolCore/packages.config +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/modules/MeasureTool/MeasureToolUI/MeasureToolUI.csproj b/src/modules/MeasureTool/MeasureToolUI/MeasureToolUI.csproj index 434ff088b2..3e92bd42f3 100644 --- a/src/modules/MeasureTool/MeasureToolUI/MeasureToolUI.csproj +++ b/src/modules/MeasureTool/MeasureToolUI/MeasureToolUI.csproj @@ -73,6 +73,13 @@ - + + false + true + + + + PreserveNewest + diff --git a/src/modules/MeasureTool/MeasureToolUI/Settings.cs b/src/modules/MeasureTool/MeasureToolUI/Settings.cs index 4e8cd99b18..ac48339ad6 100644 --- a/src/modules/MeasureTool/MeasureToolUI/Settings.cs +++ b/src/modules/MeasureTool/MeasureToolUI/Settings.cs @@ -11,7 +11,7 @@ namespace MeasureToolUI { public sealed class Settings { - private static readonly SettingsUtils ModuleSettings = new(); + private static readonly SettingsUtils ModuleSettings = SettingsUtils.Default; public MeasureToolMeasureStyle DefaultMeasureStyle { diff --git a/src/modules/MouseUtils/FindMyMouse/FindMyMouse.vcxproj b/src/modules/MouseUtils/FindMyMouse/FindMyMouse.vcxproj index d127de245e..bfed4af15d 100644 --- a/src/modules/MouseUtils/FindMyMouse/FindMyMouse.vcxproj +++ b/src/modules/MouseUtils/FindMyMouse/FindMyMouse.vcxproj @@ -1,13 +1,16 @@ - - - - - - - - + + + PackageReference + + + native,Version=v0.0 + + + Windows + $(WindowsTargetPlatformVersion) + 15.0 {e94fd11c-0591-456f-899f-efc0ca548336} @@ -20,9 +23,12 @@ false true false - - packages.config + + + + + DynamicLibrary @@ -127,18 +133,18 @@ - - - - - - - - - NotUsing - - + + + + + + + + NotUsing + + + <_ToDelete Include="$(OutDir)Microsoft.Web.WebView2.Core.dll" /> @@ -148,38 +154,4 @@ - - - - - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/modules/MouseUtils/FindMyMouse/packages.config b/src/modules/MouseUtils/FindMyMouse/packages.config deleted file mode 100644 index cff3aa8705..0000000000 --- a/src/modules/MouseUtils/FindMyMouse/packages.config +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/src/modules/MouseUtils/MouseJumpUI/Helpers/SettingsHelper.cs b/src/modules/MouseUtils/MouseJumpUI/Helpers/SettingsHelper.cs index efe721e873..6e19043547 100644 --- a/src/modules/MouseUtils/MouseJumpUI/Helpers/SettingsHelper.cs +++ b/src/modules/MouseUtils/MouseJumpUI/Helpers/SettingsHelper.cs @@ -53,7 +53,7 @@ internal sealed class SettingsHelper lock (this.LockObject) { { - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; // set this to 1 to disable retries var remainingRetries = 5; diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.Encryption.cs b/src/modules/MouseWithoutBorders/App/Class/Common.Encryption.cs deleted file mode 100644 index 1293a4ef39..0000000000 --- a/src/modules/MouseWithoutBorders/App/Class/Common.Encryption.cs +++ /dev/null @@ -1,248 +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. - -// -// Encrypt/decrypt implementation. -// -// -// 2008 created by Truong Do (ductdo). -// 2009-... modified by Truong Do (TruongDo). -// 2023- Included in PowerToys. -// -using System; -using System.Collections.Concurrent; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Security.Cryptography; -using System.Threading.Tasks; - -using MouseWithoutBorders.Core; - -namespace MouseWithoutBorders -{ - internal partial class Common - { -#pragma warning disable SYSLIB0021 - private static AesCryptoServiceProvider symAl; -#pragma warning restore SYSLIB0021 -#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter - internal static string myKey; -#pragma warning restore SA1307 - private static uint magicNumber; - private static Random ran = new(); // Used for non encryption related functionality. - internal const int SymAlBlockSize = 16; - - /// - /// This is used for the first encryption block, the following blocks will be combined with the cipher text of the previous block. - /// Thus identical blocks in the socket stream would be encrypted to different cipher text blocks. - /// The first block is a handshake one containing random data. - /// Related Unit Test: TestEncryptDecrypt - /// - internal static readonly string InitialIV = ulong.MaxValue.ToString(CultureInfo.InvariantCulture); - - internal static Random Ran - { - get => Common.ran ??= new Random(); - set => Common.ran = value; - } - - internal static uint MagicNumber - { - get => Common.magicNumber; - set => Common.magicNumber = value; - } - - internal static string MyKey - { - get => Common.myKey; - - set - { - if (Common.myKey != value) - { - Common.myKey = value; - _ = Task.Factory.StartNew( - () => Common.GenLegalKey(), - System.Threading.CancellationToken.None, - TaskCreationOptions.None, - TaskScheduler.Default); // Cache the key to improve UX. - } - } - } - - internal static string KeyDisplayedText(string key) - { - string displayedValue = string.Empty; - int i = 0; - - do - { - int length = Math.Min(4, key.Length - i); - displayedValue += string.Concat(key.AsSpan(i, length), " "); - i += 4; - } - while (i < key.Length - 1); - - return displayedValue.Trim(); - } - - internal static bool GeneratedKey { get; set; } - - internal static bool KeyCorrupted { get; set; } - - internal static void InitEncryption() - { - try - { - if (symAl == null) - { -#pragma warning disable SYSLIB0021 // No proper replacement for now - symAl = new AesCryptoServiceProvider(); -#pragma warning restore SYSLIB0021 - symAl.KeySize = 256; - symAl.BlockSize = SymAlBlockSize * 8; - symAl.Padding = PaddingMode.Zeros; - symAl.Mode = CipherMode.CBC; - symAl.GenerateIV(); - } - } - catch (Exception e) - { - Logger.Log(e); - } - } - - private static readonly ConcurrentDictionary LegalKeyDictionary = new(StringComparer.OrdinalIgnoreCase); - - internal static byte[] GenLegalKey() - { - byte[] rv; - string myKey = Common.MyKey; - - if (!LegalKeyDictionary.TryGetValue(myKey, out byte[] value)) - { - Rfc2898DeriveBytes key = new( - myKey, - Common.GetBytesU(InitialIV), - 50000, - HashAlgorithmName.SHA512); - rv = key.GetBytes(32); - _ = LegalKeyDictionary.AddOrUpdate(myKey, rv, (k, v) => rv); - } - else - { - rv = value; - } - - return rv; - } - - private static byte[] GenLegalIV() - { - string st = InitialIV; - int ivLength = symAl.IV.Length; - if (st.Length > ivLength) - { - st = st[..ivLength]; - } - else if (st.Length < ivLength) - { - st = st.PadRight(ivLength, ' '); - } - - return GetBytes(st); - } - - internal static Stream GetEncryptedStream(Stream encryptedStream) - { - ICryptoTransform encryptor; - encryptor = symAl.CreateEncryptor(GenLegalKey(), GenLegalIV()); - return new CryptoStream(encryptedStream, encryptor, CryptoStreamMode.Write); - } - - internal static Stream GetDecryptedStream(Stream encryptedStream) - { - ICryptoTransform decryptor; - decryptor = symAl.CreateDecryptor(GenLegalKey(), GenLegalIV()); - return new CryptoStream(encryptedStream, decryptor, CryptoStreamMode.Read); - } - - internal static uint Get24BitHash(string st) - { - if (string.IsNullOrEmpty(st)) - { - return 0; - } - - byte[] bytes = new byte[PACKAGE_SIZE]; - for (int i = 0; i < PACKAGE_SIZE; i++) - { - if (i < st.Length) - { - bytes[i] = (byte)st[i]; - } - } - - var hash = SHA512.Create(); - byte[] hashValue = hash.ComputeHash(bytes); - - for (int i = 0; i < 50000; i++) - { - hashValue = hash.ComputeHash(hashValue); - } - - Logger.LogDebug(string.Format(CultureInfo.CurrentCulture, "magic: {0},{1},{2}", hashValue[0], hashValue[1], hashValue[^1])); - hash.Clear(); - 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(); - } - - private const int PW_LENGTH = 16; - - public static string CreateRandomKey() - { - // Not including characters like "'`O0& since they are confusing to users. - string[] chars = new[] { "abcdefghjkmnpqrstuvxyz", "ABCDEFGHJKMNPQRSTUVXYZ", "123456789", "~!@#$%^*()_-+=:;<,>.?/\\|[]" }; - char[][] charactersUsedForKey = chars.Select(charset => Enumerable.Range(0, charset.Length - 1).Select(i => charset[i]).ToArray()).ToArray(); - byte[] randomData = new byte[1]; - string key = string.Empty; - - do - { - foreach (string set in chars) - { - randomData = RandomNumberGenerator.GetBytes(1); - key += set[randomData[0] % set.Length]; - - if (key.Length >= PW_LENGTH) - { - break; - } - } - } - while (key.Length < PW_LENGTH); - - return key; - } - - internal static bool IsKeyValid(string key, out string error) - { - error = string.IsNullOrEmpty(key) || key.Length < 16 - ? "Key must have at least 16 characters in length (spaces are discarded). Key must be auto generated in one of the machines." - : null; - - return error == null; - } - } -} diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.Package.cs b/src/modules/MouseWithoutBorders/App/Class/Common.Package.cs deleted file mode 100644 index baaf1c0544..0000000000 --- a/src/modules/MouseWithoutBorders/App/Class/Common.Package.cs +++ /dev/null @@ -1,262 +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. - -// -// Package format/conversion. -// -// -// 2008 created by Truong Do (ductdo). -// 2009-... modified by Truong Do (TruongDo). -// 2023- Included in PowerToys. -// -using System; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.InteropServices; - -// In X64, we are WOW -[module: SuppressMessage("Microsoft.Portability", "CA1900:ValueTypeFieldsShouldBePortable", Scope = "type", Target = "MouseWithoutBorders.DATA", Justification = "Dotnet port with style preservation")] - -namespace MouseWithoutBorders -{ - internal enum PackageType// : int - { - // Search for PACKAGE_TYPE_RELATED before changing these! - Invalid = 0xFF, - - Error = 0xFE, - - Hi = 2, - Hello = 3, - ByeBye = 4, - - Heartbeat = 20, - Awake = 21, - HideMouse = 50, - Heartbeat_ex = 51, - Heartbeat_ex_l2 = 52, - Heartbeat_ex_l3 = 53, - - Clipboard = 69, - ClipboardDragDrop = 70, - ClipboardDragDropEnd = 71, - ExplorerDragDrop = 72, - ClipboardCapture = 73, - CaptureScreenCommand = 74, - ClipboardDragDropOperation = 75, - ClipboardDataEnd = 76, - MachineSwitched = 77, - ClipboardAsk = 78, - ClipboardPush = 79, - - NextMachine = 121, - Keyboard = 122, - Mouse = 123, - ClipboardText = 124, - ClipboardImage = 125, - - Handshake = 126, - HandshakeAck = 127, - - Matrix = 128, - MatrixSwapFlag = 2, - MatrixTwoRowFlag = 4, - } - - internal struct PackageMonitor - { - internal ulong Keyboard; - internal ulong Mouse; - internal ulong Heartbeat; - internal ulong ByeBye; - internal ulong Hello; - internal ulong Matrix; - internal ulong ClipboardText; - internal ulong ClipboardImage; - internal ulong Clipboard; - internal ulong ClipboardDragDrop; - internal ulong ClipboardDragDropEnd; - internal ulong ClipboardAsk; - internal ulong ExplorerDragDrop; - internal ulong Nil; - - internal PackageMonitor(ulong value) - { - ClipboardDragDrop = ClipboardDragDropEnd = ExplorerDragDrop = - Keyboard = Mouse = Heartbeat = ByeBye = Hello = Clipboard = - Matrix = ClipboardImage = ClipboardText = Nil = ClipboardAsk = value; - } - } - - internal enum ID : uint - { - NONE = 0, - ALL = 255, - } - - internal enum ClipboardPostAction : uint - { - Other = 0, - Desktop = 1, - Mspaint = 2, - } - - [StructLayout(LayoutKind.Sequential)] - internal struct KEYBDDATA - { - [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Same name as in winAPI")] - internal int wVk; - [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Same name as in winAPI")] - internal int dwFlags; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct MOUSEDATA - { - internal int X; - internal int Y; - internal int WheelDelta; - [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Same name as in winAPI")] - internal int dwFlags; - } - - // The beauty of "union" in C# - [StructLayout(LayoutKind.Explicit)] - internal class DATA - { - [FieldOffset(0)] - internal PackageType Type; // 4 (first byte = package type, 1 = checksum, 2+3 = magic no.) - - [FieldOffset(sizeof(PackageType))] - internal int Id; // 4 - - [FieldOffset(sizeof(PackageType) + sizeof(uint))] - internal ID Src; // 4 - - [FieldOffset(sizeof(PackageType) + (2 * sizeof(uint)))] - internal ID Des; // 4 - - [FieldOffset(sizeof(PackageType) + (3 * sizeof(uint)))] - internal long DateTime; - - [FieldOffset(sizeof(PackageType) + (3 * sizeof(uint)) + sizeof(long))] - internal KEYBDDATA Kd; - - [FieldOffset(sizeof(PackageType) + (3 * sizeof(uint)))] - internal MOUSEDATA Md; - - [FieldOffset(sizeof(PackageType) + (3 * sizeof(uint)))] - internal ID Machine1; - - [FieldOffset(sizeof(PackageType) + (4 * sizeof(uint)))] - internal ID Machine2; - - [FieldOffset(sizeof(PackageType) + (5 * sizeof(uint)))] - internal ID Machine3; - - [FieldOffset(sizeof(PackageType) + (6 * sizeof(uint)))] - internal ID Machine4; - - [FieldOffset(sizeof(PackageType) + (3 * sizeof(uint)))] - internal ClipboardPostAction PostAction; - - [FieldOffset(sizeof(PackageType) + (7 * sizeof(uint)))] - private long machineNameP1; - - [FieldOffset(sizeof(PackageType) + (7 * sizeof(uint)) + sizeof(long))] - private long machineNameP2; - - [FieldOffset(sizeof(PackageType) + (7 * sizeof(uint)) + (2 * sizeof(long)))] - private long machineNameP3; - - [FieldOffset(sizeof(PackageType) + (7 * sizeof(uint)) + (3 * sizeof(long)))] - private long machineNameP4; - - internal string MachineName - { - get - { - string name = Common.GetString(BitConverter.GetBytes(machineNameP1)) - + Common.GetString(BitConverter.GetBytes(machineNameP2)) - + Common.GetString(BitConverter.GetBytes(machineNameP3)) - + Common.GetString(BitConverter.GetBytes(machineNameP4)); - return name.Trim(); - } - - set - { - byte[] machineName = Common.GetBytes(value.PadRight(32, ' ')); - machineNameP1 = BitConverter.ToInt64(machineName, 0); - machineNameP2 = BitConverter.ToInt64(machineName, 8); - machineNameP3 = BitConverter.ToInt64(machineName, 16); - machineNameP4 = BitConverter.ToInt64(machineName, 24); - } - } - - public DATA() - { - } - - public DATA(byte[] initialData) - { - Bytes = initialData; - } - - internal byte[] Bytes - { - get - { - byte[] buf = new byte[IsBigPackage ? Common.PACKAGE_SIZE_EX : Common.PACKAGE_SIZE]; - Array.Copy(StructToBytes(this), buf, IsBigPackage ? Common.PACKAGE_SIZE_EX : Common.PACKAGE_SIZE); - - return buf; - } - - set - { - Debug.Assert(value.Length <= Common.PACKAGE_SIZE_EX, "Length > package size"); - byte[] buf = new byte[Common.PACKAGE_SIZE_EX]; - Array.Copy(value, buf, value.Length); - BytesToStruct(buf, this); - } - } - - internal bool IsBigPackage - { - get => Type == 0 - ? throw new InvalidOperationException("Package type not set.") - : Type switch - { - PackageType.Hello or PackageType.Awake or PackageType.Heartbeat or PackageType.Heartbeat_ex or PackageType.Handshake or PackageType.HandshakeAck or PackageType.ClipboardPush or PackageType.Clipboard or PackageType.ClipboardAsk or PackageType.ClipboardImage or PackageType.ClipboardText or PackageType.ClipboardDataEnd => true, - _ => (Type & PackageType.Matrix) == PackageType.Matrix, - }; - } - - private byte[] StructToBytes(object structObject) - { - byte[] bytes = new byte[Common.PACKAGE_SIZE_EX]; - GCHandle bHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned); - Marshal.StructureToPtr(structObject, Marshal.UnsafeAddrOfPinnedArrayElement(bytes, 0), false); - bHandle.Free(); - return bytes; - } - - private void BytesToStruct(byte[] value, object structObject) - { - GCHandle bHandle = GCHandle.Alloc(value, GCHandleType.Pinned); - Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(value, 0), structObject); - bHandle.Free(); - } - } - - internal partial class Common - { - internal const byte PACKAGE_SIZE = 32; - internal const byte PACKAGE_SIZE_EX = 64; - internal const byte WP_PACKAGE_SIZE = 6; - internal static PackageMonitor PackageSent; - internal static PackageMonitor PackageReceived; - internal static int PackageID; - } -} diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.ShutdownWithPowerToys.cs b/src/modules/MouseWithoutBorders/App/Class/Common.ShutdownWithPowerToys.cs deleted file mode 100644 index 7c0dd4eb9b..0000000000 --- a/src/modules/MouseWithoutBorders/App/Class/Common.ShutdownWithPowerToys.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Microsoft Corporation -// The Microsoft Corporation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; - -using ManagedCommon; -using Microsoft.PowerToys.Telemetry; -using MouseWithoutBorders.Class; - -using Logger = MouseWithoutBorders.Core.Logger; - -namespace MouseWithoutBorders -{ - internal class ShutdownWithPowerToys - { - public static void WaitForPowerToysRunner(ETWTrace etwTrace) - { - try - { - RunnerHelper.WaitForPowerToysRunnerExitFallback(() => - { - etwTrace?.Dispose(); - Common.MainForm.Quit(true, false); - }); - } - catch (Exception e) - { - Logger.Log(e); - } - } - } -} diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.VK.cs b/src/modules/MouseWithoutBorders/App/Class/Common.VK.cs deleted file mode 100644 index 3f54a0281d..0000000000 --- a/src/modules/MouseWithoutBorders/App/Class/Common.VK.cs +++ /dev/null @@ -1,131 +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. - -// -// Virtual key constants. -// -// -// 2008 created by Truong Do (ductdo). -// 2009-... modified by Truong Do (TruongDo). -// 2023- Included in PowerToys. -// -using System; - -namespace MouseWithoutBorders -{ - internal enum VK : ushort - { - CAPITAL = 0x14, - NUMLOCK = 0x90, - SHIFT = 0x10, - CONTROL = 0x11, - MENU = 0x12, - ESCAPE = 0x1B, - BACK = 0x08, - TAB = 0x09, - RETURN = 0x0D, - PRIOR = 0x21, - NEXT = 0x22, - END = 0x23, - HOME = 0x24, - LEFT = 0x25, - UP = 0x26, - RIGHT = 0x27, - DOWN = 0x28, - SELECT = 0x29, - PRINT = 0x2A, - EXECUTE = 0x2B, - SNAPSHOT = 0x2C, - INSERT = 0x2D, - DELETE = 0x2E, - HELP = 0x2F, - NUMPAD0 = 0x60, - NUMPAD1 = 0x61, - NUMPAD2 = 0x62, - NUMPAD3 = 0x63, - NUMPAD4 = 0x64, - NUMPAD5 = 0x65, - NUMPAD6 = 0x66, - NUMPAD7 = 0x67, - NUMPAD8 = 0x68, - NUMPAD9 = 0x69, - MULTIPLY = 0x6A, - ADD = 0x6B, - SEPARATOR = 0x6C, - SUBTRACT = 0x6D, - DECIMAL = 0x6E, - DIVIDE = 0x6F, - F1 = 0x70, - F2 = 0x71, - F3 = 0x72, - F4 = 0x73, - F5 = 0x74, - F6 = 0x75, - F7 = 0x76, - F8 = 0x77, - F9 = 0x78, - F10 = 0x79, - F11 = 0x7A, - F12 = 0x7B, - OEM_1 = 0xBA, - OEM_PLUS = 0xBB, - OEM_COMMA = 0xBC, - OEM_MINUS = 0xBD, - OEM_PERIOD = 0xBE, - OEM_2 = 0xBF, - OEM_3 = 0xC0, - MEDIA_NEXT_TRACK = 0xB0, - MEDIA_PREV_TRACK = 0xB1, - MEDIA_STOP = 0xB2, - MEDIA_PLAY_PAUSE = 0xB3, - LWIN = 0x5B, - RWIN = 0x5C, - LSHIFT = 0xA0, - RSHIFT = 0xA1, - LCONTROL = 0xA2, - RCONTROL = 0xA3, - LMENU = 0xA4, - RMENU = 0xA5, - } - - internal partial class Common - { - internal const ushort KEYEVENTF_KEYDOWN = 0x0001; - internal const ushort KEYEVENTF_KEYUP = 0x0002; - - internal const int WH_MOUSE = 7; - internal const int WH_KEYBOARD = 2; - internal const int WH_MOUSE_LL = 14; - internal const int WH_KEYBOARD_LL = 13; - - internal const int WM_MOUSEMOVE = 0x200; - internal const int WM_LBUTTONDOWN = 0x201; - internal const int WM_RBUTTONDOWN = 0x204; - internal const int WM_MBUTTONDOWN = 0x207; - internal const int WM_XBUTTONDOWN = 0x20B; - internal const int WM_LBUTTONUP = 0x202; - internal const int WM_RBUTTONUP = 0x205; - internal const int WM_MBUTTONUP = 0x208; - internal const int WM_XBUTTONUP = 0x20C; - internal const int WM_LBUTTONDBLCLK = 0x203; - internal const int WM_RBUTTONDBLCLK = 0x206; - internal const int WM_MBUTTONDBLCLK = 0x209; - internal const int WM_MOUSEWHEEL = 0x020A; - internal const int WM_MOUSEHWHEEL = 0x020E; - - internal const int WM_KEYDOWN = 0x100; - internal const int WM_KEYUP = 0x101; - internal const int WM_SYSKEYDOWN = 0x104; - internal const int WM_SYSKEYUP = 0x105; - - [Flags] - internal enum LLKHF - { - EXTENDED = 0x01, - INJECTED = 0x10, - ALTDOWN = 0x20, - UP = 0x80, - } - } -} diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.WinAPI.cs b/src/modules/MouseWithoutBorders/App/Class/Common.WinAPI.cs deleted file mode 100644 index ee2d99398c..0000000000 --- a/src/modules/MouseWithoutBorders/App/Class/Common.WinAPI.cs +++ /dev/null @@ -1,363 +0,0 @@ -// Copyright (c) Microsoft Corporation -// The Microsoft Corporation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Drawing; -using System.Globalization; -using System.Linq; -using System.Runtime.InteropServices; -using System.Threading; -using System.Windows.Forms; - -// -// Screen/Desktop helper functions. -// -// -// 2008 created by Truong Do (ductdo). -// 2009-... modified by Truong Do (TruongDo). -// 2023- Included in PowerToys. -// -using MouseWithoutBorders.Class; -using MouseWithoutBorders.Core; - -using Thread = MouseWithoutBorders.Core.Thread; - -namespace MouseWithoutBorders -{ - // Desktops, and GetScreenConfig routines - internal partial class Common - { - private static MyRectangle newDesktopBounds; - private static MyRectangle newPrimaryScreenBounds; - private static string activeDesktop; - - internal static string ActiveDesktop => Common.activeDesktop; - - internal static void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e) - { - GetScreenConfig(); - } - - internal static readonly List SensitivePoints = new(); - - private static bool MonitorEnumProc(IntPtr hMonitor, IntPtr hdcMonitor, ref NativeMethods.RECT lprcMonitor, IntPtr dwData) - { - // lprcMonitor is wrong!!! => using GetMonitorInfo(...) - // Log(String.Format( CultureInfo.CurrentCulture,"MONITOR: l{0}, t{1}, r{2}, b{3}", lprcMonitor.Left, lprcMonitor.Top, lprcMonitor.Right, lprcMonitor.Bottom)); - NativeMethods.MonitorInfoEx mi = default; - mi.cbSize = Marshal.SizeOf(mi); - _ = NativeMethods.GetMonitorInfo(hMonitor, ref mi); - - try - { - // For logging only - _ = NativeMethods.GetDpiForMonitor(hMonitor, 0, out uint dpiX, out uint dpiY); - Logger.Log(string.Format(CultureInfo.CurrentCulture, "MONITOR: ({0}, {1}, {2}, {3}). DPI: ({4}, {5})", mi.rcMonitor.Left, mi.rcMonitor.Top, mi.rcMonitor.Right, mi.rcMonitor.Bottom, dpiX, dpiY)); - } - catch (DllNotFoundException) - { - Logger.Log("GetDpiForMonitor is unsupported in Windows 7 and lower."); - } - catch (EntryPointNotFoundException) - { - Logger.Log("GetDpiForMonitor is unsupported in Windows 7 and lower."); - } - catch (Exception e) - { - Logger.Log(e); - } - - if (mi.rcMonitor.Left == 0 && mi.rcMonitor.Top == 0 && mi.rcMonitor.Right != 0 && mi.rcMonitor.Bottom != 0) - { - // Primary screen - _ = Interlocked.Exchange(ref screenWidth, mi.rcMonitor.Right - mi.rcMonitor.Left); - _ = Interlocked.Exchange(ref screenHeight, mi.rcMonitor.Bottom - mi.rcMonitor.Top); - - newPrimaryScreenBounds.Left = mi.rcMonitor.Left; - newPrimaryScreenBounds.Top = mi.rcMonitor.Top; - newPrimaryScreenBounds.Right = mi.rcMonitor.Right; - newPrimaryScreenBounds.Bottom = mi.rcMonitor.Bottom; - } - else - { - if (mi.rcMonitor.Left < newDesktopBounds.Left) - { - newDesktopBounds.Left = mi.rcMonitor.Left; - } - - if (mi.rcMonitor.Top < newDesktopBounds.Top) - { - newDesktopBounds.Top = mi.rcMonitor.Top; - } - - if (mi.rcMonitor.Right > newDesktopBounds.Right) - { - newDesktopBounds.Right = mi.rcMonitor.Right; - } - - if (mi.rcMonitor.Bottom > newDesktopBounds.Bottom) - { - newDesktopBounds.Bottom = mi.rcMonitor.Bottom; - } - } - - lock (SensitivePoints) - { - SensitivePoints.Add(new Point(mi.rcMonitor.Left, mi.rcMonitor.Top)); - SensitivePoints.Add(new Point(mi.rcMonitor.Right, mi.rcMonitor.Top)); - SensitivePoints.Add(new Point(mi.rcMonitor.Right, mi.rcMonitor.Bottom)); - SensitivePoints.Add(new Point(mi.rcMonitor.Left, mi.rcMonitor.Bottom)); - } - - return true; - } - - internal static void GetScreenConfig() - { - try - { - Logger.LogDebug("==================== GetScreenConfig started"); - newDesktopBounds = new MyRectangle(); - newPrimaryScreenBounds = new MyRectangle(); - newDesktopBounds.Left = newPrimaryScreenBounds.Left = Screen.PrimaryScreen.Bounds.Left; - newDesktopBounds.Top = newPrimaryScreenBounds.Top = Screen.PrimaryScreen.Bounds.Top; - newDesktopBounds.Right = newPrimaryScreenBounds.Right = Screen.PrimaryScreen.Bounds.Right; - newDesktopBounds.Bottom = newPrimaryScreenBounds.Bottom = Screen.PrimaryScreen.Bounds.Bottom; - - Logger.Log(string.Format( - CultureInfo.CurrentCulture, - "logon = {0} PrimaryScreenBounds = {1},{2},{3},{4} desktopBounds = {5},{6},{7},{8}", - Common.RunOnLogonDesktop, - Common.newPrimaryScreenBounds.Left, - Common.newPrimaryScreenBounds.Top, - Common.newPrimaryScreenBounds.Right, - Common.newPrimaryScreenBounds.Bottom, - Common.newDesktopBounds.Left, - Common.newDesktopBounds.Top, - Common.newDesktopBounds.Right, - Common.newDesktopBounds.Bottom)); - -#if USE_MANAGED_ROUTINES - // Managed routines do not work well when running on secure desktop:( - screenWidth = Screen.PrimaryScreen.Bounds.Width; - screenHeight = Screen.PrimaryScreen.Bounds.Height; - screenCount = Screen.AllScreens.Length; - for (int i = 0; i < Screen.AllScreens.Length; i++) - { - if (Screen.AllScreens[i].Bounds.Left < desktopBounds.Left) desktopBounds.Left = Screen.AllScreens[i].Bounds.Left; - if (Screen.AllScreens[i].Bounds.Top < desktopBounds.Top) desktopBounds.Top = Screen.AllScreens[i].Bounds.Top; - if (Screen.AllScreens[i].Bounds.Right > desktopBounds.Right) desktopBounds.Right = Screen.AllScreens[i].Bounds.Right; - if (Screen.AllScreens[i].Bounds.Bottom > desktopBounds.Bottom) desktopBounds.Bottom = Screen.AllScreens[i].Bounds.Bottom; - } -#else - lock (SensitivePoints) - { - SensitivePoints.Clear(); - } - - NativeMethods.EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, MonitorEnumProc, IntPtr.Zero); - - // 1000 calls to EnumDisplayMonitors cost a dozen of milliseconds -#endif - Interlocked.Exchange(ref MachineStuff.desktopBounds, newDesktopBounds); - Interlocked.Exchange(ref MachineStuff.primaryScreenBounds, newPrimaryScreenBounds); - - Logger.Log(string.Format( - CultureInfo.CurrentCulture, - "logon = {0} PrimaryScreenBounds = {1},{2},{3},{4} desktopBounds = {5},{6},{7},{8}", - Common.RunOnLogonDesktop, - MachineStuff.PrimaryScreenBounds.Left, - MachineStuff.PrimaryScreenBounds.Top, - MachineStuff.PrimaryScreenBounds.Right, - MachineStuff.PrimaryScreenBounds.Bottom, - MachineStuff.DesktopBounds.Left, - MachineStuff.DesktopBounds.Top, - MachineStuff.DesktopBounds.Right, - MachineStuff.DesktopBounds.Bottom)); - - Logger.Log("==================== GetScreenConfig ended"); - } - catch (Exception e) - { - Logger.Log(e); - } - } - -#if USING_SCREEN_SAVER_ROUTINES - [DllImport("user32.dll", CharSet = CharSet.Auto)] - private static extern int PostMessage(IntPtr hWnd, int wMsg, int wParam, int lParam); - - [DllImport("user32.dll", CharSet = CharSet.Auto)] - private static extern IntPtr OpenDesktop(string hDesktop, int Flags, bool Inherit, UInt32 DesiredAccess); - - [DllImport("user32.dll", CharSet = CharSet.Auto)] - private static extern bool CloseDesktop(IntPtr hDesktop); - - [DllImport("user32.dll", CharSet = CharSet.Auto)] - private static extern bool EnumDesktopWindows( IntPtr hDesktop, EnumDesktopWindowsProc callback, IntPtr lParam); - - [DllImport("user32.dll", CharSet = CharSet.Auto)] - private static extern bool IsWindowVisible(IntPtr hWnd); - - [DllImport("user32.dll", CharSet = CharSet.Auto)] - private static extern bool SystemParametersInfo(int uAction, int uParam, ref int pvParam, int flags); - - private delegate bool EnumDesktopWindowsProc(IntPtr hDesktop, IntPtr lParam); - private const int WM_CLOSE = 16; - private const int SPI_GETSCREENSAVERRUNNING = 114; - - internal static bool IsScreenSaverRunning() - { - int isRunning = 0; - SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0,ref isRunning, 0); - return (isRunning != 0); - } - - internal static void CloseScreenSaver() - { - IntPtr hDesktop = OpenDesktop("Screen-saver", 0, false, DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS); - if (hDesktop != IntPtr.Zero) - { - LogDebug("Closing screen saver..."); - EnumDesktopWindows(hDesktop, new EnumDesktopWindowsProc(CloseScreenSaverFunc), IntPtr.Zero); - CloseDesktop(hDesktop); - } - } - - private static bool CloseScreenSaverFunc(IntPtr hWnd, IntPtr lParam) - { - if (IsWindowVisible(hWnd)) - { - LogDebug("Posting WM_CLOSE to " + hWnd.ToString(CultureInfo.InvariantCulture)); - PostMessage(hWnd, WM_CLOSE, 0, 0); - } - return true; - } -#endif - - internal static string GetMyDesktop() - { - byte[] arThreadDesktop = new byte[256]; - IntPtr hD = NativeMethods.GetThreadDesktop(NativeMethods.GetCurrentThreadId()); - if (hD != IntPtr.Zero) - { - _ = NativeMethods.GetUserObjectInformation(hD, NativeMethods.UOI_NAME, arThreadDesktop, arThreadDesktop.Length, out _); - return GetString(arThreadDesktop).Replace("\0", string.Empty); - } - - return string.Empty; - } - - internal static string GetInputDesktop() - { - byte[] arInputDesktop = new byte[256]; - IntPtr hD = NativeMethods.OpenInputDesktop(0, false, NativeMethods.DESKTOP_READOBJECTS); - if (hD != IntPtr.Zero) - { - _ = NativeMethods.GetUserObjectInformation(hD, NativeMethods.UOI_NAME, arInputDesktop, arInputDesktop.Length, out _); - return GetString(arInputDesktop).Replace("\0", string.Empty); - } - - return string.Empty; - } - - internal static void StartMMService(string desktopToRunMouseWithoutBordersOn) - { - if (!Common.RunWithNoAdminRight) - { - Logger.LogDebug("*** Starting on active Desktop: " + desktopToRunMouseWithoutBordersOn); - Service.StartMouseWithoutBordersService(desktopToRunMouseWithoutBordersOn); - } - } - - internal static void CheckForDesktopSwitchEvent(bool cleanupIfExit) - { - try - { - if (!IsMyDesktopActive() || Common.CurrentProcess.SessionId != NativeMethods.WTSGetActiveConsoleSessionId()) - { - Helper.RunDDHelper(true); - int waitCount = 20; - - while (NativeMethods.WTSGetActiveConsoleSessionId() == 0xFFFFFFFF && waitCount > 0) - { - waitCount--; - Logger.LogDebug("The session is detached/attached."); - Thread.Sleep(500); - } - - string myDesktop = GetMyDesktop(); - activeDesktop = GetInputDesktop(); - - Logger.LogDebug("*** Active Desktop = " + activeDesktop); - Logger.LogDebug("*** My Desktop = " + myDesktop); - - if (myDesktop.Equals(activeDesktop, StringComparison.OrdinalIgnoreCase)) - { - Logger.LogDebug("*** Active Desktop == My Desktop (TS session)"); - } - - if (!activeDesktop.Equals("winlogon", StringComparison.OrdinalIgnoreCase) && - !activeDesktop.Equals("default", StringComparison.OrdinalIgnoreCase) && - !activeDesktop.Equals("disconnect", StringComparison.OrdinalIgnoreCase)) - { - try - { - StartMMService(activeDesktop); - } - catch (Exception e) - { - Logger.Log($"{nameof(CheckForDesktopSwitchEvent)}: {e}"); - } - } - else - { - if (!myDesktop.Equals(activeDesktop, StringComparison.OrdinalIgnoreCase)) - { - Logger.Log("*** Active Desktop <> My Desktop"); - } - - uint sid = NativeMethods.WTSGetActiveConsoleSessionId(); - - if (Process.GetProcessesByName(Common.BinaryName).Any(p => (uint)p.SessionId == sid)) - { - Logger.Log("Found MouseWithoutBorders on the active session!"); - } - else - { - Logger.Log("MouseWithoutBorders not found on the active session!"); - StartMMService(null); - } - } - - if (!myDesktop.Equals("winlogon", StringComparison.OrdinalIgnoreCase) && - !myDesktop.Equals("default", StringComparison.OrdinalIgnoreCase)) - { - Logger.LogDebug("*** Desktop inactive, exiting: " + myDesktop); - Setting.Values.LastX = JUST_GOT_BACK_FROM_SCREEN_SAVER; - if (cleanupIfExit) - { - InitAndCleanup.Cleanup(); - } - - Process.GetCurrentProcess().KillProcess(); - } - } - } - catch (Exception e) - { - Logger.Log(e); - } - } - - private static Point p; - - internal static bool IsMyDesktopActive() - { - return NativeMethods.GetCursorPos(ref p); - } - } -} diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.cs b/src/modules/MouseWithoutBorders/App/Class/Common.cs index ba5a1655e0..9a34500b52 100644 --- a/src/modules/MouseWithoutBorders/App/Class/Common.cs +++ b/src/modules/MouseWithoutBorders/App/Class/Common.cs @@ -315,7 +315,7 @@ namespace MouseWithoutBorders if (!acquireMutex) { Process[] ps = Process.GetProcessesByName(Common.BinaryName); - Logger.TelemetryLogTrace($"Balance: {socketMutexBalance}, Active: {IsMyDesktopActive()}, Sid/Console: {Process.GetCurrentProcess().SessionId}/{NativeMethods.WTSGetActiveConsoleSessionId()}, Desktop/Input: {GetMyDesktop()}/{GetInputDesktop()}, count: {ps?.Length}.", SeverityLevel.Warning); + Logger.TelemetryLogTrace($"Balance: {socketMutexBalance}, Active: {WinAPI.IsMyDesktopActive()}, Sid/Console: {Process.GetCurrentProcess().SessionId}/{NativeMethods.WTSGetActiveConsoleSessionId()}, Desktop/Input: {WinAPI.GetMyDesktop()}/{WinAPI.GetInputDesktop()}, count: {ps?.Length}.", SeverityLevel.Warning); } Logger.LogDebug("SOCKET MUTEX ENDED."); @@ -358,7 +358,7 @@ namespace MouseWithoutBorders Logger.TelemetryLogTrace($"[{actionName}] took more than {(long)timeout.TotalSeconds}, restarting the process.", SeverityLevel.Warning, true); - string desktop = Common.GetMyDesktop(); + string desktop = WinAPI.GetMyDesktop(); MachineStuff.oneInstanceCheck?.Close(); _ = Process.Start(Application.ExecutablePath, desktop); Logger.LogDebug($"Started on desktop {desktop}"); @@ -514,7 +514,7 @@ namespace MouseWithoutBorders internal static void SendHeartBeat(bool initial = false) { - SendPackage(ID.ALL, initial && Common.GeneratedKey ? PackageType.Heartbeat_ex : PackageType.Heartbeat); + SendPackage(ID.ALL, initial && Encryption.GeneratedKey ? PackageType.Heartbeat_ex : PackageType.Heartbeat); } private static long lastSendNextMachine; @@ -550,7 +550,7 @@ namespace MouseWithoutBorders internal static void SendAwakeBeat() { - if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && Common.IsMyDesktopActive() && + if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && WinAPI.IsMyDesktopActive() && Setting.Values.BlockScreenSaver && lastRealInputEventCount != Event.RealInputEventCount) { SendPackage(ID.ALL, PackageType.Awake); @@ -568,7 +568,7 @@ namespace MouseWithoutBorders { if (lastInputEventCount == Event.InputEventCount) { - if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && Common.IsMyDesktopActive()) + if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && WinAPI.IsMyDesktopActive()) { PokeMyself(); } @@ -577,13 +577,13 @@ namespace MouseWithoutBorders lastInputEventCount = Event.InputEventCount; } - private static void PokeMyself() + internal static void PokeMyself() { int x, y = 0; for (int i = 0; i < 10; i++) { - x = Ran.Next(-9, 10); + x = Encryption.Ran.Next(-9, 10); InputSimulation.MoveMouseRelative(x, y); Thread.Sleep(50); InputSimulation.MoveMouseRelative(-x, -y); @@ -677,7 +677,7 @@ namespace MouseWithoutBorders { Common.MMSleep(0.2); InputSimulation.SendKey(new KEYBDDATA() { wVk = (int)VK.SNAPSHOT }); - InputSimulation.SendKey(new KEYBDDATA() { dwFlags = (int)Common.LLKHF.UP, wVk = (int)VK.SNAPSHOT }); + InputSimulation.SendKey(new KEYBDDATA() { dwFlags = (int)WM.LLKHF.UP, wVk = (int)VK.SNAPSHOT }); Logger.LogDebug("PrepareScreenCapture: SNAPSHOT simulated."); @@ -710,7 +710,7 @@ namespace MouseWithoutBorders "\"" + Environment.ExpandEnvironmentVariables(@"%SystemRoot%\System32\Mspaint.exe") + "\"", "\"" + file + "\"", - GetInputDesktop(), + WinAPI.GetInputDesktop(), 1); // CreateNormalIntegrityProcess(Environment.ExpandEnvironmentVariables(@"%SystemRoot%\System32\Mspaint.exe") + @@ -919,7 +919,7 @@ namespace MouseWithoutBorders try { - data.Id = Interlocked.Increment(ref PackageID); + data.Id = Interlocked.Increment(ref Package.PackageID); bool updateClientSockets = false; @@ -999,7 +999,7 @@ namespace MouseWithoutBorders } else { - PackageSent.Nil++; + Package.PackageSent.Nil++; } } @@ -1379,7 +1379,7 @@ namespace MouseWithoutBorders if (string.IsNullOrEmpty(machine_Name)) { - machine_Name = "RANDOM" + Ran.Next().ToString(CultureInfo.CurrentCulture); + machine_Name = "RANDOM" + Encryption.Ran.Next().ToString(CultureInfo.CurrentCulture); } } @@ -1533,13 +1533,13 @@ namespace MouseWithoutBorders internal static void SendOrReceiveARandomDataBlockPerInitialIV(Stream st, bool send = true) { - byte[] ranData = new byte[SymAlBlockSize]; + byte[] ranData = new byte[Encryption.SymAlBlockSize]; try { if (send) { - ranData = RandomNumberGenerator.GetBytes(SymAlBlockSize); + ranData = RandomNumberGenerator.GetBytes(Encryption.SymAlBlockSize); st.Write(ranData, 0, ranData.Length); } else diff --git a/src/modules/MouseWithoutBorders/App/Class/InputHook.cs b/src/modules/MouseWithoutBorders/App/Class/InputHook.cs index d68b1a1584..53e815c1a0 100644 --- a/src/modules/MouseWithoutBorders/App/Class/InputHook.cs +++ b/src/modules/MouseWithoutBorders/App/Class/InputHook.cs @@ -109,7 +109,7 @@ namespace MouseWithoutBorders.Class // Install Mouse Hook mouseHookProcedure = new NativeMethods.HookProc(MouseHookProc); hMouseHook = NativeMethods.SetWindowsHookEx( - Common.WH_MOUSE_LL, + WM.WH_MOUSE_LL, mouseHookProcedure, Marshal.GetHINSTANCE( Assembly.GetExecutingAssembly().GetModules()[0]), @@ -126,7 +126,7 @@ namespace MouseWithoutBorders.Class // Install Keyboard Hook keyboardHookProcedure = new NativeMethods.HookProc(KeyboardHookProc); hKeyboardHook = NativeMethods.SetWindowsHookEx( - Common.WH_KEYBOARD_LL, + WM.WH_KEYBOARD_LL, keyboardHookProcedure, Marshal.GetHINSTANCE( Assembly.GetExecutingAssembly().GetModules()[0]), @@ -233,7 +233,7 @@ namespace MouseWithoutBorders.Class if (nCode >= 0 && MouseEvent != null) { - if (wParam == Common.WM_LBUTTONUP && SkipMouseUpCount > 0) + if (wParam == WM.WM_LBUTTONUP && SkipMouseUpCount > 0) { Logger.LogDebug($"{nameof(SkipMouseUpCount)}: {SkipMouseUpCount}."); SkipMouseUpCount--; @@ -241,7 +241,7 @@ namespace MouseWithoutBorders.Class return rv; } - if ((wParam == Common.WM_LBUTTONUP || wParam == Common.WM_LBUTTONDOWN) && SkipMouseUpDown) + if ((wParam == WM.WM_LBUTTONUP || wParam == WM.WM_LBUTTONDOWN) && SkipMouseUpDown) { rv = NativeMethods.CallNextHookEx(hMouseHook, nCode, wParam, lParam); return rv; @@ -370,7 +370,7 @@ namespace MouseWithoutBorders.Class private bool ProcessKeyEx(int vkCode, int flags, KEYBDDATA hookCallbackKeybdData) { - if ((flags & (int)Common.LLKHF.UP) == (int)Common.LLKHF.UP) + if ((flags & (int)WM.LLKHF.UP) == (int)WM.LLKHF.UP) { EasyMouseKeyDown = false; @@ -553,7 +553,7 @@ namespace MouseWithoutBorders.Class KeyboardEvent(hookCallbackKeybdData); } - hookCallbackKeybdData.dwFlags |= (int)Common.LLKHF.UP; + hookCallbackKeybdData.dwFlags |= (int)WM.LLKHF.UP; foreach (var code in codes) { diff --git a/src/modules/MouseWithoutBorders/App/Class/InputSimulation.cs b/src/modules/MouseWithoutBorders/App/Class/InputSimulation.cs index e735db814c..156f69597d 100644 --- a/src/modules/MouseWithoutBorders/App/Class/InputSimulation.cs +++ b/src/modules/MouseWithoutBorders/App/Class/InputSimulation.cs @@ -112,12 +112,12 @@ namespace MouseWithoutBorders.Class uint scanCode = 0; // http://msdn.microsoft.com/en-us/library/ms644967(VS.85).aspx - if ((kd.dwFlags & (int)Common.LLKHF.UP) == (int)Common.LLKHF.UP) + if ((kd.dwFlags & (int)WM.LLKHF.UP) == (int)WM.LLKHF.UP) { dwFlags = NativeMethods.KEYEVENTF.KEYUP; } - if ((kd.dwFlags & (int)Common.LLKHF.EXTENDED) == (int)Common.LLKHF.EXTENDED) + if ((kd.dwFlags & (int)WM.LLKHF.EXTENDED) == (int)WM.LLKHF.EXTENDED) { dwFlags |= NativeMethods.KEYEVENTF.EXTENDEDKEY; } @@ -173,44 +173,44 @@ namespace MouseWithoutBorders.Class mouse_input.mi.dy = (int)dy; mouse_input.mi.mouseData = md.WheelDelta; - if (md.dwFlags != Common.WM_MOUSEMOVE) + if (md.dwFlags != WM.WM_MOUSEMOVE) { Logger.LogDebug($"InputSimulation.SendMouse: x = {md.X}, y = {md.Y}, WheelDelta = {md.WheelDelta}, dwFlags = {md.dwFlags}."); } switch (md.dwFlags) { - case Common.WM_MOUSEMOVE: + case WM.WM_MOUSEMOVE: mouse_input.mi.dwFlags |= (int)(NativeMethods.MOUSEEVENTF.MOVE | NativeMethods.MOUSEEVENTF.ABSOLUTE); break; - case Common.WM_LBUTTONDOWN: + case WM.WM_LBUTTONDOWN: mouse_input.mi.dwFlags |= (int)NativeMethods.MOUSEEVENTF.LEFTDOWN; break; - case Common.WM_LBUTTONUP: + case WM.WM_LBUTTONUP: mouse_input.mi.dwFlags |= (int)NativeMethods.MOUSEEVENTF.LEFTUP; break; - case Common.WM_RBUTTONDOWN: + case WM.WM_RBUTTONDOWN: mouse_input.mi.dwFlags |= (int)NativeMethods.MOUSEEVENTF.RIGHTDOWN; break; - case Common.WM_RBUTTONUP: + case WM.WM_RBUTTONUP: mouse_input.mi.dwFlags |= (int)NativeMethods.MOUSEEVENTF.RIGHTUP; break; - case Common.WM_MBUTTONDOWN: + case WM.WM_MBUTTONDOWN: mouse_input.mi.dwFlags |= (int)NativeMethods.MOUSEEVENTF.MIDDLEDOWN; break; - case Common.WM_MBUTTONUP: + case WM.WM_MBUTTONUP: mouse_input.mi.dwFlags |= (int)NativeMethods.MOUSEEVENTF.MIDDLEUP; break; - case Common.WM_MOUSEWHEEL: + case WM.WM_MOUSEWHEEL: mouse_input.mi.dwFlags |= (int)NativeMethods.MOUSEEVENTF.WHEEL; break; - case Common.WM_MOUSEHWHEEL: + case WM.WM_MOUSEHWHEEL: mouse_input.mi.dwFlags |= (int)NativeMethods.MOUSEEVENTF.HWHEEL; break; - case Common.WM_XBUTTONUP: + case WM.WM_XBUTTONUP: mouse_input.mi.dwFlags |= (int)NativeMethods.MOUSEEVENTF.XUP; break; - case Common.WM_XBUTTONDOWN: + case WM.WM_XBUTTONDOWN: mouse_input.mi.dwFlags |= (int)NativeMethods.MOUSEEVENTF.XDOWN; break; @@ -373,7 +373,7 @@ namespace MouseWithoutBorders.Class { eatKey = false; - if ((flags & (int)Common.LLKHF.UP) == (int)Common.LLKHF.UP) + if ((flags & (int)WM.LLKHF.UP) == (int)WM.LLKHF.UP) { switch ((VK)vkCode) { diff --git a/src/modules/MouseWithoutBorders/App/Class/Program.cs b/src/modules/MouseWithoutBorders/App/Class/Program.cs index c139da46e9..23513e1515 100644 --- a/src/modules/MouseWithoutBorders/App/Class/Program.cs +++ b/src/modules/MouseWithoutBorders/App/Class/Program.cs @@ -143,7 +143,7 @@ namespace MouseWithoutBorders.Class return; } - string myDesktop = Common.GetMyDesktop(); + string myDesktop = WinAPI.GetMyDesktop(); if (firstArg.Equals("winlogon", StringComparison.OrdinalIgnoreCase)) { @@ -305,8 +305,8 @@ namespace MouseWithoutBorders.Class MachineStuff.ClearComputerMatrix(); Setting.Values.MyKey = securityKey; - Common.MyKey = securityKey; - Common.MagicNumber = Common.Get24BitHash(Common.MyKey); + Encryption.MyKey = securityKey; + Encryption.MagicNumber = Encryption.Get24BitHash(Encryption.MyKey); MachineStuff.MachineMatrix = new string[MachineStuff.MAX_MACHINE] { pcName.Trim().ToUpper(CultureInfo.CurrentCulture), Common.MachineName.Trim(), string.Empty, string.Empty }; string[] machines = MachineStuff.MachineMatrix; @@ -328,8 +328,8 @@ namespace MouseWithoutBorders.Class Setting.Values.EasyMouse = (int)EasyMouseOption.Enable; MachineStuff.ClearComputerMatrix(); - Setting.Values.MyKey = Common.MyKey = Common.CreateRandomKey(); - Common.GeneratedKey = true; + Setting.Values.MyKey = Encryption.MyKey = Encryption.CreateRandomKey(); + Encryption.GeneratedKey = true; Setting.Values.PauseInstantSaving = false; Setting.Values.SaveSettings(); diff --git a/src/modules/MouseWithoutBorders/App/Class/Setting.cs b/src/modules/MouseWithoutBorders/App/Class/Setting.cs index 623571f6ce..7d440a6125 100644 --- a/src/modules/MouseWithoutBorders/App/Class/Setting.cs +++ b/src/modules/MouseWithoutBorders/App/Class/Setting.cs @@ -109,9 +109,9 @@ namespace MouseWithoutBorders.Class var shouldReopenSockets = false; - if (Common.MyKey != _properties.SecurityKey.Value) + if (Encryption.MyKey != _properties.SecurityKey.Value) { - Common.MyKey = _properties.SecurityKey.Value; + Encryption.MyKey = _properties.SecurityKey.Value; shouldReopenSockets = true; } @@ -192,7 +192,7 @@ namespace MouseWithoutBorders.Class internal Settings() { - _settingsUtils = new SettingsUtils(); + _settingsUtils = SettingsUtils.Default; _watcher = SettingsHelper.GetFileWatcher("MouseWithoutBorders", "settings.json", () => { @@ -489,7 +489,7 @@ namespace MouseWithoutBorders.Class } else { - string randomKey = Common.CreateDefaultKey(); + string randomKey = Encryption.CreateDefaultKey(); _properties.SecurityKey.Value = randomKey; return randomKey; @@ -1055,7 +1055,7 @@ namespace MouseWithoutBorders.Class if (machineId == 0) { - var newMachineId = Common.Ran.Next(); + var newMachineId = Encryption.Ran.Next(); _properties.MachineID.Value = newMachineId; machineId = newMachineId; if (!PauseInstantSaving) diff --git a/src/modules/MouseWithoutBorders/App/Class/SocketStuff.cs b/src/modules/MouseWithoutBorders/App/Class/SocketStuff.cs index c5241beddf..575c9582df 100644 --- a/src/modules/MouseWithoutBorders/App/Class/SocketStuff.cs +++ b/src/modules/MouseWithoutBorders/App/Class/SocketStuff.cs @@ -101,7 +101,7 @@ namespace MouseWithoutBorders.Class { if (encryptedStream == null && BackingSocket.Connected) { - encryptedStream = Common.GetEncryptedStream(new NetworkStream(BackingSocket)); + encryptedStream = Encryption.GetEncryptedStream(new NetworkStream(BackingSocket)); Common.SendOrReceiveARandomDataBlockPerInitialIV(encryptedStream); } @@ -115,7 +115,7 @@ namespace MouseWithoutBorders.Class { if (decryptedStream == null && BackingSocket.Connected) { - decryptedStream = Common.GetDecryptedStream(new NetworkStream(BackingSocket)); + decryptedStream = Encryption.GetDecryptedStream(new NetworkStream(BackingSocket)); Common.SendOrReceiveARandomDataBlockPerInitialIV(decryptedStream, false); } @@ -181,7 +181,7 @@ namespace MouseWithoutBorders.Class Logger.LogDebug("SocketStuff started."); bASE_PORT = port; - Common.Ran = new Random(); + Encryption.Ran = new Random(); Logger.LogDebug("Validating session..."); @@ -221,11 +221,11 @@ namespace MouseWithoutBorders.Class if (Setting.Values.IsMyKeyRandom) { - Setting.Values.MyKey = Common.MyKey; + Setting.Values.MyKey = Encryption.MyKey; } - Common.MagicNumber = Common.Get24BitHash(Common.MyKey); - Common.PackageID = Setting.Values.PackageID; + Encryption.MagicNumber = Encryption.Get24BitHash(Encryption.MyKey); + Package.PackageID = Setting.Values.PackageID; TcpPort = bASE_PORT; @@ -242,7 +242,7 @@ namespace MouseWithoutBorders.Class Logger.TelemetryLogTrace($"{nameof(SocketStuff)}: {e.Message}", SeverityLevel.Warning); } - Common.GetScreenConfig(); + WinAPI.GetScreenConfig(); if (firstRun && Common.RunOnScrSaverDesktop) { @@ -305,7 +305,7 @@ namespace MouseWithoutBorders.Class sleepSecs = 10; // It is reasonable to give a try on restarting MwB processes in other sessions. - if (restartCount++ < 5 && Common.IsMyDesktopActive() && !Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop) + if (restartCount++ < 5 && WinAPI.IsMyDesktopActive() && !Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop) { Logger.TelemetryLogTrace("Restarting the service dues to WSAEADDRINUSE.", SeverityLevel.Warning); Program.StartService(); @@ -361,7 +361,7 @@ namespace MouseWithoutBorders.Class { Setting.Values.LastX = Common.LastX; Setting.Values.LastY = Common.LastY; - Setting.Values.PackageID = Common.PackageID; + Setting.Values.PackageID = Package.PackageID; // Common.Log("Saving IP: " + Setting.Values.DesMachineID.ToString(CultureInfo.CurrentCulture)); Setting.Values.DesMachineID = (uint)Common.DesMachineID; @@ -505,10 +505,10 @@ namespace MouseWithoutBorders.Class throw new ExpectedSocketException(log); } - bytes[3] = (byte)((Common.MagicNumber >> 24) & 0xFF); - bytes[2] = (byte)((Common.MagicNumber >> 16) & 0xFF); + bytes[3] = (byte)((Encryption.MagicNumber >> 24) & 0xFF); + bytes[2] = (byte)((Encryption.MagicNumber >> 16) & 0xFF); bytes[1] = 0; - for (int i = 2; i < Common.PACKAGE_SIZE; i++) + for (int i = 2; i < Package.PACKAGE_SIZE; i++) { bytes[1] = (byte)(bytes[1] + bytes[i]); } @@ -535,13 +535,13 @@ namespace MouseWithoutBorders.Class magic = (buf[3] << 24) + (buf[2] << 16); - if (magic != (Common.MagicNumber & 0xFFFF0000)) + if (magic != (Encryption.MagicNumber & 0xFFFF0000)) { Logger.Log("Magic number invalid!"); buf[0] = (byte)PackageType.Invalid; } - for (int i = 2; i < Common.PACKAGE_SIZE; i++) + for (int i = 2; i < Package.PACKAGE_SIZE; i++) { checksum = (byte)(checksum + buf[i]); } @@ -557,7 +557,7 @@ namespace MouseWithoutBorders.Class internal static DATA TcpReceiveData(TcpSk tcp, out int bytesReceived) { - byte[] buf = new byte[Common.PACKAGE_SIZE_EX]; + byte[] buf = new byte[Package.PACKAGE_SIZE_EX]; Stream decryptedStream = tcp.DecryptedStream; if (tcp.BackingSocket == null || !tcp.BackingSocket.Connected || decryptedStream == null) @@ -571,9 +571,9 @@ namespace MouseWithoutBorders.Class try { - bytesReceived = decryptedStream.ReadEx(buf, 0, Common.PACKAGE_SIZE); + bytesReceived = decryptedStream.ReadEx(buf, 0, Package.PACKAGE_SIZE); - if (bytesReceived != Common.PACKAGE_SIZE) + if (bytesReceived != Package.PACKAGE_SIZE) { buf[0] = bytesReceived == 0 ? (byte)PackageType.Error : (byte)PackageType.Invalid; } @@ -586,9 +586,9 @@ namespace MouseWithoutBorders.Class if (package.IsBigPackage) { - bytesReceived = decryptedStream.ReadEx(buf, Common.PACKAGE_SIZE, Common.PACKAGE_SIZE); + bytesReceived = decryptedStream.ReadEx(buf, Package.PACKAGE_SIZE, Package.PACKAGE_SIZE); - if (bytesReceived != Common.PACKAGE_SIZE) + if (bytesReceived != Package.PACKAGE_SIZE) { buf[0] = bytesReceived == 0 ? (byte)PackageType.Error : (byte)PackageType.Invalid; } @@ -614,28 +614,28 @@ namespace MouseWithoutBorders.Class switch (type) { case PackageType.Keyboard: - Common.PackageSent.Keyboard++; + Package.PackageSent.Keyboard++; break; case PackageType.Mouse: - Common.PackageSent.Mouse++; + Package.PackageSent.Mouse++; break; case PackageType.Heartbeat: case PackageType.Heartbeat_ex: - Common.PackageSent.Heartbeat++; + Package.PackageSent.Heartbeat++; break; case PackageType.Hello: - Common.PackageSent.Hello++; + Package.PackageSent.Hello++; break; case PackageType.ByeBye: - Common.PackageSent.ByeBye++; + Package.PackageSent.ByeBye++; break; case PackageType.Matrix: - Common.PackageSent.Matrix++; + Package.PackageSent.Matrix++; break; default: @@ -643,11 +643,11 @@ namespace MouseWithoutBorders.Class switch (subtype) { case (byte)PackageType.ClipboardText: - Common.PackageSent.ClipboardText++; + Package.PackageSent.ClipboardText++; break; case (byte)PackageType.ClipboardImage: - Common.PackageSent.ClipboardImage++; + Package.PackageSent.ClipboardImage++; break; default: @@ -1266,7 +1266,7 @@ namespace MouseWithoutBorders.Class string strIP = string.Empty; ID remoteID = ID.NONE; - byte[] buf = RandomNumberGenerator.GetBytes(Common.PACKAGE_SIZE_EX); + byte[] buf = RandomNumberGenerator.GetBytes(Package.PACKAGE_SIZE_EX); d = new DATA(buf); TcpSk currentTcp = tcp; @@ -1280,8 +1280,8 @@ namespace MouseWithoutBorders.Class try { - currentSocket.SendBufferSize = Common.PACKAGE_SIZE * 10000; - currentSocket.ReceiveBufferSize = Common.PACKAGE_SIZE * 10000; + currentSocket.SendBufferSize = Package.PACKAGE_SIZE * 10000; + currentSocket.ReceiveBufferSize = Package.PACKAGE_SIZE * 10000; currentSocket.NoDelay = true; // This is very interesting to know:( currentSocket.SendTimeout = 500; d.MachineName = Common.MachineName; @@ -1829,7 +1829,7 @@ namespace MouseWithoutBorders.Class } while (rv > 0); - if ((rv = Common.PACKAGE_SIZE - (sentCount % Common.PACKAGE_SIZE)) > 0) + if ((rv = Package.PACKAGE_SIZE - (sentCount % Package.PACKAGE_SIZE)) > 0) { Array.Clear(buf, 0, buf.Length); ecStream.Write(buf, 0, rv); @@ -1900,7 +1900,7 @@ namespace MouseWithoutBorders.Class } while (rv > 0); - if ((rv = sentCount % Common.PACKAGE_SIZE) > 0) + if ((rv = sentCount % Package.PACKAGE_SIZE) > 0) { Array.Clear(buf, 0, buf.Length); ecStream.Write(buf, 0, rv); @@ -1984,7 +1984,7 @@ namespace MouseWithoutBorders.Class if (tcp.MachineId == Setting.Values.MachineId) { tcp = null; - Setting.Values.MachineId = Common.Ran.Next(); + Setting.Values.MachineId = Encryption.Ran.Next(); InitAndCleanup.UpdateMachineTimeAndID(); InitAndCleanup.PleaseReopenSocket = InitAndCleanup.REOPEN_WHEN_HOTKEY; diff --git a/src/modules/MouseWithoutBorders/App/Class/TcpServer.cs b/src/modules/MouseWithoutBorders/App/Class/TcpServer.cs index f915ae94e0..cc98381483 100644 --- a/src/modules/MouseWithoutBorders/App/Class/TcpServer.cs +++ b/src/modules/MouseWithoutBorders/App/Class/TcpServer.cs @@ -70,7 +70,7 @@ namespace MouseWithoutBorders.Class continue; } - if (!Common.IsMyDesktopActive()) + if (!WinAPI.IsMyDesktopActive()) { // We can just throw the SocketException but to avoid a redundant log entry: throw new ExpectedSocketException($"{nameof(StartServer)}: The desktop is no longer active."); diff --git a/src/modules/MouseWithoutBorders/App/Core/Clipboard.cs b/src/modules/MouseWithoutBorders/App/Core/Clipboard.cs index 5840325941..e557ff4a37 100644 --- a/src/modules/MouseWithoutBorders/App/Core/Clipboard.cs +++ b/src/modules/MouseWithoutBorders/App/Core/Clipboard.cs @@ -270,15 +270,15 @@ internal static class Clipboard int index = 0; int len; DATA package = new(); - byte[] buf = new byte[Common.PACKAGE_SIZE_EX]; - int dataStart = Common.PACKAGE_SIZE_EX - DATA_SIZE; + byte[] buf = new byte[Package.PACKAGE_SIZE_EX]; + int dataStart = Package.PACKAGE_SIZE_EX - DATA_SIZE; while (true) { if ((index + DATA_SIZE) > l) { len = l - index; - Array.Clear(buf, 0, Common.PACKAGE_SIZE_EX); + Array.Clear(buf, 0, Package.PACKAGE_SIZE_EX); } else { @@ -315,7 +315,7 @@ internal static class Clipboard } MemoryStream m = new(); - int dataStart = Common.PACKAGE_SIZE_EX - DATA_SIZE; + int dataStart = Package.PACKAGE_SIZE_EX - DATA_SIZE; m.Write(data.Bytes, dataStart, DATA_SIZE); int unexpectedCount = 0; @@ -809,27 +809,27 @@ internal static class Clipboard MachineName = Common.MachineName, }; - byte[] buf = new byte[Common.PACKAGE_SIZE_EX]; + byte[] buf = new byte[Package.PACKAGE_SIZE_EX]; NetworkStream ns = new(s); - enStream = Common.GetEncryptedStream(ns); + enStream = Encryption.GetEncryptedStream(ns); Common.SendOrReceiveARandomDataBlockPerInitialIV(enStream); Logger.LogDebug($"{nameof(ShakeHand)}: Writing header package."); - enStream.Write(package.Bytes, 0, Common.PACKAGE_SIZE_EX); + enStream.Write(package.Bytes, 0, Package.PACKAGE_SIZE_EX); Logger.LogDebug($"{nameof(ShakeHand)}: Sent: clientPush={clientPushData}, postAction={postAction}."); - deStream = Common.GetDecryptedStream(ns); + deStream = Encryption.GetDecryptedStream(ns); Common.SendOrReceiveARandomDataBlockPerInitialIV(deStream, false); Logger.LogDebug($"{nameof(ShakeHand)}: Reading header package."); - int bytesReceived = deStream.ReadEx(buf, 0, Common.PACKAGE_SIZE_EX); + int bytesReceived = deStream.ReadEx(buf, 0, Package.PACKAGE_SIZE_EX); package.Bytes = buf; string name = "Unknown"; - if (bytesReceived == Common.PACKAGE_SIZE_EX) + if (bytesReceived == Package.PACKAGE_SIZE_EX) { if (package.Type is PackageType.Clipboard or PackageType.ClipboardPush) { diff --git a/src/modules/MouseWithoutBorders/App/Core/ClipboardPostAction.cs b/src/modules/MouseWithoutBorders/App/Core/ClipboardPostAction.cs new file mode 100644 index 0000000000..c07a8bb91a --- /dev/null +++ b/src/modules/MouseWithoutBorders/App/Core/ClipboardPostAction.cs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; + +// +// Package format/conversion. +// +// +// 2008 created by Truong Do (ductdo). +// 2009-... modified by Truong Do (TruongDo). +// 2023- Included in PowerToys. +// +namespace MouseWithoutBorders.Core; + +internal enum ClipboardPostAction : uint +{ + Other = 0, + Desktop = 1, + Mspaint = 2, +} diff --git a/src/modules/MouseWithoutBorders/App/Core/DATA.cs b/src/modules/MouseWithoutBorders/App/Core/DATA.cs new file mode 100644 index 0000000000..4085483bd9 --- /dev/null +++ b/src/modules/MouseWithoutBorders/App/Core/DATA.cs @@ -0,0 +1,150 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; + +// In X64, we are WOW +[module: SuppressMessage("Microsoft.Portability", "CA1900:ValueTypeFieldsShouldBePortable", Scope = "type", Target = "MouseWithoutBorders.Core.DATA", Justification = "Dotnet port with style preservation")] + +// +// Package format/conversion. +// +// +// 2008 created by Truong Do (ductdo). +// 2009-... modified by Truong Do (TruongDo). +// 2023- Included in PowerToys. +// +namespace MouseWithoutBorders.Core; + +// The beauty of "union" in C# +[StructLayout(LayoutKind.Explicit)] +internal sealed class DATA +{ + [FieldOffset(0)] + internal PackageType Type; // 4 (first byte = package type, 1 = checksum, 2+3 = magic no.) + + [FieldOffset(sizeof(PackageType))] + internal int Id; // 4 + + [FieldOffset(sizeof(PackageType) + sizeof(uint))] + internal ID Src; // 4 + + [FieldOffset(sizeof(PackageType) + (2 * sizeof(uint)))] + internal ID Des; // 4 + + [FieldOffset(sizeof(PackageType) + (3 * sizeof(uint)))] + internal long DateTime; + + [FieldOffset(sizeof(PackageType) + (3 * sizeof(uint)) + sizeof(long))] + internal KEYBDDATA Kd; + + [FieldOffset(sizeof(PackageType) + (3 * sizeof(uint)))] + internal MOUSEDATA Md; + + [FieldOffset(sizeof(PackageType) + (3 * sizeof(uint)))] + internal ID Machine1; + + [FieldOffset(sizeof(PackageType) + (4 * sizeof(uint)))] + internal ID Machine2; + + [FieldOffset(sizeof(PackageType) + (5 * sizeof(uint)))] + internal ID Machine3; + + [FieldOffset(sizeof(PackageType) + (6 * sizeof(uint)))] + internal ID Machine4; + + [FieldOffset(sizeof(PackageType) + (3 * sizeof(uint)))] + internal ClipboardPostAction PostAction; + + [FieldOffset(sizeof(PackageType) + (7 * sizeof(uint)))] + private long machineNameP1; + + [FieldOffset(sizeof(PackageType) + (7 * sizeof(uint)) + sizeof(long))] + private long machineNameP2; + + [FieldOffset(sizeof(PackageType) + (7 * sizeof(uint)) + (2 * sizeof(long)))] + private long machineNameP3; + + [FieldOffset(sizeof(PackageType) + (7 * sizeof(uint)) + (3 * sizeof(long)))] + private long machineNameP4; + + internal string MachineName + { + get + { + string name = Common.GetString(BitConverter.GetBytes(machineNameP1)) + + Common.GetString(BitConverter.GetBytes(machineNameP2)) + + Common.GetString(BitConverter.GetBytes(machineNameP3)) + + Common.GetString(BitConverter.GetBytes(machineNameP4)); + return name.Trim(); + } + + set + { + byte[] machineName = Common.GetBytes(value.PadRight(32, ' ')); + machineNameP1 = BitConverter.ToInt64(machineName, 0); + machineNameP2 = BitConverter.ToInt64(machineName, 8); + machineNameP3 = BitConverter.ToInt64(machineName, 16); + machineNameP4 = BitConverter.ToInt64(machineName, 24); + } + } + + public DATA() + { + } + + public DATA(byte[] initialData) + { + Bytes = initialData; + } + + internal byte[] Bytes + { + get + { + byte[] buf = new byte[IsBigPackage ? Package.PACKAGE_SIZE_EX : Package.PACKAGE_SIZE]; + Array.Copy(StructToBytes(this), buf, IsBigPackage ? Package.PACKAGE_SIZE_EX : Package.PACKAGE_SIZE); + + return buf; + } + + set + { + Debug.Assert(value.Length <= Package.PACKAGE_SIZE_EX, "Length > package size"); + byte[] buf = new byte[Package.PACKAGE_SIZE_EX]; + Array.Copy(value, buf, value.Length); + BytesToStruct(buf, this); + } + } + + internal bool IsBigPackage + { + get => Type == 0 + ? throw new InvalidOperationException("Package type not set.") + : Type switch + { + PackageType.Hello or PackageType.Awake or PackageType.Heartbeat or PackageType.Heartbeat_ex or PackageType.Handshake or PackageType.HandshakeAck or PackageType.ClipboardPush or PackageType.Clipboard or PackageType.ClipboardAsk or PackageType.ClipboardImage or PackageType.ClipboardText or PackageType.ClipboardDataEnd => true, + _ => (Type & PackageType.Matrix) == PackageType.Matrix, + }; + } + + private byte[] StructToBytes(object structObject) + { + byte[] bytes = new byte[Package.PACKAGE_SIZE_EX]; + GCHandle bHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned); + Marshal.StructureToPtr(structObject, Marshal.UnsafeAddrOfPinnedArrayElement(bytes, 0), false); + bHandle.Free(); + return bytes; + } + + private void BytesToStruct(byte[] value, object structObject) + { + GCHandle bHandle = GCHandle.Alloc(value, GCHandleType.Pinned); + Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(value, 0), structObject); + bHandle.Free(); + } +} diff --git a/src/modules/MouseWithoutBorders/App/Core/DragDrop.cs b/src/modules/MouseWithoutBorders/App/Core/DragDrop.cs index 2decb83261..d262e48f24 100644 --- a/src/modules/MouseWithoutBorders/App/Core/DragDrop.cs +++ b/src/modules/MouseWithoutBorders/App/Core/DragDrop.cs @@ -67,20 +67,20 @@ internal static class DragDrop return; } - if (wParam == Common.WM_LBUTTONDOWN) + if (wParam == WM.WM_LBUTTONDOWN) { MouseDown = true; DragMachine = MachineStuff.desMachineID; MachineStuff.dropMachineID = ID.NONE; Logger.LogDebug("DragDropStep01: MouseDown"); } - else if (wParam == Common.WM_LBUTTONUP) + else if (wParam == WM.WM_LBUTTONUP) { MouseDown = false; Logger.LogDebug("DragDropStep01: MouseUp"); } - if (wParam == Common.WM_RBUTTONUP && IsDropping) + if (wParam == WM.WM_RBUTTONUP && IsDropping) { IsDropping = false; Clipboard.LastIDWithClipboardData = ID.NONE; @@ -252,7 +252,7 @@ internal static class DragDrop internal static void DragDropStep09(int wParam) { - if (wParam == Common.WM_MOUSEMOVE && IsDropping) + if (wParam == WM.WM_MOUSEMOVE && IsDropping) { // Show/Move form Common.DoSomethingInUIThread(() => @@ -260,7 +260,7 @@ internal static class DragDrop _ = NativeMethods.PostMessage(Common.MainForm.Handle, NativeMethods.WM_SHOW_DRAG_DROP, (IntPtr)0, (IntPtr)0); }); } - else if (wParam == Common.WM_LBUTTONUP && (IsDropping || IsDragging)) + else if (wParam == WM.WM_LBUTTONUP && (IsDropping || IsDragging)) { if (IsDropping) { diff --git a/src/modules/MouseWithoutBorders/App/Core/Encryption.cs b/src/modules/MouseWithoutBorders/App/Core/Encryption.cs new file mode 100644 index 0000000000..9d00b6bb40 --- /dev/null +++ b/src/modules/MouseWithoutBorders/App/Core/Encryption.cs @@ -0,0 +1,245 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Concurrent; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Threading.Tasks; + +// +// Encrypt/decrypt implementation. +// +// +// 2008 created by Truong Do (ductdo). +// 2009-... modified by Truong Do (TruongDo). +// 2023- Included in PowerToys. +// +namespace MouseWithoutBorders.Core; + +internal static class Encryption +{ +#pragma warning disable SYSLIB0021 + private static AesCryptoServiceProvider symAl; +#pragma warning restore SYSLIB0021 +#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter + internal static string myKey; +#pragma warning restore SA1307 + private static uint magicNumber; + private static Random ran = new(); // Used for non encryption related functionality. + internal const int SymAlBlockSize = 16; + + /// + /// This is used for the first encryption block, the following blocks will be combined with the cipher text of the previous block. + /// Thus identical blocks in the socket stream would be encrypted to different cipher text blocks. + /// The first block is a handshake one containing random data. + /// Related Unit Test: TestEncryptDecrypt + /// + private static readonly string InitialIV = ulong.MaxValue.ToString(CultureInfo.InvariantCulture); + + internal static Random Ran + { + get => Encryption.ran ??= new Random(); + set => Encryption.ran = value; + } + + internal static uint MagicNumber + { + get => Encryption.magicNumber; + set => Encryption.magicNumber = value; + } + + internal static string MyKey + { + get => Encryption.myKey; + + set + { + if (Encryption.myKey != value) + { + Encryption.myKey = value; + _ = Task.Factory.StartNew( + () => Encryption.GenLegalKey(), + System.Threading.CancellationToken.None, + TaskCreationOptions.None, + TaskScheduler.Default); // Cache the key to improve UX. + } + } + } + + private static string KeyDisplayedText(string key) + { + string displayedValue = string.Empty; + int i = 0; + + do + { + int length = Math.Min(4, key.Length - i); + displayedValue += string.Concat(key.AsSpan(i, length), " "); + i += 4; + } + while (i < key.Length - 1); + + return displayedValue.Trim(); + } + + internal static bool GeneratedKey { get; set; } + + internal static bool KeyCorrupted { get; set; } + + internal static void InitEncryption() + { + try + { + if (symAl == null) + { +#pragma warning disable SYSLIB0021 // No proper replacement for now + symAl = new AesCryptoServiceProvider(); +#pragma warning restore SYSLIB0021 + symAl.KeySize = 256; + symAl.BlockSize = SymAlBlockSize * 8; + symAl.Padding = PaddingMode.Zeros; + symAl.Mode = CipherMode.CBC; + symAl.GenerateIV(); + } + } + catch (Exception e) + { + Logger.Log(e); + } + } + + private static readonly ConcurrentDictionary LegalKeyDictionary = new(StringComparer.OrdinalIgnoreCase); + + private static byte[] GenLegalKey() + { + byte[] rv; + string myKey = Encryption.MyKey; + + if (!LegalKeyDictionary.TryGetValue(myKey, out byte[] value)) + { + Rfc2898DeriveBytes key = new( + myKey, + Common.GetBytesU(InitialIV), + 50000, + HashAlgorithmName.SHA512); + rv = key.GetBytes(32); + _ = LegalKeyDictionary.AddOrUpdate(myKey, rv, (k, v) => rv); + } + else + { + rv = value; + } + + return rv; + } + + private static byte[] GenLegalIV() + { + string st = InitialIV; + int ivLength = symAl.IV.Length; + if (st.Length > ivLength) + { + st = st[..ivLength]; + } + else if (st.Length < ivLength) + { + st = st.PadRight(ivLength, ' '); + } + + return Common.GetBytes(st); + } + + internal static Stream GetEncryptedStream(Stream encryptedStream) + { + ICryptoTransform encryptor; + encryptor = symAl.CreateEncryptor(GenLegalKey(), GenLegalIV()); + return new CryptoStream(encryptedStream, encryptor, CryptoStreamMode.Write); + } + + internal static Stream GetDecryptedStream(Stream encryptedStream) + { + ICryptoTransform decryptor; + decryptor = symAl.CreateDecryptor(GenLegalKey(), GenLegalIV()); + return new CryptoStream(encryptedStream, decryptor, CryptoStreamMode.Read); + } + + internal static uint Get24BitHash(string st) + { + if (string.IsNullOrEmpty(st)) + { + return 0; + } + + byte[] bytes = new byte[Package.PACKAGE_SIZE]; + for (int i = 0; i < Package.PACKAGE_SIZE; i++) + { + if (i < st.Length) + { + bytes[i] = (byte)st[i]; + } + } + + var hash = SHA512.Create(); + byte[] hashValue = hash.ComputeHash(bytes); + + for (int i = 0; i < 50000; i++) + { + hashValue = hash.ComputeHash(hashValue); + } + + Logger.LogDebug(string.Format(CultureInfo.CurrentCulture, "magic: {0},{1},{2}", hashValue[0], hashValue[1], hashValue[^1])); + hash.Clear(); + 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(); + } + + private const int PW_LENGTH = 16; + + internal static string CreateRandomKey() + { + // Not including characters like "'`O0& since they are confusing to users. + string[] chars = new[] { "abcdefghjkmnpqrstuvxyz", "ABCDEFGHJKMNPQRSTUVXYZ", "123456789", "~!@#$%^*()_-+=:;<,>.?/\\|[]" }; + char[][] charactersUsedForKey = chars.Select(charset => Enumerable.Range(0, charset.Length - 1).Select(i => charset[i]).ToArray()).ToArray(); + byte[] randomData = new byte[1]; + string key = string.Empty; + + do + { + foreach (string set in chars) + { + randomData = RandomNumberGenerator.GetBytes(1); + key += set[randomData[0] % set.Length]; + + if (key.Length >= PW_LENGTH) + { + break; + } + } + } + while (key.Length < PW_LENGTH); + + return key; + } + + internal static bool IsKeyValid(string key, out string error) + { + error = string.IsNullOrEmpty(key) || key.Length < 16 + ? "Key must have at least 16 characters in length (spaces are discarded). Key must be auto generated in one of the machines." + : null; + + return error == null; + } +} diff --git a/src/modules/MouseWithoutBorders/App/Core/Event.cs b/src/modules/MouseWithoutBorders/App/Core/Event.cs index 1e6ee3e371..659a15526e 100644 --- a/src/modules/MouseWithoutBorders/App/Core/Event.cs +++ b/src/modules/MouseWithoutBorders/App/Core/Event.cs @@ -70,7 +70,7 @@ internal static class Event // Check if easy mouse setting is enabled. bool isEasyMouseEnabled = IsSwitchingByMouseEnabled(); - if (isEasyMouseEnabled && Common.Sk != null && (Common.DesMachineID == Common.MachineID || !Setting.Values.MoveMouseRelatively) && e.dwFlags == Common.WM_MOUSEMOVE) + if (isEasyMouseEnabled && Common.Sk != null && (Common.DesMachineID == Common.MachineID || !Setting.Values.MoveMouseRelatively) && e.dwFlags == WM.WM_MOUSEMOVE) { Point p = MachineStuff.MoveToMyNeighbourIfNeeded(e.X, e.Y, MachineStuff.desMachineID); @@ -115,7 +115,7 @@ internal static class Event Common.SkSend(MousePackage, null, false); - if (MousePackage.Md.dwFlags is Common.WM_LBUTTONUP or Common.WM_RBUTTONUP) + if (MousePackage.Md.dwFlags is WM.WM_LBUTTONUP or WM.WM_RBUTTONUP) { Thread.Sleep(10); } @@ -265,7 +265,7 @@ internal static class Event KeybdPackage.Kd = e; KeybdPackage.DateTime = Common.GetTick(); Common.SkSend(KeybdPackage, null, false); - if (KeybdPackage.Kd.dwFlags is Common.WM_KEYUP or Common.WM_SYSKEYUP) + if (KeybdPackage.Kd.dwFlags is WM.WM_KEYUP or WM.WM_SYSKEYUP) { Thread.Sleep(10); } diff --git a/src/modules/MouseWithoutBorders/App/Core/Helper.cs b/src/modules/MouseWithoutBorders/App/Core/Helper.cs index bd66c9a83f..8c291fb417 100644 --- a/src/modules/MouseWithoutBorders/App/Core/Helper.cs +++ b/src/modules/MouseWithoutBorders/App/Core/Helper.cs @@ -290,7 +290,7 @@ internal static class Helper return; } - if (!Common.IsMyDesktopActive()) + if (!WinAPI.IsMyDesktopActive()) { return; } @@ -314,7 +314,7 @@ internal static class Helper _ = Launch.CreateProcessInInputDesktopSession( $"\"{Path.GetDirectoryName(Application.ExecutablePath)}\\{HelperProcessName}.exe\"", string.Empty, - Common.GetInputDesktop(), + WinAPI.GetInputDesktop(), 0); Clipboard.HasSwitchedMachineSinceLastCopy = true; @@ -379,7 +379,7 @@ internal static class Helper log += "=============================================================================================================================\r\n"; log += $"{Application.ProductName} version {Application.ProductVersion}\r\n"; - log += $"{Setting.Values.Username}/{Common.GetDebugInfo(Common.MyKey)}\r\n"; + log += $"{Setting.Values.Username}/{Encryption.GetDebugInfo(Encryption.MyKey)}\r\n"; log += $"{Common.MachineName}/{Common.MachineID}/{Common.DesMachineID}\r\n"; log += $"Id: {Setting.Values.DeviceId}\r\n"; log += $"Matrix: {string.Join(",", MachineStuff.MachineMatrix)}\r\n"; diff --git a/src/modules/MouseWithoutBorders/App/Core/ID.cs b/src/modules/MouseWithoutBorders/App/Core/ID.cs new file mode 100644 index 0000000000..11dfcc22c8 --- /dev/null +++ b/src/modules/MouseWithoutBorders/App/Core/ID.cs @@ -0,0 +1,19 @@ +// 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. + +// +// Package format/conversion. +// +// +// 2008 created by Truong Do (ductdo). +// 2009-... modified by Truong Do (TruongDo). +// 2023- Included in PowerToys. +// +namespace MouseWithoutBorders.Core; + +internal enum ID : uint +{ + NONE = 0, + ALL = 255, +} diff --git a/src/modules/MouseWithoutBorders/App/Core/InitAndCleanup.cs b/src/modules/MouseWithoutBorders/App/Core/InitAndCleanup.cs index 963775cbca..510671ee95 100644 --- a/src/modules/MouseWithoutBorders/App/Core/InitAndCleanup.cs +++ b/src/modules/MouseWithoutBorders/App/Core/InitAndCleanup.cs @@ -89,23 +89,23 @@ internal static class InitAndCleanup internal static void Init() { _ = Helper.GetUserName(); - Common.GeneratedKey = true; + Encryption.GeneratedKey = true; try { - Common.MyKey = Setting.Values.MyKey; + Encryption.MyKey = Setting.Values.MyKey; int tmp = Setting.Values.MyKeyDaysToExpire; } catch (FormatException e) { - Common.KeyCorrupted = true; - Setting.Values.MyKey = Common.MyKey = Common.CreateRandomKey(); + Encryption.KeyCorrupted = true; + Setting.Values.MyKey = Encryption.MyKey = Encryption.CreateRandomKey(); Logger.Log(e.Message); } catch (CryptographicException e) { - Common.KeyCorrupted = true; - Setting.Values.MyKey = Common.MyKey = Common.CreateRandomKey(); + Encryption.KeyCorrupted = true; + Setting.Values.MyKey = Encryption.MyKey = Encryption.CreateRandomKey(); Logger.Log(e.Message); } @@ -127,14 +127,14 @@ internal static class InitAndCleanup bool dummy = Setting.Values.DrawMouseEx; Common.Is64bitOS = IntPtr.Size == 8; Common.tcpPort = Setting.Values.TcpPort; - Common.GetScreenConfig(); - Common.PackageSent = new PackageMonitor(0); - Common.PackageReceived = new PackageMonitor(0); + WinAPI.GetScreenConfig(); + Package.PackageSent = new PackageMonitor(0); + Package.PackageReceived = new PackageMonitor(0); SetupMachineNameAndID(); - Common.InitEncryption(); + Encryption.InitEncryption(); CreateHelperThreads(); - SystemEvents.DisplaySettingsChanged += new EventHandler(Common.SystemEvents_DisplaySettingsChanged); + SystemEvents.DisplaySettingsChanged += new EventHandler(WinAPI.SystemEvents_DisplaySettingsChanged); NetworkChange.NetworkAvailabilityChanged += new NetworkAvailabilityChangedEventHandler(NetworkChange_NetworkAvailabilityChanged); SystemEvents.PowerModeChanged += new PowerModeChangedEventHandler(SystemEvents_PowerModeChanged); PleaseReopenSocket = 9; @@ -220,7 +220,7 @@ internal static class InitAndCleanup lastReleaseAllKeysCall = Common.GetTick(); KEYBDDATA kd; - kd.dwFlags = (int)Common.LLKHF.UP; + kd.dwFlags = (int)WM.LLKHF.UP; VK[] keys = new VK[] { @@ -266,7 +266,7 @@ internal static class InitAndCleanup true); } - if (!Common.IsMyDesktopActive()) + if (!WinAPI.IsMyDesktopActive()) { PleaseReopenSocket = 0; } diff --git a/src/modules/MouseWithoutBorders/App/Core/KEYBDDATA.cs b/src/modules/MouseWithoutBorders/App/Core/KEYBDDATA.cs new file mode 100644 index 0000000000..244c069c98 --- /dev/null +++ b/src/modules/MouseWithoutBorders/App/Core/KEYBDDATA.cs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; + +// +// Package format/conversion. +// +// +// 2008 created by Truong Do (ductdo). +// 2009-... modified by Truong Do (TruongDo). +// 2023- Included in PowerToys. +// +namespace MouseWithoutBorders.Core; + +[StructLayout(LayoutKind.Sequential)] +internal struct KEYBDDATA +{ + [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Same name as in winAPI")] + internal int wVk; + [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Same name as in winAPI")] + internal int dwFlags; +} diff --git a/src/modules/MouseWithoutBorders/App/Core/Logger.cs b/src/modules/MouseWithoutBorders/App/Core/Logger.cs index 86ce7605b5..4d39983c35 100644 --- a/src/modules/MouseWithoutBorders/App/Core/Logger.cs +++ b/src/modules/MouseWithoutBorders/App/Core/Logger.cs @@ -121,52 +121,52 @@ internal static class Logger { string log; - if (!lastPackageSent.Equals(Common.PackageSent)) + if (!lastPackageSent.Equals(Package.PackageSent)) { log = string.Format( CultureInfo.CurrentCulture, "SENT:" + HeaderSENT, - Common.PackageSent.Heartbeat, - Common.PackageSent.Keyboard, - Common.PackageSent.Mouse, - Common.PackageSent.Hello, - Common.PackageSent.Matrix, - Common.PackageSent.ClipboardText, - Common.PackageSent.ClipboardImage, - Common.PackageSent.ByeBye, - Common.PackageSent.Clipboard, - Common.PackageSent.ClipboardDragDrop, - Common.PackageSent.ClipboardDragDropEnd, - Common.PackageSent.ExplorerDragDrop, + Package.PackageSent.Heartbeat, + Package.PackageSent.Keyboard, + Package.PackageSent.Mouse, + Package.PackageSent.Hello, + Package.PackageSent.Matrix, + Package.PackageSent.ClipboardText, + Package.PackageSent.ClipboardImage, + Package.PackageSent.ByeBye, + Package.PackageSent.Clipboard, + Package.PackageSent.ClipboardDragDrop, + Package.PackageSent.ClipboardDragDropEnd, + Package.PackageSent.ExplorerDragDrop, Event.inputEventCount, - Common.PackageSent.Nil); + Package.PackageSent.Nil); Log(log); - lastPackageSent = Common.PackageSent; // Copy data + lastPackageSent = Package.PackageSent; // Copy data } - if (!lastPackageReceived.Equals(Common.PackageReceived)) + if (!lastPackageReceived.Equals(Package.PackageReceived)) { log = string.Format( CultureInfo.CurrentCulture, "RECEIVED:" + HeaderRECEIVED, - Common.PackageReceived.Heartbeat, - Common.PackageReceived.Keyboard, - Common.PackageReceived.Mouse, - Common.PackageReceived.Hello, - Common.PackageReceived.Matrix, - Common.PackageReceived.ClipboardText, - Common.PackageReceived.ClipboardImage, - Common.PackageReceived.ByeBye, - Common.PackageReceived.Clipboard, - Common.PackageReceived.ClipboardDragDrop, - Common.PackageReceived.ClipboardDragDropEnd, - Common.PackageReceived.ExplorerDragDrop, + Package.PackageReceived.Heartbeat, + Package.PackageReceived.Keyboard, + Package.PackageReceived.Mouse, + Package.PackageReceived.Hello, + Package.PackageReceived.Matrix, + Package.PackageReceived.ClipboardText, + Package.PackageReceived.ClipboardImage, + Package.PackageReceived.ByeBye, + Package.PackageReceived.Clipboard, + Package.PackageReceived.ClipboardDragDrop, + Package.PackageReceived.ClipboardDragDropEnd, + Package.PackageReceived.ExplorerDragDrop, Event.invalidPackageCount, - Common.PackageReceived.Nil, + Package.PackageReceived.Nil, Receiver.processedPackageCount, Receiver.skippedPackageCount); Log(log); - lastPackageReceived = Common.PackageReceived; + lastPackageReceived = Package.PackageReceived; } } @@ -209,9 +209,9 @@ internal static class Logger "Private Mem: " + (Process.GetCurrentProcess().PrivateMemorySize64 / 1024).ToString(CultureInfo.CurrentCulture) + "KB", sb.ToString()); - if (!string.IsNullOrEmpty(Common.myKey)) + if (!string.IsNullOrEmpty(Encryption.myKey)) { - log = log.Replace(Common.MyKey, Common.GetDebugInfo(Common.MyKey)); + log = log.Replace(Encryption.MyKey, Encryption.GetDebugInfo(Encryption.MyKey)); } log += Thread.DumpThreadsStack(); @@ -251,14 +251,18 @@ internal static class Logger { typeof(Clipboard), typeof(DragDrop), + typeof(Encryption), typeof(Event), typeof(InitAndCleanup), typeof(Helper), typeof(Launch), typeof(Logger), typeof(MachineStuff), + typeof(Package), typeof(Receiver), typeof(Service), + typeof(WinAPI), + typeof(WM), }; foreach (var staticType in staticTypes) { @@ -294,7 +298,7 @@ internal static class Logger // strArr[3] = t.FullName; strArr[4] = " = "; strArr[5] = objName.Equals("myKey", StringComparison.OrdinalIgnoreCase) - ? Common.GetDebugInfo(objString) + ? Encryption.GetDebugInfo(objString) : objName.Equals("lastClipboardObject", StringComparison.OrdinalIgnoreCase) ? string.Empty : objString diff --git a/src/modules/MouseWithoutBorders/App/Core/MOUSEDATA.cs b/src/modules/MouseWithoutBorders/App/Core/MOUSEDATA.cs new file mode 100644 index 0000000000..8f8e0f4267 --- /dev/null +++ b/src/modules/MouseWithoutBorders/App/Core/MOUSEDATA.cs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; + +// +// Package format/conversion. +// +// +// 2008 created by Truong Do (ductdo). +// 2009-... modified by Truong Do (TruongDo). +// 2023- Included in PowerToys. +// +namespace MouseWithoutBorders.Core; + +[StructLayout(LayoutKind.Sequential)] +internal struct MOUSEDATA +{ + internal int X; + internal int Y; + internal int WheelDelta; + [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Same name as in winAPI")] + internal int dwFlags; +} diff --git a/src/modules/MouseWithoutBorders/App/Core/MachineStuff.cs b/src/modules/MouseWithoutBorders/App/Core/MachineStuff.cs index e5263aa788..add9a03b04 100644 --- a/src/modules/MouseWithoutBorders/App/Core/MachineStuff.cs +++ b/src/modules/MouseWithoutBorders/App/Core/MachineStuff.cs @@ -221,9 +221,9 @@ internal static class MachineStuff if (Setting.Values.BlockMouseAtCorners) { - lock (Common.SensitivePoints) + lock (WinAPI.SensitivePoints) { - foreach (Point p in Common.SensitivePoints) + foreach (Point p in WinAPI.SensitivePoints) { if (Math.Abs(p.X - x) < 100 && Math.Abs(p.Y - y) < 100) { @@ -793,8 +793,8 @@ internal static class MachineStuff internal static void ShowSetupForm(bool reopenSockets = false) { Logger.LogDebug("========== BEGIN THE SETUP EXPERIENCE ==========", true); - Setting.Values.MyKey = Common.MyKey = Common.CreateRandomKey(); - Common.GeneratedKey = true; + Setting.Values.MyKey = Encryption.MyKey = Encryption.CreateRandomKey(); + Encryption.GeneratedKey = true; if (Process.GetCurrentProcess().SessionId != NativeMethods.WTSGetActiveConsoleSessionId()) { @@ -1067,7 +1067,7 @@ internal static class MachineStuff internal static void AssertOneInstancePerDesktopSession() { - string eventName = $"Global\\{Application.ProductName}-{FrmAbout.AssemblyVersion}-{Common.GetMyDesktop()}-{Common.CurrentProcess.SessionId}"; + string eventName = $"Global\\{Application.ProductName}-{FrmAbout.AssemblyVersion}-{WinAPI.GetMyDesktop()}-{Common.CurrentProcess.SessionId}"; oneInstanceCheck = new EventWaitHandle(false, EventResetMode.ManualReset, eventName, out bool created); if (!created) diff --git a/src/modules/MouseWithoutBorders/App/Core/Package.cs b/src/modules/MouseWithoutBorders/App/Core/Package.cs new file mode 100644 index 0000000000..54b5e3e467 --- /dev/null +++ b/src/modules/MouseWithoutBorders/App/Core/Package.cs @@ -0,0 +1,23 @@ +// 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. + +// +// Package format/conversion. +// +// +// 2008 created by Truong Do (ductdo). +// 2009-... modified by Truong Do (TruongDo). +// 2023- Included in PowerToys. +// +namespace MouseWithoutBorders.Core; + +internal static class Package +{ + internal const byte PACKAGE_SIZE = 32; + internal const byte PACKAGE_SIZE_EX = 64; + private const byte WP_PACKAGE_SIZE = 6; + internal static PackageMonitor PackageSent; + internal static PackageMonitor PackageReceived; + internal static int PackageID; +} diff --git a/src/modules/MouseWithoutBorders/App/Core/PackageMonitor.cs b/src/modules/MouseWithoutBorders/App/Core/PackageMonitor.cs new file mode 100644 index 0000000000..e0ccf9ef75 --- /dev/null +++ b/src/modules/MouseWithoutBorders/App/Core/PackageMonitor.cs @@ -0,0 +1,38 @@ +// 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. + +// +// Package format/conversion. +// +// +// 2008 created by Truong Do (ductdo). +// 2009-... modified by Truong Do (TruongDo). +// 2023- Included in PowerToys. +// +namespace MouseWithoutBorders.Core; + +internal struct PackageMonitor +{ + internal ulong Keyboard; + internal ulong Mouse; + internal ulong Heartbeat; + internal ulong ByeBye; + internal ulong Hello; + internal ulong Matrix; + internal ulong ClipboardText; + internal ulong ClipboardImage; + internal ulong Clipboard; + internal ulong ClipboardDragDrop; + internal ulong ClipboardDragDropEnd; + internal ulong ClipboardAsk; + internal ulong ExplorerDragDrop; + internal ulong Nil; + + internal PackageMonitor(ulong value) + { + ClipboardDragDrop = ClipboardDragDropEnd = ExplorerDragDrop = + Keyboard = Mouse = Heartbeat = ByeBye = Hello = Clipboard = + Matrix = ClipboardImage = ClipboardText = Nil = ClipboardAsk = value; + } +} diff --git a/src/modules/MouseWithoutBorders/App/Core/PackageType.cs b/src/modules/MouseWithoutBorders/App/Core/PackageType.cs new file mode 100644 index 0000000000..9b7b48fc12 --- /dev/null +++ b/src/modules/MouseWithoutBorders/App/Core/PackageType.cs @@ -0,0 +1,57 @@ +// 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. + +// +// Package format/conversion. +// +// +// 2008 created by Truong Do (ductdo). +// 2009-... modified by Truong Do (TruongDo). +// 2023- Included in PowerToys. +// +namespace MouseWithoutBorders.Core; + +internal enum PackageType // : int +{ + // Search for PACKAGE_TYPE_RELATED before changing these! + Invalid = 0xFF, + + Error = 0xFE, + + Hi = 2, + Hello = 3, + ByeBye = 4, + + Heartbeat = 20, + Awake = 21, + HideMouse = 50, + Heartbeat_ex = 51, + Heartbeat_ex_l2 = 52, + Heartbeat_ex_l3 = 53, + + Clipboard = 69, + ClipboardDragDrop = 70, + ClipboardDragDropEnd = 71, + ExplorerDragDrop = 72, + ClipboardCapture = 73, + CaptureScreenCommand = 74, + ClipboardDragDropOperation = 75, + ClipboardDataEnd = 76, + MachineSwitched = 77, + ClipboardAsk = 78, + ClipboardPush = 79, + + NextMachine = 121, + Keyboard = 122, + Mouse = 123, + ClipboardText = 124, + ClipboardImage = 125, + + Handshake = 126, + HandshakeAck = 127, + + Matrix = 128, + MatrixSwapFlag = 2, + MatrixTwoRowFlag = 4, +} diff --git a/src/modules/MouseWithoutBorders/App/Core/Receiver.cs b/src/modules/MouseWithoutBorders/App/Core/Receiver.cs index 1b1e0730b0..0a6aaad2ee 100644 --- a/src/modules/MouseWithoutBorders/App/Core/Receiver.cs +++ b/src/modules/MouseWithoutBorders/App/Core/Receiver.cs @@ -93,7 +93,7 @@ internal static class Receiver switch (package.Type) { case PackageType.Keyboard: - Common.PackageReceived.Keyboard++; + Package.PackageReceived.Keyboard++; if (package.Des == Common.MachineID || package.Des == ID.ALL) { JustGotAKey = Common.GetTick(); @@ -102,7 +102,7 @@ internal static class Receiver bool nonElevated = Common.RunWithNoAdminRight && false; if (nonElevated && Setting.Values.OneWayControlMode) { - if ((package.Kd.dwFlags & (int)Common.LLKHF.UP) == (int)Common.LLKHF.UP) + if ((package.Kd.dwFlags & (int)WM.LLKHF.UP) == (int)WM.LLKHF.UP) { Helper.ShowOneWayModeMessage(); } @@ -116,7 +116,7 @@ internal static class Receiver break; case PackageType.Mouse: - Common.PackageReceived.Mouse++; + Package.PackageReceived.Mouse++; if (package.Des == Common.MachineID || package.Des == ID.ALL) { @@ -127,16 +127,16 @@ internal static class Receiver // NOTE(@yuyoyuppe): disabled to drop elevation requirement bool nonElevated = Common.RunWithNoAdminRight && false; - if (nonElevated && Setting.Values.OneWayControlMode && package.Md.dwFlags != Common.WM_MOUSEMOVE) + if (nonElevated && Setting.Values.OneWayControlMode && package.Md.dwFlags != WM.WM_MOUSEMOVE) { if (!DragDrop.IsDropping) { - if (package.Md.dwFlags is Common.WM_LBUTTONDOWN or Common.WM_RBUTTONDOWN) + if (package.Md.dwFlags is WM.WM_LBUTTONDOWN or WM.WM_RBUTTONDOWN) { Helper.ShowOneWayModeMessage(); } } - else if (package.Md.dwFlags is Common.WM_LBUTTONUP or Common.WM_RBUTTONUP) + else if (package.Md.dwFlags is WM.WM_LBUTTONUP or WM.WM_RBUTTONUP) { DragDrop.IsDropping = false; } @@ -146,7 +146,7 @@ internal static class Receiver if (Math.Abs(package.Md.X) >= Event.MOVE_MOUSE_RELATIVE && Math.Abs(package.Md.Y) >= Event.MOVE_MOUSE_RELATIVE) { - if (package.Md.dwFlags == Common.WM_MOUSEMOVE) + if (package.Md.dwFlags == WM.WM_MOUSEMOVE) { InputSimulation.MoveMouseRelative( package.Md.X < 0 ? package.Md.X + Event.MOVE_MOUSE_RELATIVE : package.Md.X - Event.MOVE_MOUSE_RELATIVE, @@ -203,19 +203,19 @@ internal static class Receiver break; case PackageType.ExplorerDragDrop: - Common.PackageReceived.ExplorerDragDrop++; + Package.PackageReceived.ExplorerDragDrop++; DragDrop.DragDropStep03(package); break; case PackageType.Heartbeat: case PackageType.Heartbeat_ex: - Common.PackageReceived.Heartbeat++; + Package.PackageReceived.Heartbeat++; - Common.GeneratedKey = Common.GeneratedKey || package.Type == PackageType.Heartbeat_ex; + Encryption.GeneratedKey = Encryption.GeneratedKey || package.Type == PackageType.Heartbeat_ex; - if (Common.GeneratedKey) + if (Encryption.GeneratedKey) { - Setting.Values.MyKey = Common.MyKey; + Setting.Values.MyKey = Encryption.MyKey; Common.SendPackage(ID.ALL, PackageType.Heartbeat_ex_l2); } @@ -230,26 +230,26 @@ internal static class Receiver break; case PackageType.Heartbeat_ex_l2: - Common.GeneratedKey = true; - Setting.Values.MyKey = Common.MyKey; + Encryption.GeneratedKey = true; + Setting.Values.MyKey = Encryption.MyKey; Common.SendPackage(ID.ALL, PackageType.Heartbeat_ex_l3); break; case PackageType.Heartbeat_ex_l3: - Common.GeneratedKey = true; - Setting.Values.MyKey = Common.MyKey; + Encryption.GeneratedKey = true; + Setting.Values.MyKey = Encryption.MyKey; break; case PackageType.Awake: - Common.PackageReceived.Heartbeat++; + Package.PackageReceived.Heartbeat++; _ = MachineStuff.AddToMachinePool(package); Common.HumanBeingDetected(); break; case PackageType.Hello: - Common.PackageReceived.Hello++; + Package.PackageReceived.Hello++; Common.SendHeartBeat(); string newMachine = MachineStuff.AddToMachinePool(package); if (Setting.Values.MachineMatrixString == null) @@ -262,16 +262,16 @@ internal static class Receiver break; case PackageType.Hi: - Common.PackageReceived.Hello++; + Package.PackageReceived.Hello++; break; case PackageType.ByeBye: - Common.PackageReceived.ByeBye++; + Package.PackageReceived.ByeBye++; Common.ProcessByeByeMessage(package); break; case PackageType.Clipboard: - Common.PackageReceived.Clipboard++; + Package.PackageReceived.Clipboard++; if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop) { Clipboard.clipboardCopiedTime = Common.GetTick(); @@ -291,7 +291,7 @@ internal static class Receiver break; case PackageType.ClipboardCapture: - Common.PackageReceived.Clipboard++; + Package.PackageReceived.Clipboard++; if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop) { if (package.Des == Common.MachineID || package.Des == ID.ALL) @@ -304,7 +304,7 @@ internal static class Receiver break; case PackageType.CaptureScreenCommand: - Common.PackageReceived.Clipboard++; + Package.PackageReceived.Clipboard++; if (package.Des == Common.MachineID || package.Des == ID.ALL) { Common.SendImage(package.Src, Common.CaptureScreen()); @@ -313,7 +313,7 @@ internal static class Receiver break; case PackageType.ClipboardAsk: - Common.PackageReceived.ClipboardAsk++; + Package.PackageReceived.ClipboardAsk++; if (package.Des == Common.MachineID) { @@ -344,17 +344,17 @@ internal static class Receiver break; case PackageType.ClipboardDragDrop: - Common.PackageReceived.ClipboardDragDrop++; + Package.PackageReceived.ClipboardDragDrop++; DragDrop.DragDropStep08(package); break; case PackageType.ClipboardDragDropOperation: - Common.PackageReceived.ClipboardDragDrop++; + Package.PackageReceived.ClipboardDragDrop++; DragDrop.DragDropStep08_2(package); break; case PackageType.ClipboardDragDropEnd: - Common.PackageReceived.ClipboardDragDropEnd++; + Package.PackageReceived.ClipboardDragDropEnd++; DragDrop.DragDropStep12(); break; @@ -363,11 +363,11 @@ internal static class Receiver Clipboard.clipboardCopiedTime = 0; if (package.Type == PackageType.ClipboardImage) { - Common.PackageReceived.ClipboardImage++; + Package.PackageReceived.ClipboardImage++; } else { - Common.PackageReceived.ClipboardText++; + Package.PackageReceived.ClipboardText++; } if (tcp != null) @@ -390,7 +390,7 @@ internal static class Receiver default: if ((package.Type & PackageType.Matrix) == PackageType.Matrix) { - Common.PackageReceived.Matrix++; + Package.PackageReceived.Matrix++; MachineStuff.UpdateMachineMatrix(package); break; } diff --git a/src/modules/MouseWithoutBorders/App/Core/ShutdownWithPowerToys.cs b/src/modules/MouseWithoutBorders/App/Core/ShutdownWithPowerToys.cs new file mode 100644 index 0000000000..a221aa1733 --- /dev/null +++ b/src/modules/MouseWithoutBorders/App/Core/ShutdownWithPowerToys.cs @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +using ManagedCommon; +using Microsoft.PowerToys.Telemetry; + +namespace MouseWithoutBorders.Core; + +internal static class ShutdownWithPowerToys +{ + internal static void WaitForPowerToysRunner(ETWTrace etwTrace) + { + try + { + RunnerHelper.WaitForPowerToysRunnerExitFallback(() => + { + etwTrace?.Dispose(); + Common.MainForm.Quit(true, false); + }); + } + catch (Exception e) + { + Logger.Log(e); + } + } +} diff --git a/src/modules/MouseWithoutBorders/App/Core/VK.cs b/src/modules/MouseWithoutBorders/App/Core/VK.cs new file mode 100644 index 0000000000..239692abed --- /dev/null +++ b/src/modules/MouseWithoutBorders/App/Core/VK.cs @@ -0,0 +1,88 @@ +// 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. + +// +// Virtual key constants. +// +// +// 2008 created by Truong Do (ductdo). +// 2009-... modified by Truong Do (TruongDo). +// 2023- Included in PowerToys. +// +namespace MouseWithoutBorders.Core; + +internal enum VK : ushort +{ + CAPITAL = 0x14, + NUMLOCK = 0x90, + SHIFT = 0x10, + CONTROL = 0x11, + MENU = 0x12, + ESCAPE = 0x1B, + BACK = 0x08, + TAB = 0x09, + RETURN = 0x0D, + PRIOR = 0x21, + NEXT = 0x22, + END = 0x23, + HOME = 0x24, + LEFT = 0x25, + UP = 0x26, + RIGHT = 0x27, + DOWN = 0x28, + SELECT = 0x29, + PRINT = 0x2A, + EXECUTE = 0x2B, + SNAPSHOT = 0x2C, + INSERT = 0x2D, + DELETE = 0x2E, + HELP = 0x2F, + NUMPAD0 = 0x60, + NUMPAD1 = 0x61, + NUMPAD2 = 0x62, + NUMPAD3 = 0x63, + NUMPAD4 = 0x64, + NUMPAD5 = 0x65, + NUMPAD6 = 0x66, + NUMPAD7 = 0x67, + NUMPAD8 = 0x68, + NUMPAD9 = 0x69, + MULTIPLY = 0x6A, + ADD = 0x6B, + SEPARATOR = 0x6C, + SUBTRACT = 0x6D, + DECIMAL = 0x6E, + DIVIDE = 0x6F, + F1 = 0x70, + F2 = 0x71, + F3 = 0x72, + F4 = 0x73, + F5 = 0x74, + F6 = 0x75, + F7 = 0x76, + F8 = 0x77, + F9 = 0x78, + F10 = 0x79, + F11 = 0x7A, + F12 = 0x7B, + OEM_1 = 0xBA, + OEM_PLUS = 0xBB, + OEM_COMMA = 0xBC, + OEM_MINUS = 0xBD, + OEM_PERIOD = 0xBE, + OEM_2 = 0xBF, + OEM_3 = 0xC0, + MEDIA_NEXT_TRACK = 0xB0, + MEDIA_PREV_TRACK = 0xB1, + MEDIA_STOP = 0xB2, + MEDIA_PLAY_PAUSE = 0xB3, + LWIN = 0x5B, + RWIN = 0x5C, + LSHIFT = 0xA0, + RSHIFT = 0xA1, + LCONTROL = 0xA2, + RCONTROL = 0xA3, + LMENU = 0xA4, + RMENU = 0xA5, +} diff --git a/src/modules/MouseWithoutBorders/App/Core/WM.cs b/src/modules/MouseWithoutBorders/App/Core/WM.cs new file mode 100644 index 0000000000..e93897e93b --- /dev/null +++ b/src/modules/MouseWithoutBorders/App/Core/WM.cs @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +// +// Virtual key constants. +// +// +// 2008 created by Truong Do (ductdo). +// 2009-... modified by Truong Do (TruongDo). +// 2023- Included in PowerToys. +// +namespace MouseWithoutBorders.Core; + +internal partial class WM +{ + internal const ushort KEYEVENTF_KEYDOWN = 0x0001; + internal const ushort KEYEVENTF_KEYUP = 0x0002; + + internal const int WH_MOUSE = 7; + internal const int WH_KEYBOARD = 2; + internal const int WH_MOUSE_LL = 14; + internal const int WH_KEYBOARD_LL = 13; + + internal const int WM_MOUSEMOVE = 0x200; + internal const int WM_LBUTTONDOWN = 0x201; + internal const int WM_RBUTTONDOWN = 0x204; + internal const int WM_MBUTTONDOWN = 0x207; + internal const int WM_XBUTTONDOWN = 0x20B; + internal const int WM_LBUTTONUP = 0x202; + internal const int WM_RBUTTONUP = 0x205; + internal const int WM_MBUTTONUP = 0x208; + internal const int WM_XBUTTONUP = 0x20C; + internal const int WM_LBUTTONDBLCLK = 0x203; + internal const int WM_RBUTTONDBLCLK = 0x206; + internal const int WM_MBUTTONDBLCLK = 0x209; + internal const int WM_MOUSEWHEEL = 0x020A; + internal const int WM_MOUSEHWHEEL = 0x020E; + + internal const int WM_KEYDOWN = 0x100; + internal const int WM_KEYUP = 0x101; + internal const int WM_SYSKEYDOWN = 0x104; + internal const int WM_SYSKEYUP = 0x105; + + [Flags] + internal enum LLKHF + { + EXTENDED = 0x01, + INJECTED = 0x10, + ALTDOWN = 0x20, + UP = 0x80, + } +} diff --git a/src/modules/MouseWithoutBorders/App/Core/WinAPI.cs b/src/modules/MouseWithoutBorders/App/Core/WinAPI.cs new file mode 100644 index 0000000000..4d14dcb973 --- /dev/null +++ b/src/modules/MouseWithoutBorders/App/Core/WinAPI.cs @@ -0,0 +1,359 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Globalization; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading; +using System.Windows.Forms; + +using MouseWithoutBorders.Class; + +// +// Screen/Desktop helper functions. +// +// +// 2008 created by Truong Do (ductdo). +// 2009-... modified by Truong Do (TruongDo). +// 2023- Included in PowerToys. +// +namespace MouseWithoutBorders.Core; + +// Desktops, and GetScreenConfig routines +internal static class WinAPI +{ + private static MyRectangle newDesktopBounds; + private static MyRectangle newPrimaryScreenBounds; + private static string activeDesktop; + + private static string ActiveDesktop => WinAPI.activeDesktop; + + internal static void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e) + { + GetScreenConfig(); + } + + internal static readonly List SensitivePoints = new(); + + private static bool MonitorEnumProc(IntPtr hMonitor, IntPtr hdcMonitor, ref NativeMethods.RECT lprcMonitor, IntPtr dwData) + { + // lprcMonitor is wrong!!! => using GetMonitorInfo(...) + // Log(String.Format( CultureInfo.CurrentCulture,"MONITOR: l{0}, t{1}, r{2}, b{3}", lprcMonitor.Left, lprcMonitor.Top, lprcMonitor.Right, lprcMonitor.Bottom)); + NativeMethods.MonitorInfoEx mi = default; + mi.cbSize = Marshal.SizeOf(mi); + _ = NativeMethods.GetMonitorInfo(hMonitor, ref mi); + + try + { + // For logging only + _ = NativeMethods.GetDpiForMonitor(hMonitor, 0, out uint dpiX, out uint dpiY); + Logger.Log(string.Format(CultureInfo.CurrentCulture, "MONITOR: ({0}, {1}, {2}, {3}). DPI: ({4}, {5})", mi.rcMonitor.Left, mi.rcMonitor.Top, mi.rcMonitor.Right, mi.rcMonitor.Bottom, dpiX, dpiY)); + } + catch (DllNotFoundException) + { + Logger.Log("GetDpiForMonitor is unsupported in Windows 7 and lower."); + } + catch (EntryPointNotFoundException) + { + Logger.Log("GetDpiForMonitor is unsupported in Windows 7 and lower."); + } + catch (Exception e) + { + Logger.Log(e); + } + + if (mi.rcMonitor.Left == 0 && mi.rcMonitor.Top == 0 && mi.rcMonitor.Right != 0 && mi.rcMonitor.Bottom != 0) + { + // Primary screen + _ = Interlocked.Exchange(ref Common.screenWidth, mi.rcMonitor.Right - mi.rcMonitor.Left); + _ = Interlocked.Exchange(ref Common.screenHeight, mi.rcMonitor.Bottom - mi.rcMonitor.Top); + + newPrimaryScreenBounds.Left = mi.rcMonitor.Left; + newPrimaryScreenBounds.Top = mi.rcMonitor.Top; + newPrimaryScreenBounds.Right = mi.rcMonitor.Right; + newPrimaryScreenBounds.Bottom = mi.rcMonitor.Bottom; + } + else + { + if (mi.rcMonitor.Left < newDesktopBounds.Left) + { + newDesktopBounds.Left = mi.rcMonitor.Left; + } + + if (mi.rcMonitor.Top < newDesktopBounds.Top) + { + newDesktopBounds.Top = mi.rcMonitor.Top; + } + + if (mi.rcMonitor.Right > newDesktopBounds.Right) + { + newDesktopBounds.Right = mi.rcMonitor.Right; + } + + if (mi.rcMonitor.Bottom > newDesktopBounds.Bottom) + { + newDesktopBounds.Bottom = mi.rcMonitor.Bottom; + } + } + + lock (SensitivePoints) + { + SensitivePoints.Add(new Point(mi.rcMonitor.Left, mi.rcMonitor.Top)); + SensitivePoints.Add(new Point(mi.rcMonitor.Right, mi.rcMonitor.Top)); + SensitivePoints.Add(new Point(mi.rcMonitor.Right, mi.rcMonitor.Bottom)); + SensitivePoints.Add(new Point(mi.rcMonitor.Left, mi.rcMonitor.Bottom)); + } + + return true; + } + + internal static void GetScreenConfig() + { + try + { + Logger.LogDebug("==================== GetScreenConfig started"); + newDesktopBounds = new MyRectangle(); + newPrimaryScreenBounds = new MyRectangle(); + newDesktopBounds.Left = newPrimaryScreenBounds.Left = Screen.PrimaryScreen.Bounds.Left; + newDesktopBounds.Top = newPrimaryScreenBounds.Top = Screen.PrimaryScreen.Bounds.Top; + newDesktopBounds.Right = newPrimaryScreenBounds.Right = Screen.PrimaryScreen.Bounds.Right; + newDesktopBounds.Bottom = newPrimaryScreenBounds.Bottom = Screen.PrimaryScreen.Bounds.Bottom; + + Logger.Log(string.Format( + CultureInfo.CurrentCulture, + "logon = {0} PrimaryScreenBounds = {1},{2},{3},{4} desktopBounds = {5},{6},{7},{8}", + Common.RunOnLogonDesktop, + WinAPI.newPrimaryScreenBounds.Left, + WinAPI.newPrimaryScreenBounds.Top, + WinAPI.newPrimaryScreenBounds.Right, + WinAPI.newPrimaryScreenBounds.Bottom, + WinAPI.newDesktopBounds.Left, + WinAPI.newDesktopBounds.Top, + WinAPI.newDesktopBounds.Right, + WinAPI.newDesktopBounds.Bottom)); + +#if USE_MANAGED_ROUTINES + // Managed routines do not work well when running on secure desktop:( + screenWidth = Screen.PrimaryScreen.Bounds.Width; + screenHeight = Screen.PrimaryScreen.Bounds.Height; + screenCount = Screen.AllScreens.Length; + for (int i = 0; i < Screen.AllScreens.Length; i++) + { + if (Screen.AllScreens[i].Bounds.Left < desktopBounds.Left) desktopBounds.Left = Screen.AllScreens[i].Bounds.Left; + if (Screen.AllScreens[i].Bounds.Top < desktopBounds.Top) desktopBounds.Top = Screen.AllScreens[i].Bounds.Top; + if (Screen.AllScreens[i].Bounds.Right > desktopBounds.Right) desktopBounds.Right = Screen.AllScreens[i].Bounds.Right; + if (Screen.AllScreens[i].Bounds.Bottom > desktopBounds.Bottom) desktopBounds.Bottom = Screen.AllScreens[i].Bounds.Bottom; + } +#else + lock (SensitivePoints) + { + SensitivePoints.Clear(); + } + + NativeMethods.EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, MonitorEnumProc, IntPtr.Zero); + + // 1000 calls to EnumDisplayMonitors cost a dozen of milliseconds +#endif + Interlocked.Exchange(ref MachineStuff.desktopBounds, newDesktopBounds); + Interlocked.Exchange(ref MachineStuff.primaryScreenBounds, newPrimaryScreenBounds); + + Logger.Log(string.Format( + CultureInfo.CurrentCulture, + "logon = {0} PrimaryScreenBounds = {1},{2},{3},{4} desktopBounds = {5},{6},{7},{8}", + Common.RunOnLogonDesktop, + MachineStuff.PrimaryScreenBounds.Left, + MachineStuff.PrimaryScreenBounds.Top, + MachineStuff.PrimaryScreenBounds.Right, + MachineStuff.PrimaryScreenBounds.Bottom, + MachineStuff.DesktopBounds.Left, + MachineStuff.DesktopBounds.Top, + MachineStuff.DesktopBounds.Right, + MachineStuff.DesktopBounds.Bottom)); + + Logger.Log("==================== GetScreenConfig ended"); + } + catch (Exception e) + { + Logger.Log(e); + } + } + +#if USING_SCREEN_SAVER_ROUTINES + [DllImport("user32.dll", CharSet = CharSet.Auto)] + private static extern int PostMessage(IntPtr hWnd, int wMsg, int wParam, int lParam); + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + private static extern IntPtr OpenDesktop(string hDesktop, int Flags, bool Inherit, UInt32 DesiredAccess); + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + private static extern bool CloseDesktop(IntPtr hDesktop); + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + private static extern bool EnumDesktopWindows( IntPtr hDesktop, EnumDesktopWindowsProc callback, IntPtr lParam); + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + private static extern bool IsWindowVisible(IntPtr hWnd); + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + private static extern bool SystemParametersInfo(int uAction, int uParam, ref int pvParam, int flags); + + private delegate bool EnumDesktopWindowsProc(IntPtr hDesktop, IntPtr lParam); + private const int WM_CLOSE = 16; + private const int SPI_GETSCREENSAVERRUNNING = 114; + + internal static bool IsScreenSaverRunning() + { + int isRunning = 0; + SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0,ref isRunning, 0); + return (isRunning != 0); + } + + internal static void CloseScreenSaver() + { + IntPtr hDesktop = OpenDesktop("Screen-saver", 0, false, DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS); + if (hDesktop != IntPtr.Zero) + { + LogDebug("Closing screen saver..."); + EnumDesktopWindows(hDesktop, new EnumDesktopWindowsProc(CloseScreenSaverFunc), IntPtr.Zero); + CloseDesktop(hDesktop); + } + } + + private static bool CloseScreenSaverFunc(IntPtr hWnd, IntPtr lParam) + { + if (IsWindowVisible(hWnd)) + { + LogDebug("Posting WM_CLOSE to " + hWnd.ToString(CultureInfo.InvariantCulture)); + PostMessage(hWnd, WM_CLOSE, 0, 0); + } + return true; + } +#endif + + internal static string GetMyDesktop() + { + byte[] arThreadDesktop = new byte[256]; + IntPtr hD = NativeMethods.GetThreadDesktop(NativeMethods.GetCurrentThreadId()); + if (hD != IntPtr.Zero) + { + _ = NativeMethods.GetUserObjectInformation(hD, NativeMethods.UOI_NAME, arThreadDesktop, arThreadDesktop.Length, out _); + return Common.GetString(arThreadDesktop).Replace("\0", string.Empty); + } + + return string.Empty; + } + + internal static string GetInputDesktop() + { + byte[] arInputDesktop = new byte[256]; + IntPtr hD = NativeMethods.OpenInputDesktop(0, false, NativeMethods.DESKTOP_READOBJECTS); + if (hD != IntPtr.Zero) + { + _ = NativeMethods.GetUserObjectInformation(hD, NativeMethods.UOI_NAME, arInputDesktop, arInputDesktop.Length, out _); + return Common.GetString(arInputDesktop).Replace("\0", string.Empty); + } + + return string.Empty; + } + + private static void StartMMService(string desktopToRunMouseWithoutBordersOn) + { + if (!Common.RunWithNoAdminRight) + { + Logger.LogDebug("*** Starting on active Desktop: " + desktopToRunMouseWithoutBordersOn); + Service.StartMouseWithoutBordersService(desktopToRunMouseWithoutBordersOn); + } + } + + internal static void CheckForDesktopSwitchEvent(bool cleanupIfExit) + { + try + { + if (!IsMyDesktopActive() || Common.CurrentProcess.SessionId != NativeMethods.WTSGetActiveConsoleSessionId()) + { + Helper.RunDDHelper(true); + int waitCount = 20; + + while (NativeMethods.WTSGetActiveConsoleSessionId() == 0xFFFFFFFF && waitCount > 0) + { + waitCount--; + Logger.LogDebug("The session is detached/attached."); + Thread.Sleep(500); + } + + string myDesktop = GetMyDesktop(); + activeDesktop = GetInputDesktop(); + + Logger.LogDebug("*** Active Desktop = " + activeDesktop); + Logger.LogDebug("*** My Desktop = " + myDesktop); + + if (myDesktop.Equals(activeDesktop, StringComparison.OrdinalIgnoreCase)) + { + Logger.LogDebug("*** Active Desktop == My Desktop (TS session)"); + } + + if (!activeDesktop.Equals("winlogon", StringComparison.OrdinalIgnoreCase) && + !activeDesktop.Equals("default", StringComparison.OrdinalIgnoreCase) && + !activeDesktop.Equals("disconnect", StringComparison.OrdinalIgnoreCase)) + { + try + { + StartMMService(activeDesktop); + } + catch (Exception e) + { + Logger.Log($"{nameof(CheckForDesktopSwitchEvent)}: {e}"); + } + } + else + { + if (!myDesktop.Equals(activeDesktop, StringComparison.OrdinalIgnoreCase)) + { + Logger.Log("*** Active Desktop <> My Desktop"); + } + + uint sid = NativeMethods.WTSGetActiveConsoleSessionId(); + + if (Process.GetProcessesByName(Common.BinaryName).Any(p => (uint)p.SessionId == sid)) + { + Logger.Log("Found MouseWithoutBorders on the active session!"); + } + else + { + Logger.Log("MouseWithoutBorders not found on the active session!"); + StartMMService(null); + } + } + + if (!myDesktop.Equals("winlogon", StringComparison.OrdinalIgnoreCase) && + !myDesktop.Equals("default", StringComparison.OrdinalIgnoreCase)) + { + Logger.LogDebug("*** Desktop inactive, exiting: " + myDesktop); + Setting.Values.LastX = Common.JUST_GOT_BACK_FROM_SCREEN_SAVER; + if (cleanupIfExit) + { + InitAndCleanup.Cleanup(); + } + + Process.GetCurrentProcess().KillProcess(); + } + } + } + catch (Exception e) + { + Logger.Log(e); + } + } + + private static Point p; + + internal static bool IsMyDesktopActive() + { + return NativeMethods.GetCursorPos(ref p); + } +} diff --git a/src/modules/MouseWithoutBorders/App/Form/Settings/SettingsFormPage.cs b/src/modules/MouseWithoutBorders/App/Form/Settings/SettingsFormPage.cs index 39574ac8fe..81c04982a9 100644 --- a/src/modules/MouseWithoutBorders/App/Form/Settings/SettingsFormPage.cs +++ b/src/modules/MouseWithoutBorders/App/Form/Settings/SettingsFormPage.cs @@ -42,7 +42,7 @@ namespace MouseWithoutBorders protected string GetSecureKey() { - return Common.MyKey; + return Encryption.MyKey; } private void BackButton_Click(object sender, EventArgs e) diff --git a/src/modules/MouseWithoutBorders/App/Form/Settings/SetupPage2a.cs b/src/modules/MouseWithoutBorders/App/Form/Settings/SetupPage2a.cs index c86df58143..5fcee5dc54 100644 --- a/src/modules/MouseWithoutBorders/App/Form/Settings/SetupPage2a.cs +++ b/src/modules/MouseWithoutBorders/App/Form/Settings/SetupPage2a.cs @@ -89,8 +89,8 @@ namespace MouseWithoutBorders { if (GetSecureKey() != SecurityCodeField.Text) { - Common.MyKey = Regex.Replace(SecurityCodeField.Text, @"\s+", string.Empty); - SecurityCode = Common.MyKey; + Encryption.MyKey = Regex.Replace(SecurityCodeField.Text, @"\s+", string.Empty); + SecurityCode = Encryption.MyKey; } MachineStuff.MachineMatrix = new string[MachineStuff.MAX_MACHINE] { ComputerNameField.Text.Trim().ToUpper(CultureInfo.CurrentCulture), Common.MachineName.Trim(), string.Empty, string.Empty }; diff --git a/src/modules/MouseWithoutBorders/App/Form/frmMatrix.cs b/src/modules/MouseWithoutBorders/App/Form/frmMatrix.cs index 66301c52cb..703ad8ef91 100644 --- a/src/modules/MouseWithoutBorders/App/Form/frmMatrix.cs +++ b/src/modules/MouseWithoutBorders/App/Form/frmMatrix.cs @@ -135,7 +135,7 @@ namespace MouseWithoutBorders internal void UpdateKeyTextBox() { _ = Helper.GetUserName(); - textBoxEnc.Text = Common.MyKey; + textBoxEnc.Text = Encryption.MyKey; } private void InitAll() @@ -505,19 +505,19 @@ namespace MouseWithoutBorders private bool UpdateKey(string newKey) { - if (!Common.IsKeyValid(newKey, out string rv)) + if (!Encryption.IsKeyValid(newKey, out string rv)) { ShowKeyErrorMsg(rv); return false; } - if (!newKey.Equals(Common.MyKey, StringComparison.OrdinalIgnoreCase)) + if (!newKey.Equals(Encryption.MyKey, StringComparison.OrdinalIgnoreCase)) { - Common.MyKey = newKey; - Common.GeneratedKey = false; + Encryption.MyKey = newKey; + Encryption.GeneratedKey = false; } - Common.MagicNumber = Common.Get24BitHash(Common.MyKey); + Encryption.MagicNumber = Encryption.Get24BitHash(Encryption.MyKey); return true; } @@ -1116,10 +1116,10 @@ namespace MouseWithoutBorders if (MessageBox.Show(message, Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes) { - Setting.Values.MyKey = Common.MyKey = Common.CreateRandomKey(); - textBoxEnc.Text = Common.MyKey; + Setting.Values.MyKey = Encryption.MyKey = Encryption.CreateRandomKey(); + textBoxEnc.Text = Encryption.MyKey; checkBoxShowKey.Checked = true; - Common.GeneratedKey = true; + Encryption.GeneratedKey = true; ButtonOK_Click(null, null); Common.ShowToolTip("New security key was generated, update other machines to the same key.", 10000, ToolTipIcon.Info, false); } diff --git a/src/modules/MouseWithoutBorders/App/Form/frmScreen.cs b/src/modules/MouseWithoutBorders/App/Form/frmScreen.cs index 1ab0ce8cc7..ca123ec850 100644 --- a/src/modules/MouseWithoutBorders/App/Form/frmScreen.cs +++ b/src/modules/MouseWithoutBorders/App/Form/frmScreen.cs @@ -318,7 +318,7 @@ namespace MouseWithoutBorders try { - if (!Common.IsMyDesktopActive() || Common.CurrentProcess.SessionId != NativeMethods.WTSGetActiveConsoleSessionId()) + if (!WinAPI.IsMyDesktopActive() || Common.CurrentProcess.SessionId != NativeMethods.WTSGetActiveConsoleSessionId()) { myDesktopNotActive = true; @@ -348,7 +348,7 @@ namespace MouseWithoutBorders Common.Hook?.ResetLastSwitchKeys(); }); - Common.CheckForDesktopSwitchEvent(true); + WinAPI.CheckForDesktopSwitchEvent(true); } } else @@ -369,21 +369,21 @@ namespace MouseWithoutBorders if (myDesktopNotActive) { myDesktopNotActive = false; - Common.MyKey = Setting.Values.MyKey; + Encryption.MyKey = Setting.Values.MyKey; } MachineStuff.UpdateMachinePoolStringSetting(); - if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && (Setting.Values.FirstRun || Common.KeyCorrupted)) + if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && (Setting.Values.FirstRun || Encryption.KeyCorrupted)) { if (!shownSetupFormOneTime) { shownSetupFormOneTime = true; MachineStuff.ShowMachineMatrix(); - if (Common.KeyCorrupted && !Setting.Values.FirstRun) + if (Encryption.KeyCorrupted && !Setting.Values.FirstRun) { - Common.KeyCorrupted = false; + Encryption.KeyCorrupted = false; string msg = "The security key is corrupted for some reason, please re-setup."; MessageBox.Show(msg, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Warning); } @@ -490,9 +490,9 @@ namespace MouseWithoutBorders if (count == 600) { - if (!Common.GeneratedKey) + if (!Encryption.GeneratedKey) { - Common.MyKey = Setting.Values.MyKey; + Encryption.MyKey = Setting.Values.MyKey; if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop) { @@ -505,7 +505,7 @@ namespace MouseWithoutBorders Common.ShowToolTip("The security key must be auto generated in one of the machines.", 10000); } } - else if (!Common.KeyCorrupted && !Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && !Setting.Values.FirstRun && Common.AtLeastOneSocketConnected()) + else if (!Encryption.KeyCorrupted && !Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && !Setting.Values.FirstRun && Common.AtLeastOneSocketConnected()) { int myKeyDaysToExpire = Setting.Values.MyKeyDaysToExpire; @@ -531,7 +531,7 @@ namespace MouseWithoutBorders #if SHOW_ON_WINLOGON // if (Common.RunOnLogonDesktop) ShowMouseWithoutBordersUiOnWinLogonDesktop(false); #endif - Common.CheckForDesktopSwitchEvent(true); + WinAPI.CheckForDesktopSwitchEvent(true); MachineStuff.UpdateClientSockets("helperTimer_Tick"); // Sockets may be closed by the remote host when both machines switch desktop at the same time. } @@ -582,7 +582,7 @@ namespace MouseWithoutBorders int rv = 0; - if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && Common.IsMyDesktopActive() && (rv = Helper.SendMessageToHelper(0x400, IntPtr.Zero, IntPtr.Zero)) <= 0) + if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && WinAPI.IsMyDesktopActive() && (rv = Helper.SendMessageToHelper(0x400, IntPtr.Zero, IntPtr.Zero)) <= 0) { Logger.TelemetryLogTrace($"{Helper.HELPER_FORM_TEXT} not found: {rv}", SeverityLevel.Warning); } diff --git a/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/Logger.PrivateDump.expected.txt b/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/Logger.PrivateDump.expected.txt index 1bbd8ba49c..34a83830cd 100644 --- a/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/Logger.PrivateDump.expected.txt +++ b/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/Logger.PrivateDump.expected.txt @@ -46,79 +46,6 @@ avgSendTime = 0 maxSendTime = 0 totalSendCount = 0 totalSendTime = 0 -magicNumber = 0 -ran = System.Random ---_impl = System.Random+XoshiroImpl -----_s0 = ???????????? -----_s1 = ???????????? -----_s2 = ???????????? -----_s3 = ???????????? ---k__BackingField = System.Random+ThreadSafeRandom -InitialIV = ???????????? -k__BackingField = False -k__BackingField = False -LegalKeyDictionary = Concurrent.ConcurrentDictionary`2[System.String,System.Byte[]] ---_tables = Concurrent.ConcurrentDictionary`2+Tables[System.String,System.Byte[]] -----_comparer = Generic.NonRandomizedStringEqualityComparer+OrdinalIgnoreCaseComparer -----_buckets = Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,System.Byte[]][] -------System.Collections.Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,System.Byte[]][] = Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,System.Byte[]][]: N/A -----_fastModBucketsMultiplier = 498560650640798693 -----_locks = O[] -------System.Object[] = O[]: N/A -----_countPerLock = 32[] -------[0] = 0 -------[1] = 0 -------[2] = 0 -------[3] = 0 -------[4] = 0 -------[5] = 0 -------[6] = 0 -------[7] = 0 ---_budget = ???????????? ---_growLockArray = True ---_comparerIsDefaultForClasses = False -PackageSent = MouseWithoutBorders.PackageMonitor ---Keyboard = 0 ---Mouse = 0 ---Heartbeat = 0 ---ByeBye = 0 ---Hello = 0 ---Matrix = 0 ---ClipboardText = 0 ---ClipboardImage = 0 ---Clipboard = 0 ---ClipboardDragDrop = 0 ---ClipboardDragDropEnd = 0 ---ClipboardAsk = 0 ---ExplorerDragDrop = 0 ---Nil = 0 -PackageReceived = MouseWithoutBorders.PackageMonitor ---Keyboard = 0 ---Mouse = 0 ---Heartbeat = 0 ---ByeBye = 0 ---Hello = 0 ---Matrix = 0 ---ClipboardText = 0 ---ClipboardImage = 0 ---Clipboard = 0 ---ClipboardDragDrop = 0 ---ClipboardDragDropEnd = 0 ---ClipboardAsk = 0 ---ExplorerDragDrop = 0 ---Nil = 0 -PackageID = 0 -SensitivePoints = Generic.List`1[Point] ---_items = Point[] -----System.Drawing.Point[] = Point[]: N/A ---_size = 0 ---_version = 0 ---s_emptyArray = Point[] -----System.Drawing.Point[] = Point[]: N/A -p = {X=0,Y=0} ---x = 0 ---y = 0 ---Empty = {X=0,Y=0} k__BackingField = False TOGGLE_ICONS_SIZE = 4 ICON_ONE = 0 @@ -128,34 +55,6 @@ ICON_BIG_CLIPBOARD = 3 ICON_ERROR = 4 JUST_GOT_BACK_FROM_SCREEN_SAVER = 9999 NETWORK_STREAM_BUF_SIZE = 1048576 -SymAlBlockSize = 16 -PW_LENGTH = 16 -PACKAGE_SIZE = 32 -PACKAGE_SIZE_EX = 64 -WP_PACKAGE_SIZE = 6 -KEYEVENTF_KEYDOWN = 1 -KEYEVENTF_KEYUP = 2 -WH_MOUSE = 7 -WH_KEYBOARD = 2 -WH_MOUSE_LL = 14 -WH_KEYBOARD_LL = 13 -WM_MOUSEMOVE = 512 -WM_LBUTTONDOWN = 513 -WM_RBUTTONDOWN = 516 -WM_MBUTTONDOWN = 519 -WM_XBUTTONDOWN = 523 -WM_LBUTTONUP = 514 -WM_RBUTTONUP = 517 -WM_MBUTTONUP = 520 -WM_XBUTTONUP = 524 -WM_LBUTTONDBLCLK = 515 -WM_RBUTTONDBLCLK = 518 -WM_MBUTTONDBLCLK = 521 -WM_MOUSEWHEEL = 522 -WM_KEYDOWN = 256 -WM_KEYUP = 257 -WM_SYSKEYDOWN = 260 -WM_SYSKEYUP = 261 [Clipboard] =============== Comma = System.Char[] @@ -193,16 +92,51 @@ dragDropStep05ExCalledByIpc = 0 isDropping = False dragMachine = NONE k__BackingField = False +[Encryption] +=============== +magicNumber = 0 +ran = System.Random +--_impl = System.Random+XoshiroImpl +----_s0 = ???????????? +----_s1 = ???????????? +----_s2 = ???????????? +----_s3 = ???????????? +--k__BackingField = System.Random+ThreadSafeRandom +InitialIV = ???????????? +k__BackingField = False +k__BackingField = False +LegalKeyDictionary = Concurrent.ConcurrentDictionary`2[System.String,System.Byte[]] +--_tables = Concurrent.ConcurrentDictionary`2+Tables[System.String,System.Byte[]] +----_comparer = Generic.NonRandomizedStringEqualityComparer+OrdinalIgnoreCaseComparer +----_buckets = Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,System.Byte[]][] +------System.Collections.Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,System.Byte[]][] = Concurrent.ConcurrentDictionary`2+VolatileNode[System.String,System.Byte[]][]: N/A +----_fastModBucketsMultiplier = 498560650640798693 +----_locks = O[] +------System.Object[] = O[]: N/A +----_countPerLock = 32[] +------[0] = 0 +------[1] = 0 +------[2] = 0 +------[3] = 0 +------[4] = 0 +------[5] = 0 +------[6] = 0 +------[7] = 0 +--_budget = ???????????? +--_growLockArray = True +--_comparerIsDefaultForClasses = False +SymAlBlockSize = 16 +PW_LENGTH = 16 [Event] =============== -KeybdPackage = MouseWithoutBorders.DATA +KeybdPackage = MouseWithoutBorders.Core.DATA --Type = 0 --Id = 0 --Src = NONE --Des = NONE --DateTime = 0 ---Kd = MouseWithoutBorders.KEYBDDATA ---Md = MouseWithoutBorders.MOUSEDATA +--Kd = MouseWithoutBorders.Core.KEYBDDATA +--Md = MouseWithoutBorders.Core.MOUSEDATA --Machine1 = NONE --Machine2 = NONE --Machine3 = NONE @@ -212,14 +146,14 @@ KeybdPackage = MouseWithoutBorders.DATA --machineNameP2 = 0 --machineNameP3 = 0 --machineNameP4 = 0 -MousePackage = MouseWithoutBorders.DATA +MousePackage = MouseWithoutBorders.Core.DATA --Type = 0 --Id = 0 --Src = NONE --Des = NONE --DateTime = 0 ---Kd = MouseWithoutBorders.KEYBDDATA ---Md = MouseWithoutBorders.MOUSEDATA +--Kd = MouseWithoutBorders.Core.KEYBDDATA +--Md = MouseWithoutBorders.Core.MOUSEDATA --Machine1 = NONE --Machine2 = NONE --Machine3 = NONE @@ -296,7 +230,7 @@ LogCounter = Concurrent.ConcurrentDictionary`2[System.String,32] allLogsIndex = 0 lastHour = 0 exceptionCount = 0 -lastPackageSent = MouseWithoutBorders.PackageMonitor +lastPackageSent = MouseWithoutBorders.Core.PackageMonitor --Keyboard = 0 --Mouse = 0 --Heartbeat = 0 @@ -311,7 +245,7 @@ lastPackageSent = MouseWithoutBorders.PackageMonitor --ClipboardAsk = 0 --ExplorerDragDrop = 0 --Nil = 0 -lastPackageReceived = MouseWithoutBorders.PackageMonitor +lastPackageReceived = MouseWithoutBorders.Core.PackageMonitor --Keyboard = 0 --Mouse = 0 --Heartbeat = 0 @@ -366,6 +300,42 @@ MAX_SOCKET = 8 HEARTBEAT_TIMEOUT = 1500000 SKIP_PIXELS = 1 JUMP_PIXELS = 2 +[Package] +=============== +PackageSent = MouseWithoutBorders.Core.PackageMonitor +--Keyboard = 0 +--Mouse = 0 +--Heartbeat = 0 +--ByeBye = 0 +--Hello = 0 +--Matrix = 0 +--ClipboardText = 0 +--ClipboardImage = 0 +--Clipboard = 0 +--ClipboardDragDrop = 0 +--ClipboardDragDropEnd = 0 +--ClipboardAsk = 0 +--ExplorerDragDrop = 0 +--Nil = 0 +PackageReceived = MouseWithoutBorders.Core.PackageMonitor +--Keyboard = 0 +--Mouse = 0 +--Heartbeat = 0 +--ByeBye = 0 +--Hello = 0 +--Matrix = 0 +--ClipboardText = 0 +--ClipboardImage = 0 +--Clipboard = 0 +--ClipboardDragDrop = 0 +--ClipboardDragDropEnd = 0 +--ClipboardAsk = 0 +--ExplorerDragDrop = 0 +--Nil = 0 +PackageID = 0 +PACKAGE_SIZE = 32 +PACKAGE_SIZE_EX = 64 +WP_PACKAGE_SIZE = 6 [Receiver] =============== QUEUE_SIZE = 50 @@ -436,3 +406,41 @@ lastStartServiceTime = ???????????? --MinValue = 01/01/0001 00:00:00 --MaxValue = 31/12/9999 23:59:59 --UnixEpoch = 01/01/1970 00:00:00 +[WinAPI] +=============== +SensitivePoints = Generic.List`1[Point] +--_items = Point[] +----System.Drawing.Point[] = Point[]: N/A +--_size = 0 +--_version = 0 +--s_emptyArray = Point[] +----System.Drawing.Point[] = Point[]: N/A +p = {X=0,Y=0} +--x = 0 +--y = 0 +--Empty = {X=0,Y=0} +[WM] +=============== +KEYEVENTF_KEYDOWN = 1 +KEYEVENTF_KEYUP = 2 +WH_MOUSE = 7 +WH_KEYBOARD = 2 +WH_MOUSE_LL = 14 +WH_KEYBOARD_LL = 13 +WM_MOUSEMOVE = 512 +WM_LBUTTONDOWN = 513 +WM_RBUTTONDOWN = 516 +WM_MBUTTONDOWN = 519 +WM_XBUTTONDOWN = 523 +WM_LBUTTONUP = 514 +WM_RBUTTONUP = 517 +WM_MBUTTONUP = 520 +WM_XBUTTONUP = 524 +WM_LBUTTONDBLCLK = 515 +WM_RBUTTONDBLCLK = 518 +WM_MBUTTONDBLCLK = 521 +WM_MOUSEWHEEL = 522 +WM_KEYDOWN = 256 +WM_KEYUP = 257 +WM_SYSKEYDOWN = 260 +WM_SYSKEYUP = 261 diff --git a/src/modules/PowerOCR/PowerOCR/Settings/UserSettings.cs b/src/modules/PowerOCR/PowerOCR/Settings/UserSettings.cs index 0c57171f3a..053f3b5f30 100644 --- a/src/modules/PowerOCR/PowerOCR/Settings/UserSettings.cs +++ b/src/modules/PowerOCR/PowerOCR/Settings/UserSettings.cs @@ -29,7 +29,7 @@ namespace PowerOCR.Settings [ImportingConstructor] public UserSettings(Helpers.IThrottledActionInvoker throttledActionInvoker) { - _settingsUtils = new SettingsUtils(); + _settingsUtils = SettingsUtils.Default; ActivationShortcut = new SettingItem(DefaultActivationShortcut); PreferredLanguage = new SettingItem(string.Empty); diff --git a/src/modules/Workspaces/WorkspacesEditor/Utils/Settings.cs b/src/modules/Workspaces/WorkspacesEditor/Utils/Settings.cs index 29dd65d56f..0955e4019e 100644 --- a/src/modules/Workspaces/WorkspacesEditor/Utils/Settings.cs +++ b/src/modules/Workspaces/WorkspacesEditor/Utils/Settings.cs @@ -9,7 +9,7 @@ namespace WorkspacesEditor.Utils public class Settings { private const string WorkspacesModuleName = "Workspaces"; - private static readonly SettingsUtils _settingsUtils = new(); + private static readonly SettingsUtils _settingsUtils = SettingsUtils.Default; public static WorkspacesSettings ReadSettings() { diff --git a/src/modules/Workspaces/WorkspacesEditor/ViewModels/MainViewModel.cs b/src/modules/Workspaces/WorkspacesEditor/ViewModels/MainViewModel.cs index d05498d62e..30b28f4cd8 100644 --- a/src/modules/Workspaces/WorkspacesEditor/ViewModels/MainViewModel.cs +++ b/src/modules/Workspaces/WorkspacesEditor/ViewModels/MainViewModel.cs @@ -133,7 +133,7 @@ namespace WorkspacesEditor.ViewModels _orderByIndex = value; OnPropertyChanged(new PropertyChangedEventArgs(nameof(WorkspacesView))); settings.Properties.SortBy = (WorkspacesProperties.SortByProperty)value; - settings.Save(new SettingsUtils()); + settings.Save(SettingsUtils.Default); } } diff --git a/src/modules/awake/Awake/Core/Manager.cs b/src/modules/awake/Awake/Core/Manager.cs index c6aa1c2efb..cc3e461b20 100644 --- a/src/modules/awake/Awake/Core/Manager.cs +++ b/src/modules/awake/Awake/Core/Manager.cs @@ -60,7 +60,7 @@ namespace Awake.Core { _tokenSource = new CancellationTokenSource(); _stateQueue = []; - ModuleSettings = new SettingsUtils(); + ModuleSettings = SettingsUtils.Default; } internal static void StartMonitor() diff --git a/src/modules/awake/Awake/Program.cs b/src/modules/awake/Awake/Program.cs index 4d6d20bc96..b5c3102ba0 100644 --- a/src/modules/awake/Awake/Program.cs +++ b/src/modules/awake/Awake/Program.cs @@ -51,7 +51,7 @@ namespace Awake private static async Task Main(string[] args) { - _settingsUtils = new SettingsUtils(); + _settingsUtils = SettingsUtils.Default; LockMutex = new Mutex(true, Core.Constants.AppName, out bool instantiated); diff --git a/src/modules/cmdpal/Core/Microsoft.CmdPal.Core.ViewModels/Messages/DismissMessage.cs b/src/modules/cmdpal/Core/Microsoft.CmdPal.Core.ViewModels/Messages/DismissMessage.cs index 98a5b34562..8150ee6584 100644 --- a/src/modules/cmdpal/Core/Microsoft.CmdPal.Core.ViewModels/Messages/DismissMessage.cs +++ b/src/modules/cmdpal/Core/Microsoft.CmdPal.Core.ViewModels/Messages/DismissMessage.cs @@ -4,6 +4,4 @@ namespace Microsoft.CmdPal.Core.ViewModels.Messages; -public record DismissMessage() -{ -} +public record DismissMessage(bool ForceGoHome = false); diff --git a/src/modules/cmdpal/Core/Microsoft.CmdPal.Core.ViewModels/Messages/NavigateBackMessage.cs b/src/modules/cmdpal/Core/Microsoft.CmdPal.Core.ViewModels/Messages/NavigateBackMessage.cs index 3e085184ed..e6152b75d5 100644 --- a/src/modules/cmdpal/Core/Microsoft.CmdPal.Core.ViewModels/Messages/NavigateBackMessage.cs +++ b/src/modules/cmdpal/Core/Microsoft.CmdPal.Core.ViewModels/Messages/NavigateBackMessage.cs @@ -4,6 +4,4 @@ namespace Microsoft.CmdPal.Core.ViewModels.Messages; -public record NavigateBackMessage(bool FromBackspace = false) -{ -} +public record NavigateBackMessage(bool FromBackspace = false); diff --git a/src/modules/cmdpal/Core/Microsoft.CmdPal.Core.ViewModels/Messages/NavigateLeftCommand.cs b/src/modules/cmdpal/Core/Microsoft.CmdPal.Core.ViewModels/Messages/NavigateLeftCommand.cs new file mode 100644 index 0000000000..d352b552cf --- /dev/null +++ b/src/modules/cmdpal/Core/Microsoft.CmdPal.Core.ViewModels/Messages/NavigateLeftCommand.cs @@ -0,0 +1,10 @@ +// 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. + +namespace Microsoft.CmdPal.Core.ViewModels.Messages; + +/// +/// Used to navigate left in a grid view when pressing the Left arrow key in the SearchBox. +/// +public record NavigateLeftCommand; diff --git a/src/modules/cmdpal/Core/Microsoft.CmdPal.Core.ViewModels/Messages/NavigateRightCommand.cs b/src/modules/cmdpal/Core/Microsoft.CmdPal.Core.ViewModels/Messages/NavigateRightCommand.cs new file mode 100644 index 0000000000..3cfb05913d --- /dev/null +++ b/src/modules/cmdpal/Core/Microsoft.CmdPal.Core.ViewModels/Messages/NavigateRightCommand.cs @@ -0,0 +1,10 @@ +// 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. + +namespace Microsoft.CmdPal.Core.ViewModels.Messages; + +/// +/// Used to navigate right in a grid view when pressing the Right arrow key in the SearchBox. +/// +public record NavigateRightCommand; diff --git a/src/modules/cmdpal/Core/Microsoft.CmdPal.Core.ViewModels/ShellViewModel.cs b/src/modules/cmdpal/Core/Microsoft.CmdPal.Core.ViewModels/ShellViewModel.cs index 046d7ea336..2abbd83d3e 100644 --- a/src/modules/cmdpal/Core/Microsoft.CmdPal.Core.ViewModels/ShellViewModel.cs +++ b/src/modules/cmdpal/Core/Microsoft.CmdPal.Core.ViewModels/ShellViewModel.cs @@ -378,7 +378,7 @@ public partial class ShellViewModel : ObservableObject, { // Reset the palette to the main page and dismiss GoHome(withAnimation: false, focusSearch: false); - WeakReferenceMessenger.Default.Send(); + WeakReferenceMessenger.Default.Send(new DismissMessage()); break; } @@ -398,7 +398,7 @@ public partial class ShellViewModel : ObservableObject, case CommandResultKind.Hide: { // Keep this page open, but hide the palette. - WeakReferenceMessenger.Default.Send(); + WeakReferenceMessenger.Default.Send(new DismissMessage()); break; } diff --git a/src/modules/cmdpal/CoreCommonProps.props b/src/modules/cmdpal/CoreCommonProps.props index aa091d435e..438d044e2a 100644 --- a/src/modules/cmdpal/CoreCommonProps.props +++ b/src/modules/cmdpal/CoreCommonProps.props @@ -6,12 +6,12 @@ preview - $(SolutionDir)$(Platform)\$(Configuration)\WinUI3Apps\CmdPal\ + ..\..\..\$(Platform)\$(Configuration)\WinUI3Apps\CmdPal\ false false $(RootNamespace).pri - + SA1313; @@ -42,5 +42,5 @@ Resources.Designer.cs - + diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/MainListPage.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/MainListPage.cs index 003a0bfb9e..4118ac64db 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/MainListPage.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/MainListPage.cs @@ -12,6 +12,7 @@ using Microsoft.CmdPal.Core.ViewModels.Messages; using Microsoft.CmdPal.Ext.Apps; using Microsoft.CmdPal.Ext.Apps.Programs; using Microsoft.CmdPal.Ext.Apps.State; +using Microsoft.CmdPal.UI.ViewModels.Commands; using Microsoft.CmdPal.UI.ViewModels.Messages; using Microsoft.CmdPal.UI.ViewModels.Properties; using Microsoft.CommandPalette.Extensions; @@ -44,6 +45,9 @@ public partial class MainListPage : DynamicListPage, private List>? _filteredItems; private List>? _filteredApps; private List>? _fallbackItems; + + // Keep as IEnumerable for deferred execution. Fallback item titles are updated + // asynchronously, so scoring must happen lazily when GetItems is called. private IEnumerable>? _scoredFallbackItems; private bool _includeApps; private bool _filteredItemsIncludesApps; @@ -155,42 +159,18 @@ public partial class MainListPage : DynamicListPage, public override IListItem[] GetItems() { - if (string.IsNullOrEmpty(SearchText)) + lock (_tlcManager.TopLevelCommands) { - lock (_tlcManager.TopLevelCommands) - { - return _tlcManager - .TopLevelCommands - .Where(tlc => !tlc.IsFallback && !string.IsNullOrEmpty(tlc.Title)) - .ToArray(); - } - } - else - { - lock (_tlcManager.TopLevelCommands) - { - var limitedApps = new List>(); - - // Fuzzy matching can produce a lot of results, so we want to limit the - // number of apps we show at once if it's a large set. - if (_filteredApps?.Count > 0) - { - limitedApps = _filteredApps.OrderByDescending(s => s.Score).Take(_appResultLimit).ToList(); - } - - var items = Enumerable.Empty>() - .Concat(_filteredItems is not null ? _filteredItems : []) - .Concat(_scoredFallbackItems is not null ? _scoredFallbackItems : []) - .Concat(limitedApps) - .OrderByDescending(o => o.Score) - - // Add fallback items post-sort so they are always at the end of the list - // and eventually ordered based on user preference - .Concat(_fallbackItems is not null ? _fallbackItems.Where(w => !string.IsNullOrEmpty(w.Item.Title)) : []) - .Select(s => s.Item) - .ToArray(); - return items; - } + // Either return the top-level commands (no search text), or the merged and + // filtered results. + return string.IsNullOrEmpty(SearchText) + ? _tlcManager.TopLevelCommands.Where(tlc => !tlc.IsFallback && !string.IsNullOrEmpty(tlc.Title)).ToArray() + : MainListPageResultFactory.Create( + _filteredItems, + _scoredFallbackItems?.ToList(), + _filteredApps, + _fallbackItems, + _appResultLimit); } } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/MainListPageResultFactory.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/MainListPageResultFactory.cs new file mode 100644 index 0000000000..f1bddf5197 --- /dev/null +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/MainListPageResultFactory.cs @@ -0,0 +1,156 @@ +// 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 warning disable IDE0007 // Use implicit type + +using Microsoft.CommandPalette.Extensions; +using Microsoft.CommandPalette.Extensions.Toolkit; + +namespace Microsoft.CmdPal.UI.ViewModels.Commands; + +internal static class MainListPageResultFactory +{ + /// + /// Creates a merged and ordered array of results from multiple scored input lists, + /// applying an application result limit and filtering fallback items as needed. + /// + public static IListItem[] Create( + IList>? filteredItems, + IList>? scoredFallbackItems, + IList>? filteredApps, + IList>? fallbackItems, + int appResultLimit) + { + if (appResultLimit < 0) + { + throw new ArgumentOutOfRangeException( + nameof(appResultLimit), "App result limit must be non-negative."); + } + + int len1 = filteredItems?.Count ?? 0; + int len2 = scoredFallbackItems?.Count ?? 0; + + // Apps are pre-sorted, so we just need to take the top N, limited by appResultLimit. + int len3 = Math.Min(filteredApps?.Count ?? 0, appResultLimit); + + // Allocate the exact size of the result array. + int totalCount = len1 + len2 + len3 + GetNonEmptyFallbackItemsCount(fallbackItems); + var result = new IListItem[totalCount]; + + // Three-way stable merge of already-sorted lists. + int idx1 = 0, idx2 = 0, idx3 = 0; + int writePos = 0; + + // Merge while all three lists have items. To maintain a stable sort, the + // priority is: list1 > list2 > list3 when scores are equal. + while (idx1 < len1 && idx2 < len2 && idx3 < len3) + { + // Using null-forgiving operator as we have already checked against lengths. + int score1 = filteredItems![idx1].Score; + int score2 = scoredFallbackItems![idx2].Score; + int score3 = filteredApps![idx3].Score; + + if (score1 >= score2 && score1 >= score3) + { + result[writePos++] = filteredItems[idx1++].Item; + } + else if (score2 >= score3) + { + result[writePos++] = scoredFallbackItems[idx2++].Item; + } + else + { + result[writePos++] = filteredApps[idx3++].Item; + } + } + + // Two-way merges for remaining pairs. + while (idx1 < len1 && idx2 < len2) + { + if (filteredItems![idx1].Score >= scoredFallbackItems![idx2].Score) + { + result[writePos++] = filteredItems[idx1++].Item; + } + else + { + result[writePos++] = scoredFallbackItems[idx2++].Item; + } + } + + while (idx1 < len1 && idx3 < len3) + { + if (filteredItems![idx1].Score >= filteredApps![idx3].Score) + { + result[writePos++] = filteredItems[idx1++].Item; + } + else + { + result[writePos++] = filteredApps[idx3++].Item; + } + } + + while (idx2 < len2 && idx3 < len3) + { + if (scoredFallbackItems![idx2].Score >= filteredApps![idx3].Score) + { + result[writePos++] = scoredFallbackItems[idx2++].Item; + } + else + { + result[writePos++] = filteredApps[idx3++].Item; + } + } + + // Drain remaining items from a non-empty list. + while (idx1 < len1) + { + result[writePos++] = filteredItems![idx1++].Item; + } + + while (idx2 < len2) + { + result[writePos++] = scoredFallbackItems![idx2++].Item; + } + + while (idx3 < len3) + { + result[writePos++] = filteredApps![idx3++].Item; + } + + // Append filtered fallback items. Fallback items are added post-sort so they are + // always at the end of the list and eventually ordered based on user preference. + if (fallbackItems is not null) + { + for (int i = 0; i < fallbackItems.Count; i++) + { + var item = fallbackItems[i].Item; + if (!string.IsNullOrEmpty(item.Title)) + { + result[writePos++] = item; + } + } + } + + return result; + } + + private static int GetNonEmptyFallbackItemsCount(IList>? fallbackItems) + { + int fallbackItemsCount = 0; + + if (fallbackItems is not null) + { + for (int i = 0; i < fallbackItems.Count; i++) + { + if (!string.IsNullOrEmpty(fallbackItems[i].Item.Title)) + { + fallbackItemsCount++; + } + } + } + + return fallbackItemsCount; + } +} +#pragma warning restore IDE0007 // Use implicit type diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs index aee23ef0ca..dae50b3f3e 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs @@ -60,6 +60,8 @@ public partial class SettingsModel : ObservableObject public TimeSpan AutoGoHomeInterval { get; set; } = Timeout.InfiniteTimeSpan; + public EscapeKeyBehavior EscapeKeyBehaviorSetting { get; set; } = EscapeKeyBehavior.ClearSearchFirstThenGoBack; + // END SETTINGS /////////////////////////////////////////////////////////////////////////// @@ -282,3 +284,11 @@ public enum MonitorBehavior InPlace = 3, ToLast = 4, } + +public enum EscapeKeyBehavior +{ + ClearSearchFirstThenGoBack = 0, + AlwaysGoBack = 1, + AlwaysDismiss = 2, + AlwaysHide = 3, +} diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsViewModel.cs index 4d44db7d8a..586670bff7 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsViewModel.cs @@ -160,6 +160,16 @@ public partial class SettingsViewModel : INotifyPropertyChanged } } + public int EscapeKeyBehaviorIndex + { + get => (int)_settings.EscapeKeyBehaviorSetting; + set + { + _settings.EscapeKeyBehaviorSetting = (EscapeKeyBehavior)value; + Save(); + } + } + public ObservableCollection CommandProviders { get; } = []; public SettingsExtensionsViewModel Extensions { get; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/App.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/App.xaml.cs index f91b9e304a..53f47286b2 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/App.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/App.xaml.cs @@ -135,8 +135,9 @@ public partial class App : Application try { var winget = new WinGetExtensionCommandsProvider(); - var callback = allApps.LookupApp; - winget.SetAllLookup(callback); + winget.SetAllLookup( + query => allApps.LookupAppByPackageFamilyName(query, requireSingleMatch: true), + query => allApps.LookupAppByProductCode(query, requireSingleMatch: true)); services.AddSingleton(winget); } catch (Exception ex) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/CmdPal.Branding.props b/src/modules/cmdpal/Microsoft.CmdPal.UI/CmdPal.Branding.props index d99688c081..298bcbd787 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/CmdPal.Branding.props +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/CmdPal.Branding.props @@ -24,7 +24,7 @@ - + true Assets\%(RecursiveDir)%(FileName)%(Extension) @@ -35,14 +35,10 @@ - - - - + + + + diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/CmdPal.pre.props b/src/modules/cmdpal/Microsoft.CmdPal.UI/CmdPal.pre.props index 21c2e7d8d1..d65b4a2cc2 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/CmdPal.pre.props +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/CmdPal.pre.props @@ -7,7 +7,7 @@ - $(SolutionDir)$(Platform)\$(Configuration)\WinUI3Apps\CmdPal + ..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps\CmdPal $(OutputPath)\AppPackages\ diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml index 78e234a184..bc78de7e67 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml @@ -142,9 +142,9 @@ FontSize="16" Glyph="" /> + Style="{StaticResource CaptionTextBlockStyle}" /> App.Current.Services.GetRequiredService(); + public PageViewModel? CurrentPageViewModel { get => (PageViewModel?)GetValue(CurrentPageViewModelProperty); @@ -131,20 +135,39 @@ public sealed partial class SearchBar : UserControl, } else if (e.Key == VirtualKey.Escape) { - if (string.IsNullOrEmpty(FilterBox.Text)) + switch (Settings.EscapeKeyBehaviorSetting) { - WeakReferenceMessenger.Default.Send(new()); - } - else - { - // Clear the search box - FilterBox.Text = string.Empty; + case EscapeKeyBehavior.AlwaysGoBack: + WeakReferenceMessenger.Default.Send(new()); + break; - // hack TODO GH #245 - if (CurrentPageViewModel is not null) - { - CurrentPageViewModel.SearchTextBox = FilterBox.Text; - } + case EscapeKeyBehavior.AlwaysDismiss: + WeakReferenceMessenger.Default.Send(new(ForceGoHome: true)); + break; + + case EscapeKeyBehavior.AlwaysHide: + WeakReferenceMessenger.Default.Send(new()); + break; + + case EscapeKeyBehavior.ClearSearchFirstThenGoBack: + default: + if (string.IsNullOrEmpty(FilterBox.Text)) + { + WeakReferenceMessenger.Default.Send(new()); + } + else + { + // Clear the search box + FilterBox.Text = string.Empty; + + // hack TODO GH #245 + if (CurrentPageViewModel is not null) + { + CurrentPageViewModel.SearchTextBox = FilterBox.Text; + } + } + + break; } e.Handled = true; @@ -185,21 +208,32 @@ public sealed partial class SearchBar : UserControl, e.Handled = true; } + else if (e.Key == VirtualKey.Left) + { + // Check if we're in a grid view, and if so, send grid navigation command + var isGridView = CurrentPageViewModel is ListViewModel { IsGridView: true }; + + // Special handling is required if we're in grid view. + if (isGridView) + { + WeakReferenceMessenger.Default.Send(); + e.Handled = true; + } + } else if (e.Key == VirtualKey.Right) { // Check if the "replace search text with suggestion" feature from 0.4-0.5 is enabled. // If it isn't, then only use the suggestion when the caret is at the end of the input. if (!IsTextToSuggestEnabled) { - if (_textToSuggest != null && + if (!string.IsNullOrEmpty(_textToSuggest) && FilterBox.SelectionStart == FilterBox.Text.Length) { FilterBox.Text = _textToSuggest; FilterBox.Select(_textToSuggest.Length, 0); e.Handled = true; + return; } - - return; } // Here, we're using the "replace search text with suggestion" feature. @@ -209,6 +243,20 @@ public sealed partial class SearchBar : UserControl, _lastText = null; DoFilterBoxUpdate(); } + + // Wouldn't want to perform text completion *and* move the selected item, so only perform this if text suggestion wasn't performed. + if (!e.Handled) + { + // Check if we're in a grid view, and if so, send grid navigation command + var isGridView = CurrentPageViewModel is ListViewModel { IsGridView: true }; + + // Special handling is required if we're in grid view. + if (isGridView) + { + WeakReferenceMessenger.Default.Send(); + e.Handled = true; + } + } } else if (e.Key == VirtualKey.Down) { @@ -251,6 +299,8 @@ public sealed partial class SearchBar : UserControl, e.Key == VirtualKey.Up || e.Key == VirtualKey.Down || + e.Key == VirtualKey.Left || + e.Key == VirtualKey.Right || e.Key == VirtualKey.RightMenu || e.Key == VirtualKey.LeftMenu || diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/ExtViews/ListPage.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/ExtViews/ListPage.xaml.cs index a28ae3e133..8957f63ea4 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/ExtViews/ListPage.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/ExtViews/ListPage.xaml.cs @@ -26,6 +26,8 @@ namespace Microsoft.CmdPal.UI; public sealed partial class ListPage : Page, IRecipient, IRecipient, + IRecipient, + IRecipient, IRecipient, IRecipient, IRecipient, @@ -85,6 +87,8 @@ public sealed partial class ListPage : Page, // RegisterAll isn't AOT compatible WeakReferenceMessenger.Default.Register(this); WeakReferenceMessenger.Default.Register(this); + WeakReferenceMessenger.Default.Register(this); + WeakReferenceMessenger.Default.Register(this); WeakReferenceMessenger.Default.Register(this); WeakReferenceMessenger.Default.Register(this); WeakReferenceMessenger.Default.Register(this); @@ -99,6 +103,8 @@ public sealed partial class ListPage : Page, WeakReferenceMessenger.Default.Unregister(this); WeakReferenceMessenger.Default.Unregister(this); + WeakReferenceMessenger.Default.Unregister(this); + WeakReferenceMessenger.Default.Unregister(this); WeakReferenceMessenger.Default.Unregister(this); WeakReferenceMessenger.Default.Unregister(this); WeakReferenceMessenger.Default.Unregister(this); @@ -257,25 +263,71 @@ public sealed partial class ListPage : Page, // And then have these commands manipulate that state being bound to the UI instead // We may want to see how other non-list UIs need to behave to make this decision // At least it's decoupled from the SearchBox now :) - if (ItemView.SelectedIndex < ItemView.Items.Count - 1) + if (ViewModel?.IsGridView == true) { - ItemView.SelectedIndex++; + // For grid views, use spatial navigation (down) + HandleGridArrowNavigation(VirtualKey.Down); } else { - ItemView.SelectedIndex = 0; + // For list views, use simple linear navigation + if (ItemView.SelectedIndex < ItemView.Items.Count - 1) + { + ItemView.SelectedIndex++; + } + else + { + ItemView.SelectedIndex = 0; + } } } public void Receive(NavigatePreviousCommand message) { - if (ItemView.SelectedIndex > 0) + if (ViewModel?.IsGridView == true) { - ItemView.SelectedIndex--; + // For grid views, use spatial navigation (up) + HandleGridArrowNavigation(VirtualKey.Up); } else { - ItemView.SelectedIndex = ItemView.Items.Count - 1; + // For list views, use simple linear navigation + if (ItemView.SelectedIndex > 0) + { + ItemView.SelectedIndex--; + } + else + { + ItemView.SelectedIndex = ItemView.Items.Count - 1; + } + } + } + + public void Receive(NavigateLeftCommand message) + { + // For grid views, use spatial navigation. For list views, just move up. + if (ViewModel?.IsGridView == true) + { + HandleGridArrowNavigation(VirtualKey.Left); + } + else + { + // In list view, left arrow doesn't navigate + // This maintains consistency with the SearchBar behavior + } + } + + public void Receive(NavigateRightCommand message) + { + // For grid views, use spatial navigation. For list views, just move down. + if (ViewModel?.IsGridView == true) + { + HandleGridArrowNavigation(VirtualKey.Right); + } + else + { + // In list view, right arrow doesn't navigate + // This maintains consistency with the SearchBar behavior } } @@ -514,6 +566,130 @@ public sealed partial class ListPage : Page, return null; } + // Find a logical neighbor in the requested direction using containers' positions. + private void HandleGridArrowNavigation(VirtualKey key) + { + if (ItemView.Items.Count == 0) + { + // No items, goodbye. + return; + } + + var currentIndex = ItemView.SelectedIndex; + if (currentIndex < 0) + { + // -1 is a valid value (no item currently selected) + currentIndex = 0; + ItemView.SelectedIndex = 0; + } + + try + { + // Try to compute using container positions; if not available, fall back to simple +/-1. + var currentContainer = ItemView.ContainerFromIndex(currentIndex) as FrameworkElement; + if (currentContainer is not null && currentContainer.ActualWidth != 0 && currentContainer.ActualHeight != 0) + { + // Use center of current container as reference + var curPoint = currentContainer.TransformToVisual(ItemView).TransformPoint(new Point(0, 0)); + var curCenterX = curPoint.X + (currentContainer.ActualWidth / 2.0); + var curCenterY = curPoint.Y + (currentContainer.ActualHeight / 2.0); + + var bestScore = double.MaxValue; + var bestIndex = currentIndex; + + for (var i = 0; i < ItemView.Items.Count; i++) + { + if (i == currentIndex) + { + continue; + } + + if (ItemView.ContainerFromIndex(i) is FrameworkElement c && c.ActualWidth > 0 && c.ActualHeight > 0) + { + var p = c.TransformToVisual(ItemView).TransformPoint(new Point(0, 0)); + var centerX = p.X + (c.ActualWidth / 2.0); + var centerY = p.Y + (c.ActualHeight / 2.0); + + var dx = centerX - curCenterX; + var dy = centerY - curCenterY; + + var candidate = false; + var score = double.MaxValue; + + switch (key) + { + case VirtualKey.Left: + if (dx < 0) + { + candidate = true; + score = Math.Abs(dy) + (Math.Abs(dx) * 0.7); + } + + break; + case VirtualKey.Right: + if (dx > 0) + { + candidate = true; + score = Math.Abs(dy) + (Math.Abs(dx) * 0.7); + } + + break; + case VirtualKey.Up: + if (dy < 0) + { + candidate = true; + score = Math.Abs(dx) + (Math.Abs(dy) * 0.7); + } + + break; + case VirtualKey.Down: + if (dy > 0) + { + candidate = true; + score = Math.Abs(dx) + (Math.Abs(dy) * 0.7); + } + + break; + } + + if (candidate && score < bestScore) + { + bestScore = score; + bestIndex = i; + } + } + } + + if (bestIndex != currentIndex) + { + ItemView.SelectedIndex = bestIndex; + ItemView.ScrollIntoView(ItemView.SelectedItem); + } + + return; + } + } + catch + { + // ignore transform errors and fall back + } + + // fallback linear behavior + var fallback = key switch + { + VirtualKey.Left => Math.Max(0, currentIndex - 1), + VirtualKey.Right => Math.Min(ItemView.Items.Count - 1, currentIndex + 1), + VirtualKey.Up => Math.Max(0, currentIndex - 1), + VirtualKey.Down => Math.Min(ItemView.Items.Count - 1, currentIndex + 1), + _ => currentIndex, + }; + if (fallback != currentIndex) + { + ItemView.SelectedIndex = fallback; + ItemView.ScrollIntoView(ItemView.SelectedItem); + } + } + private void Items_OnContextRequested(UIElement sender, ContextRequestedEventArgs e) { var (item, element) = e.OriginalSource switch @@ -564,9 +740,27 @@ public sealed partial class ListPage : Page, private void Items_PreviewKeyDown(object sender, KeyRoutedEventArgs e) { + // Track keyboard as the last input source for activation logic. if (e.Key is VirtualKey.Enter or VirtualKey.Space) { _lastInputSource = InputSource.Keyboard; + return; + } + + // Handle arrow navigation when we're showing a grid. + if (ViewModel?.IsGridView == true) + { + switch (e.Key) + { + case VirtualKey.Left: + case VirtualKey.Right: + case VirtualKey.Up: + case VirtualKey.Down: + _lastInputSource = InputSource.Keyboard; + HandleGridArrowNavigation(e.Key); + e.Handled = true; + break; + } } } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs index 2936f8447e..1655626714 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs @@ -530,6 +530,11 @@ public sealed partial class MainWindow : WindowEx, public void Receive(DismissMessage message) { + if (message.ForceGoHome) + { + WeakReferenceMessenger.Default.Send(new GoHomeMessage(false, false)); + } + // This might come in off the UI thread. Make sure to hop back. DispatcherQueue.TryEnqueue(() => { diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Microsoft.CmdPal.UI.csproj b/src/modules/cmdpal/Microsoft.CmdPal.UI/Microsoft.CmdPal.UI.csproj index eac3643847..8397ffc767 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Microsoft.CmdPal.UI.csproj +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Microsoft.CmdPal.UI.csproj @@ -15,7 +15,7 @@ enable enable true - preview + preview $(CmdPalVersion) @@ -23,13 +23,14 @@ false false + true - + - + --> true @@ -45,7 +46,7 @@ - + Microsoft.Terminal.UI;CmdPalKeyboardService $(OutDir) @@ -95,7 +96,7 @@ - + all runtime; build; native; contentfiles; analyzers @@ -141,12 +142,16 @@ - - True - True - True + + False + True - + + + + + PreserveNewest + True True diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs index dc12cf142b..7e8dc9eebd 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs @@ -133,7 +133,7 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page, if (!message.FromBackspace) { // If we can't go back then we must be at the top and thus escape again should quit. - WeakReferenceMessenger.Default.Send(); + WeakReferenceMessenger.Default.Send(new DismissMessage()); PowerToysTelemetry.Log.WriteEvent(new CmdPalDismissedOnEsc()); } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/GeneralPage.xaml b/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/GeneralPage.xaml index 5f3ea2a55e..eb0264a683 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/GeneralPage.xaml +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/GeneralPage.xaml @@ -89,6 +89,15 @@ + + + + + + + + + diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/SettingsWindow.xaml b/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/SettingsWindow.xaml index baab5c16c2..dc3cf9fd3b 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/SettingsWindow.xaml +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/SettingsWindow.xaml @@ -20,13 +20,15 @@ - + @@ -56,10 +58,12 @@ @@ -90,7 +94,10 @@ - + diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/SettingsWindow.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/SettingsWindow.xaml.cs index 5d042a09e3..09000545d2 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/SettingsWindow.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/SettingsWindow.xaml.cs @@ -4,14 +4,19 @@ using System.Collections.ObjectModel; using CommunityToolkit.Mvvm.Messaging; +using ManagedCommon; using Microsoft.CmdPal.UI.Helpers; using Microsoft.CmdPal.UI.Messages; using Microsoft.CmdPal.UI.ViewModels; using Microsoft.CmdPal.UI.ViewModels.Messages; +using Microsoft.UI.Input; using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Automation.Peers; using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; +using Microsoft.UI.Xaml.Navigation; +using Windows.System; +using Windows.UI.Core; using WinUIEx; using RS_ = Microsoft.CmdPal.UI.Helpers.ResourceLoaderInstance; using TitleBar = Microsoft.UI.Xaml.Controls.TitleBar; @@ -19,9 +24,12 @@ using TitleBar = Microsoft.UI.Xaml.Controls.TitleBar; namespace Microsoft.CmdPal.UI.Settings; public sealed partial class SettingsWindow : WindowEx, + IDisposable, IRecipient, IRecipient { + private readonly LocalKeyboardListener _localKeyboardListener; + public ObservableCollection BreadCrumbs { get; } = []; // Gets or sets optional action invoked after NavigationView is loaded. @@ -40,6 +48,17 @@ public sealed partial class SettingsWindow : WindowEx, WeakReferenceMessenger.Default.Register(this); WeakReferenceMessenger.Default.Register(this); + + _localKeyboardListener = new LocalKeyboardListener(); + _localKeyboardListener.KeyPressed += LocalKeyboardListener_OnKeyPressed; + _localKeyboardListener.Start(); + Closed += SettingsWindow_Closed; + RootElement.AddHandler(UIElement.PointerPressedEvent, new PointerEventHandler(RootElement_OnPointerPressed), true); + } + + private void SettingsWindow_Closed(object sender, WindowEventArgs args) + { + Dispose(); } // Handles NavigationView loaded event. @@ -85,10 +104,9 @@ public sealed partial class SettingsWindow : WindowEx, "Extensions" => typeof(ExtensionsPage), _ => null, }; + if (pageType is not null) { - BreadCrumbs.Clear(); - BreadCrumbs.Add(new(page, page)); NavFrame.Navigate(pageType); } } @@ -96,7 +114,6 @@ public sealed partial class SettingsWindow : WindowEx, private void Navigate(ProviderSettingsViewModel extension) { NavFrame.Navigate(typeof(ExtensionPage), extension); - BreadCrumbs.Add(new(extension.DisplayName, string.Empty)); } private void PositionCentered() @@ -127,9 +144,9 @@ public sealed partial class SettingsWindow : WindowEx, } } - private void Window_Activated(object sender, WindowActivatedEventArgs args) + private void Window_Activated(object sender, Microsoft.UI.Xaml.WindowActivatedEventArgs args) { - WeakReferenceMessenger.Default.Send(args); + WeakReferenceMessenger.Default.Send(args); } private void Window_Closed(object sender, WindowEventArgs args) @@ -141,7 +158,7 @@ public sealed partial class SettingsWindow : WindowEx, private void NavView_DisplayModeChanged(NavigationView sender, NavigationViewDisplayModeChangedEventArgs args) { - if (args.DisplayMode == NavigationViewDisplayMode.Compact || args.DisplayMode == NavigationViewDisplayMode.Minimal) + if (args.DisplayMode is NavigationViewDisplayMode.Compact or NavigationViewDisplayMode.Minimal) { AppTitleBar.IsPaneToggleButtonVisible = true; WorkAroundIcon.Margin = new Thickness(8, 0, 16, 0); // Required for workaround, see XAML comment @@ -149,7 +166,7 @@ public sealed partial class SettingsWindow : WindowEx, else { AppTitleBar.IsPaneToggleButtonVisible = false; - WorkAroundIcon.Margin = new Thickness(16, 0, 0, 0); // Required for workaround, see XAML comment + WorkAroundIcon.Margin = new Thickness(16, 0, 8, 0); // Required for workaround, see XAML comment } } @@ -163,6 +180,93 @@ public sealed partial class SettingsWindow : WindowEx, { NavView.IsPaneOpen = !NavView.IsPaneOpen; } + + private void TryGoBack() + { + if (NavFrame.CanGoBack) + { + NavFrame.GoBack(); + } + } + + private void TitleBar_BackRequested(TitleBar sender, object args) + { + TryGoBack(); + } + + private void LocalKeyboardListener_OnKeyPressed(object? sender, LocalKeyboardListenerKeyPressedEventArgs e) + { + switch (e.Key) + { + case VirtualKey.GoBack: + case VirtualKey.XButton1: + TryGoBack(); + break; + + case VirtualKey.Left: + var altPressed = InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Menu).HasFlag(CoreVirtualKeyStates.Down); + if (altPressed) + { + TryGoBack(); + } + + break; + } + } + + private void RootElement_OnPointerPressed(object sender, PointerRoutedEventArgs e) + { + try + { + if (e.Pointer.PointerDeviceType == PointerDeviceType.Mouse) + { + var ptrPt = e.GetCurrentPoint(RootElement); + if (ptrPt.Properties.IsXButton1Pressed) + { + TryGoBack(); + } + } + } + catch (Exception ex) + { + Logger.LogError("Error handling mouse button press event", ex); + } + } + + public void Dispose() + { + _localKeyboardListener?.Dispose(); + } + + private void NavFrame_OnNavigated(object sender, NavigationEventArgs e) + { + BreadCrumbs.Clear(); + + if (e.SourcePageType == typeof(GeneralPage)) + { + NavView.SelectedItem = GeneralPageNavItem; + var pageType = RS_.GetString("Settings_PageTitles_GeneralPage"); + BreadCrumbs.Add(new(pageType, pageType)); + } + else if (e.SourcePageType == typeof(ExtensionsPage)) + { + NavView.SelectedItem = ExtensionPageNavItem; + var pageType = RS_.GetString("Settings_PageTitles_ExtensionsPage"); + BreadCrumbs.Add(new(pageType, pageType)); + } + else if (e.SourcePageType == typeof(ExtensionPage) && e.Parameter is ProviderSettingsViewModel vm) + { + NavView.SelectedItem = ExtensionPageNavItem; + var extensionsPageType = RS_.GetString("Settings_PageTitles_ExtensionsPage"); + BreadCrumbs.Add(new(extensionsPageType, extensionsPageType)); + BreadCrumbs.Add(new(vm.DisplayName, vm)); + } + else + { + BreadCrumbs.Add(new($"[{e.SourcePageType?.Name}]", string.Empty)); + Logger.LogError($"Unknown breadcrumb for page type '{e.SourcePageType}'"); + } + } } public readonly struct Crumb diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Strings/en-us/Resources.resw b/src/modules/cmdpal/Microsoft.CmdPal.UI/Strings/en-us/Resources.resw index 89f7b5f10d..8fe053cae2 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Strings/en-us/Resources.resw +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Strings/en-us/Resources.resw @@ -1,17 +1,17 @@  - @@ -550,4 +550,31 @@ Right-click to remove the key combination, thereby deactivating the shortcut. Automatically returns to home page after a period of inactivity when Command Palette is closed + + General + + + Extensions + + + Clear search first, then go back + + + Go back + + + Hide window and go home + + + Hide window + + + Escape key behavior + + + Choose how Escape key behaves + + + Settings + \ No newline at end of file diff --git a/src/modules/cmdpal/Microsoft.Terminal.UI/FontIconGlyphClassifier.cpp b/src/modules/cmdpal/Microsoft.Terminal.UI/FontIconGlyphClassifier.cpp index bc3496a542..e6cb46457b 100644 --- a/src/modules/cmdpal/Microsoft.Terminal.UI/FontIconGlyphClassifier.cpp +++ b/src/modules/cmdpal/Microsoft.Terminal.UI/FontIconGlyphClassifier.cpp @@ -12,9 +12,9 @@ namespace winrt::Microsoft::Terminal::UI::implementation // Check if the code point is in the Private Use Area range used by Fluent UI icons. [[nodiscard]] constexpr bool _isFluentIconPua(const UChar32 cp) noexcept { - static constexpr UChar32 _fluentIconsPrivateUseAreaStart = 0xE700; - static constexpr UChar32 _fluentIconsPrivateUseAreaEnd = 0xF8FF; - return cp >= _fluentIconsPrivateUseAreaStart && cp <= _fluentIconsPrivateUseAreaEnd; + constexpr UChar32 fluentIconsPrivateUseAreaStart = 0xE700; + constexpr UChar32 fluentIconsPrivateUseAreaEnd = 0xF8FF; + return cp >= fluentIconsPrivateUseAreaStart && cp <= fluentIconsPrivateUseAreaEnd; } // Determine if the given text (as a sequence of UChar code units) is emoji diff --git a/src/modules/cmdpal/Microsoft.Terminal.UI/Microsoft.Terminal.UI.vcxproj b/src/modules/cmdpal/Microsoft.Terminal.UI/Microsoft.Terminal.UI.vcxproj index 6e474cf5f3..676d7297ba 100644 --- a/src/modules/cmdpal/Microsoft.Terminal.UI/Microsoft.Terminal.UI.vcxproj +++ b/src/modules/cmdpal/Microsoft.Terminal.UI/Microsoft.Terminal.UI.vcxproj @@ -1,17 +1,16 @@  - - - ..\..\..\..\ - $(PathToRoot)packages\Microsoft.WindowsAppSDK.1.8.250907003 + + + PackageReference + + native,Version=v0.0 + + Windows + $(WindowsTargetPlatformVersion) + + - - - - - - - true true @@ -28,6 +27,11 @@ 10.0.26100.0 10.0.19041.0 + + + + + @@ -47,10 +51,6 @@ x64 - - $(SolutionDir)$(Platform)\$(Configuration)\WinUI3Apps\CmdPal - obj\$(Platform)\$(Configuration)\ - DynamicLibrary v143 @@ -200,43 +200,11 @@ - + + ..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps\CmdPal + obj\$(Platform)\$(Configuration)\ + - - - - - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/modules/cmdpal/Microsoft.Terminal.UI/packages.config b/src/modules/cmdpal/Microsoft.Terminal.UI/packages.config deleted file mode 100644 index 2fb34c8fed..0000000000 --- a/src/modules/cmdpal/Microsoft.Terminal.UI/packages.config +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.Apps.UnitTests/AllAppsCommandProviderTests.cs b/src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.Apps.UnitTests/AllAppsCommandProviderTests.cs index e7fbc6859d..cc24433931 100644 --- a/src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.Apps.UnitTests/AllAppsCommandProviderTests.cs +++ b/src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.Apps.UnitTests/AllAppsCommandProviderTests.cs @@ -58,7 +58,7 @@ public class AllAppsCommandProviderTests : AppsTestBase var provider = new AllAppsCommandProvider(page); // Act - var result = provider.LookupApp(string.Empty); + var result = provider.LookupAppByDisplayName(string.Empty); // Assert Assert.IsNotNull(result); @@ -77,7 +77,7 @@ public class AllAppsCommandProviderTests : AppsTestBase await WaitForPageInitializationAsync(); // Act - var result = provider.LookupApp("TestApp"); + var result = provider.LookupAppByDisplayName("TestApp"); // Assert Assert.IsNotNull(result); @@ -97,7 +97,7 @@ public class AllAppsCommandProviderTests : AppsTestBase await WaitForPageInitializationAsync(); // Act - var result = provider.LookupApp("NonExistentApp"); + var result = provider.LookupAppByDisplayName("NonExistentApp"); // Assert Assert.IsNull(result); diff --git a/src/modules/cmdpal/Tests/Microsoft.CmdPal.UI.ViewModels.UnitTests/MainListPageResultFactoryTests.cs b/src/modules/cmdpal/Tests/Microsoft.CmdPal.UI.ViewModels.UnitTests/MainListPageResultFactoryTests.cs new file mode 100644 index 0000000000..624fa2da73 --- /dev/null +++ b/src/modules/cmdpal/Tests/Microsoft.CmdPal.UI.ViewModels.UnitTests/MainListPageResultFactoryTests.cs @@ -0,0 +1,161 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.CmdPal.UI.ViewModels.Commands; +using Microsoft.CommandPalette.Extensions; +using Microsoft.CommandPalette.Extensions.Toolkit; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Windows.Foundation; + +namespace Microsoft.CmdPal.UI.ViewModels.UnitTests; + +[TestClass] +public partial class MainListPageResultFactoryTests +{ + private sealed partial class MockListItem : IListItem + { + public string Title { get; set; } = string.Empty; + + public string Subtitle { get; set; } = string.Empty; + + public ICommand Command => new NoOpCommand(); + + public IDetails? Details => null; + + public IIconInfo? Icon => null; + + public string Section => throw new NotImplementedException(); + + public ITag[] Tags => throw new NotImplementedException(); + + public string TextToSuggest => throw new NotImplementedException(); + + public IContextItem[] MoreCommands => throw new NotImplementedException(); + +#pragma warning disable CS0067 // The event is never used + public event TypedEventHandler? PropChanged; +#pragma warning restore CS0067 // The event is never used + + public override string ToString() => Title; + } + + private static Scored S(string title, int score) + { + return new Scored + { + Score = score, + Item = new MockListItem { Title = title }, + }; + } + + [TestMethod] + public void Merge_PrioritizesListsCorrectly() + { + var filtered = new List> + { + S("F1", 100), + S("F2", 50), + }; + + var scoredFallback = new List> + { + S("SF1", 100), + S("SF2", 60), + }; + + var apps = new List> + { + S("A1", 100), + S("A2", 55), + }; + + // Fallbacks are not scored. + var fallbacks = new List> + { + S("FB1", 0), + S("FB2", 0), + }; + + var result = MainListPageResultFactory.Create( + filtered, + scoredFallback, + apps, + fallbacks, + appResultLimit: 10); + + // Expected order: + // 100: F1, SF1, A1 + // 60: SF2 + // 55: A2 + // 50: F2 + // Then fallbacks in original order: FB1, FB2 + var titles = result.Select(r => r.Title).ToArray(); +#pragma warning disable CA1861 // Avoid constant arrays as arguments + CollectionAssert.AreEqual( + new[] { "F1", "SF1", "A1", "SF2", "A2", "F2", "FB1", "FB2" }, + titles); +#pragma warning restore CA1861 // Avoid constant arrays as arguments + } + + [TestMethod] + public void Merge_AppliesAppLimit() + { + var apps = new List> + { + S("A1", 100), + S("A2", 90), + S("A3", 80), + }; + + var result = MainListPageResultFactory.Create( + null, + null, + apps, + null, + 2); + + Assert.AreEqual(2, result.Length); + Assert.AreEqual("A1", result[0].Title); + Assert.AreEqual("A2", result[1].Title); + } + + [TestMethod] + public void Merge_FiltersEmptyFallbacks() + { + var fallbacks = new List> + { + S("FB1", 0), + S(string.Empty, 0), + S("FB3", 0), + }; + + var result = MainListPageResultFactory.Create( + null, + null, + null, + fallbacks, + appResultLimit: 10); + + Assert.AreEqual(2, result.Length); + Assert.AreEqual("FB1", result[0].Title); + Assert.AreEqual("FB3", result[1].Title); + } + + [TestMethod] + public void Merge_HandlesNullLists() + { + var result = MainListPageResultFactory.Create( + null, + null, + null, + null, + appResultLimit: 10); + + Assert.IsNotNull(result); + Assert.AreEqual(0, result.Length); + } +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AllAppsCommandProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AllAppsCommandProvider.cs index 7232e955d7..317087847e 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AllAppsCommandProvider.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AllAppsCommandProvider.cs @@ -4,6 +4,8 @@ using System; using System.Collections.Generic; +using Microsoft.CmdPal.Ext.Apps.Helpers; +using Microsoft.CmdPal.Ext.Apps.Programs; using Microsoft.CmdPal.Ext.Apps.Properties; using Microsoft.CmdPal.Ext.Apps.State; using Microsoft.CommandPalette.Extensions; @@ -66,7 +68,71 @@ public partial class AllAppsCommandProvider : CommandProvider public override ICommandItem[] TopLevelCommands() => [_listItem, .. _page.GetPinnedApps()]; - public ICommandItem? LookupApp(string displayName) + public ICommandItem? LookupAppByPackageFamilyName(string packageFamilyName, bool requireSingleMatch) + { + if (string.IsNullOrEmpty(packageFamilyName)) + { + return null; + } + + var items = _page.GetItems(); + List matches = []; + + foreach (var item in items) + { + if (item is AppListItem appItem && string.Equals(packageFamilyName, appItem.App.PackageFamilyName, StringComparison.OrdinalIgnoreCase)) + { + matches.Add(item); + if (!requireSingleMatch) + { + // Return early if we don't require uniqueness. + return item; + } + } + } + + return requireSingleMatch && matches.Count == 1 ? matches[0] : null; + } + + public ICommandItem? LookupAppByProductCode(string productCode, bool requireSingleMatch) + { + if (string.IsNullOrEmpty(productCode)) + { + return null; + } + + if (!UninstallRegistryAppLocator.TryGetInstallInfo(productCode, out _, out var candidates) || candidates.Count <= 0) + { + return null; + } + + var items = _page.GetItems(); + List matches = []; + + foreach (var item in items) + { + if (item is not AppListItem appListItem || string.IsNullOrEmpty(appListItem.App.FullExecutablePath)) + { + continue; + } + + foreach (var candidate in candidates) + { + if (string.Equals(appListItem.App.FullExecutablePath, candidate, StringComparison.OrdinalIgnoreCase)) + { + matches.Add(item); + if (!requireSingleMatch) + { + return item; + } + } + } + } + + return requireSingleMatch && matches.Count == 1 ? matches[0] : null; + } + + public ICommandItem? LookupAppByDisplayName(string displayName) { var items = _page.GetItems(); diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppItem.cs index b7d01593cb..14f9597418 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppItem.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppItem.cs @@ -29,6 +29,10 @@ public sealed class AppItem public string AppIdentifier { get; set; } = string.Empty; + public string? PackageFamilyName { get; set; } + + public string? FullExecutablePath { get; set; } + public AppItem() { } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppListItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppListItem.cs index e99ffae352..5689b70698 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppListItem.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppListItem.cs @@ -40,6 +40,8 @@ public sealed partial class AppListItem : ListItem public string AppIdentifier => _app.AppIdentifier; + public AppItem App => _app; + public AppListItem(AppItem app, bool useThumbnails, bool isPinned) { Command = _appCommand = new AppCommand(app); @@ -82,6 +84,12 @@ public sealed partial class AppListItem : ListItem metadata.Add(new DetailsElement() { Key = "Path", Data = new DetailsLink() { Text = _app.ExePath } }); } +#if DEBUG + metadata.Add(new DetailsElement() { Key = "[DEBUG] AppIdentifier", Data = new DetailsLink() { Text = _app.AppIdentifier } }); + metadata.Add(new DetailsElement() { Key = "[DEBUG] ExePath", Data = new DetailsLink() { Text = _app.ExePath } }); + metadata.Add(new DetailsElement() { Key = "[DEBUG] IcoPath", Data = new DetailsLink() { Text = _app.IcoPath } }); +#endif + // Icon IconInfo? heroImage = null; if (_app.IsPackaged) diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Helpers/UninstallRegistryAppLocator.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Helpers/UninstallRegistryAppLocator.cs new file mode 100644 index 0000000000..8e59a26395 --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Helpers/UninstallRegistryAppLocator.cs @@ -0,0 +1,205 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.Win32; + +namespace Microsoft.CmdPal.Ext.Apps.Helpers; + +internal static class UninstallRegistryAppLocator +{ + private static readonly string[] UninstallBaseKeys = + [ + @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", + @"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall", + ]; + + /// + /// Tries to find install directory and a list of plausible main EXEs from an uninstall key + /// (e.g. Inno Setup keys like "{guid}_is1"). + /// may be empty if we couldn't pick any safe EXEs. + /// + /// + /// Returns true if the uninstall key is found and an install directory is resolved. + /// + public static bool TryGetInstallInfo( + string uninstallKeyName, + out string? installDir, + out IReadOnlyList exeCandidates, + string? expectedExeName = null) + { + installDir = null; + exeCandidates = []; + + if (string.IsNullOrWhiteSpace(uninstallKeyName)) + { + throw new ArgumentException("Key name must not be null or empty.", nameof(uninstallKeyName)); + } + + uninstallKeyName = uninstallKeyName.Trim(); + + foreach (var baseKeyPath in UninstallBaseKeys) + { + // HKLM + using (var key = Registry.LocalMachine.OpenSubKey($"{baseKeyPath}\\{uninstallKeyName}")) + { + if (TryFromUninstallKey(key, expectedExeName, out installDir, out exeCandidates)) + { + return true; + } + } + + // HKCU + using (var key = Registry.CurrentUser.OpenSubKey($"{baseKeyPath}\\{uninstallKeyName}")) + { + if (TryFromUninstallKey(key, expectedExeName, out installDir, out exeCandidates)) + { + return true; + } + } + } + + return false; + } + + private static bool TryFromUninstallKey( + RegistryKey? key, + string? expectedExeName, + out string? installDir, + out IReadOnlyList exeCandidates) + { + installDir = null; + exeCandidates = []; + + if (key is null) + { + return false; + } + + var location = (key.GetValue("InstallLocation") as string)?.Trim('"', ' ', '\t'); + if (string.IsNullOrEmpty(location)) + { + location = (key.GetValue("Inno Setup: App Path") as string)?.Trim('"', ' ', '\t'); + } + + if (string.IsNullOrEmpty(location)) + { + var uninstall = key.GetValue("UninstallString") as string; + var uninsExe = ExtractFirstPath(uninstall); + if (!string.IsNullOrEmpty(uninsExe)) + { + var dir = Path.GetDirectoryName(uninsExe); + if (!string.IsNullOrEmpty(dir) && Directory.Exists(dir)) + { + location = dir; + } + } + } + + if (string.IsNullOrEmpty(location) || !Directory.Exists(location)) + { + return false; + } + + installDir = location; + + // Collect safe EXE candidates; may be empty if ambiguous or only uninstall exes exist. + exeCandidates = GetExeCandidates(location, expectedExeName); + return true; + } + + private static IReadOnlyList GetExeCandidates(string root, string? expectedExeName) + { + // Look at root and a "bin" subfolder (very common pattern) + var allExes = Directory.EnumerateFiles(root, "*.exe", SearchOption.TopDirectoryOnly) + .Concat(GetBinExes(root)) + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToArray(); + + if (allExes.Length == 0) + { + return []; + } + + var result = new List(); + + // 1) Exact match on expected exe name (if provided), ignoring case, and not uninstall/setup-like. + if (!string.IsNullOrWhiteSpace(expectedExeName)) + { + foreach (var exe in allExes) + { + if (string.Equals(Path.GetFileName(exe), expectedExeName, StringComparison.OrdinalIgnoreCase) && + !LooksLikeUninstallerOrSetup(exe)) + { + result.Add(exe); + } + } + } + + // 2) All other non-uninstall/setup exes + foreach (var exe in allExes) + { + if (LooksLikeUninstallerOrSetup(exe)) + { + continue; + } + + // Skip ones already added as expectedExeName matches + if (result.Contains(exe, StringComparer.OrdinalIgnoreCase)) + { + continue; + } + + result.Add(exe); + } + + // 3) We intentionally do NOT add uninstall/setup/update exes here. + // If you ever want them, you can add a separate API to expose them. + return result; + } + + private static IEnumerable GetBinExes(string root) + { + var bin = Path.Combine(root, "bin"); + return !Directory.Exists(bin) + ? [] + : Directory.EnumerateFiles(bin, "*.exe", SearchOption.TopDirectoryOnly); + } + + private static bool LooksLikeUninstallerOrSetup(string path) + { + var name = Path.GetFileName(path); + return name.StartsWith("unins", StringComparison.OrdinalIgnoreCase) // e.g. Inno: unins000.exe + || name.Contains("setup", StringComparison.OrdinalIgnoreCase) // setup.exe + || name.Contains("installer", StringComparison.OrdinalIgnoreCase) // installer.exe / MyAppInstaller.exe + || name.Contains("update", StringComparison.OrdinalIgnoreCase); // updater/updater.exe + } + + private static string? ExtractFirstPath(string? commandLine) + { + if (string.IsNullOrWhiteSpace(commandLine)) + { + return null; + } + + commandLine = commandLine.Trim(); + + if (commandLine.StartsWith('"')) + { + var endQuote = commandLine.IndexOf('"', 1); + if (endQuote > 1) + { + return commandLine[1..endQuote]; + } + } + + var firstSpace = commandLine.IndexOf(' '); + var candidate = firstSpace > 0 ? commandLine[..firstSpace] : commandLine; + candidate = candidate.Trim('"'); + return candidate.Length > 0 ? candidate : null; + } +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/UWPApplication.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/UWPApplication.cs index 37698d972d..4ec9598483 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/UWPApplication.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/UWPApplication.cs @@ -558,6 +558,7 @@ public class UWPApplication : IUWPApplication IsPackaged = true, Commands = app.GetCommands(), AppIdentifier = app.GetAppIdentifier(), + PackageFamilyName = app.Package.FamilyName, }; return item; } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/Win32Program.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/Win32Program.cs index 9b89afc425..fda8e2c697 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/Win32Program.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/Win32Program.cs @@ -1065,6 +1065,7 @@ public class Win32Program : IProgram DirPath = app.Location, Commands = app.GetCommands(), AppIdentifier = app.GetAppIdentifier(), + FullExecutablePath = app.FullPath, }; } } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.RemoteDesktop/Properties/Resources.Designer.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.RemoteDesktop/Properties/Resources.Designer.cs index de0b924c33..f3262d526c 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.RemoteDesktop/Properties/Resources.Designer.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.RemoteDesktop/Properties/Resources.Designer.cs @@ -19,7 +19,7 @@ namespace Microsoft.CmdPal.Ext.RemoteDesktop.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "18.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class Resources { @@ -88,7 +88,8 @@ namespace Microsoft.CmdPal.Ext.RemoteDesktop.Properties { } /// - /// Looks up a localized string similar to Unable to initialize Microsoft Terminal Service Client. Ensure it is enabled in Windows Settings.\r{0}. + /// Looks up a localized string similar to Unable to initialize Microsoft Terminal Service Client. Ensure it is enabled in Windows Settings. + ///{0}. /// public static string remotedesktop_log_mstsc_error { get { diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.RemoteDesktop/Properties/Resources.resx b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.RemoteDesktop/Properties/Resources.resx index bfbf1d3ac5..75603679d4 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.RemoteDesktop/Properties/Resources.resx +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.RemoteDesktop/Properties/Resources.resx @@ -142,7 +142,8 @@ A list of connections to include in the query results by default - Unable to initialize Microsoft Terminal Service Client. Ensure it is enabled in Windows Settings.\r{0} + Unable to initialize Microsoft Terminal Service Client. Ensure it is enabled in Windows Settings. +{0} The hostname '{0}' was invalid. Ensure you're using a valid hostname or IP address. diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageCommand.cs index d2c1ea7283..7dbe740d95 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageCommand.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageCommand.cs @@ -62,7 +62,7 @@ public partial class InstallPackageCommand : InvokableCommand { PackageInstallCommandState.Install => Icons.DownloadIcon, PackageInstallCommandState.Update => Icons.UpdateIcon, - PackageInstallCommandState.Uninstall => Icons.CompletedIcon, + PackageInstallCommandState.Uninstall => Icons.DeleteIcon, _ => throw new NotImplementedException(), }; Name = InstallCommandState switch diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageListItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageListItem.cs index a8eda1bae9..1e1f337944 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageListItem.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageListItem.cs @@ -194,46 +194,95 @@ public partial class InstallPackageListItem : ListItem var isInstalled = _package.InstalledVersion is not null; var installedState = isInstalled ? - (_package.IsUpdateAvailable ? - PackageInstallCommandState.Update : PackageInstallCommandState.Uninstall) : + (_package.IsUpdateAvailable ? PackageInstallCommandState.Update : PackageInstallCommandState.Uninstall) : PackageInstallCommandState.Install; // might be an uninstall command InstallPackageCommand installCommand = new(_package, installedState); - if (isInstalled) + if (_package.InstalledVersion is not null) { - this.Icon = installCommand.Icon; - this.Command = new NoOpCommand(); +#if DEBUG + var installerType = _package.InstalledVersion.GetMetadata(PackageVersionMetadataField.InstallerType); + Subtitle = installerType + " | " + Subtitle; +#endif + List contextMenu = []; - CommandContextItem uninstallContextItem = new(installCommand) + Command = installCommand; + Icon = installedState switch { - IsCritical = true, - Icon = Icons.DeleteIcon, + PackageInstallCommandState.Install => Icons.DownloadIcon, + PackageInstallCommandState.Update => Icons.UpdateIcon, + PackageInstallCommandState.Uninstall => Icons.CompletedIcon, + _ => Icons.DownloadIcon, }; - if (WinGetStatics.AppSearchCallback is not null) + TryLocateAndAppendActionForApp(contextMenu); + + MoreCommands = contextMenu.ToArray(); + } + else + { + _installCommand = new InstallPackageCommand(_package, installedState); + _installCommand.InstallStateChanged += InstallStateChangedHandler; + Command = _installCommand; + Icon = _installCommand.Icon; + } + } + + private void TryLocateAndAppendActionForApp(List contextMenu) + { + try + { + // Let's try to connect it to an installed app if possible + // This is a bit of dark magic, since there's no direct link between + // WinGet packages and installed apps. + var lookupByPackageName = WinGetStatics.AppSearchByPackageFamilyNameCallback; + if (lookupByPackageName is not null) { - var callback = WinGetStatics.AppSearchCallback; - var installedApp = callback(_package.DefaultInstallVersion is null ? _package.Name : _package.DefaultInstallVersion.DisplayName); - if (installedApp is not null) + var names = _package.InstalledVersion.PackageFamilyNames; + for (var i = 0; i < names.Count; i++) { - this.Command = installedApp.Command; - contextMenu = [.. installedApp.MoreCommands]; + var installedAppByPfn = lookupByPackageName(names[i]); + if (installedAppByPfn is not null) + { + contextMenu.Add(new Separator()); + contextMenu.Add(new CommandContextItem(installedAppByPfn.Command)); + foreach (var item in installedAppByPfn.MoreCommands) + { + contextMenu.Add(item); + } + + return; + } } } - contextMenu.Add(uninstallContextItem); - this.MoreCommands = contextMenu.ToArray(); - return; + var lookupByProductCode = WinGetStatics.AppSearchByProductCodeCallback; + if (lookupByProductCode is not null) + { + var productCodes = _package.InstalledVersion.ProductCodes; + for (var i = 0; i < productCodes.Count; i++) + { + var installedAppByProductCode = lookupByProductCode(productCodes[i]); + if (installedAppByProductCode is not null) + { + contextMenu.Add(new Separator()); + contextMenu.Add(new CommandContextItem(installedAppByProductCode.Command)); + foreach (var item in installedAppByProductCode.MoreCommands) + { + contextMenu.Add(item); + } + + return; + } + } + } + } + catch (Exception ex) + { + Logger.LogError($"Failed to retrieve app context menu items for package '{_package?.Name ?? "Unknown"}'", ex); } - - // didn't find the app - _installCommand = new InstallPackageCommand(_package, installedState); - this.Command = _installCommand; - - Icon = _installCommand.Icon; - _installCommand.InstallStateChanged += InstallStateChangedHandler; } private void InstallStateChangedHandler(object? sender, InstallPackageCommand e) diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WinGetExtensionCommandsProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WinGetExtensionCommandsProvider.cs index 14c7ec0831..a2608ef8a8 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WinGetExtensionCommandsProvider.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WinGetExtensionCommandsProvider.cs @@ -41,5 +41,9 @@ public partial class WinGetExtensionCommandsProvider : CommandProvider public override void InitializeWithHost(IExtensionHost host) => WinGetExtensionHost.Instance.Initialize(host); - public void SetAllLookup(Func callback) => WinGetStatics.AppSearchCallback = callback; + public void SetAllLookup(Func lookupByPackageName, Func lookupByProductCode) + { + WinGetStatics.AppSearchByPackageFamilyNameCallback = lookupByPackageName; + WinGetStatics.AppSearchByProductCodeCallback = lookupByProductCode; + } } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WinGetStatics.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WinGetStatics.cs index da591c566c..001ba5539d 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WinGetStatics.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WinGetStatics.cs @@ -34,7 +34,9 @@ internal static class WinGetStatics private static readonly StatusMessage _errorMessage = new() { State = MessageState.Error }; - public static Func? AppSearchCallback { get; set; } + public static Func? AppSearchByPackageFamilyNameCallback { get; set; } + + public static Func? AppSearchByProductCodeCallback { get; set; } private static readonly CompositeFormat CreateCatalogErrorMessage = System.Text.CompositeFormat.Parse(Properties.Resources.winget_create_catalog_error); diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/FuzzyStringMatcher.cs b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/FuzzyStringMatcher.cs index f4591bc443..7ecfc74222 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/FuzzyStringMatcher.cs +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/FuzzyStringMatcher.cs @@ -2,6 +2,10 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Globalization; + +using ToolGood.Words.Pinyin; + namespace Microsoft.CommandPalette.Extensions.Toolkit; // Inspired by the fuzzy.rs from edit.exe @@ -9,6 +13,21 @@ public static class FuzzyStringMatcher { private const int NOMATCH = 0; + /// + /// Gets a value indicating whether to support Chinese PinYin. + /// Automatically enabled when the system UI culture is Simplified Chinese. + /// + public static bool ChinesePinYinSupport { get; } = IsSimplifiedChinese(); + + private static bool IsSimplifiedChinese() + { + var culture = CultureInfo.CurrentUICulture; + + // Detect Simplified Chinese: zh-CN, zh-Hans, zh-Hans-* + return culture.Name.StartsWith("zh-CN", StringComparison.OrdinalIgnoreCase) + || culture.Name.StartsWith("zh-Hans", StringComparison.OrdinalIgnoreCase); + } + public static int ScoreFuzzy(string needle, string haystack, bool allowNonContiguousMatches = true) { var (s, _) = ScoreFuzzyWithPositions(needle, haystack, allowNonContiguousMatches); @@ -16,6 +35,28 @@ public static class FuzzyStringMatcher } public static (int Score, List Positions) ScoreFuzzyWithPositions(string needle, string haystack, bool allowNonContiguousMatches) + => ScoreAllFuzzyWithPositions(needle, haystack, allowNonContiguousMatches).MaxBy(i => i.Score); + + public static IEnumerable<(int Score, List Positions)> ScoreAllFuzzyWithPositions(string needle, string haystack, bool allowNonContiguousMatches) + { + List needles = [needle]; + List haystacks = [haystack]; + + if (ChinesePinYinSupport) + { + // Remove IME composition split characters. + var input = needle.Replace("'", string.Empty); + needles.Add(WordsHelper.GetPinyin(input)); + if (WordsHelper.HasChinese(haystack)) + { + haystacks.Add(WordsHelper.GetPinyin(haystack)); + } + } + + return needles.SelectMany(i => haystacks.Select(j => ScoreFuzzyWithPositionsInternal(i, j, allowNonContiguousMatches))); + } + + private static (int Score, List Positions) ScoreFuzzyWithPositionsInternal(string needle, string haystack, bool allowNonContiguousMatches) { if (string.IsNullOrEmpty(haystack) || string.IsNullOrEmpty(needle)) { diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/Microsoft.CommandPalette.Extensions.Toolkit.csproj b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/Microsoft.CommandPalette.Extensions.Toolkit.csproj index f5f8f2ccbc..eb887e9e36 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/Microsoft.CommandPalette.Extensions.Toolkit.csproj +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/Microsoft.CommandPalette.Extensions.Toolkit.csproj @@ -42,6 +42,7 @@ runtime; build; native; contentfiles; analyzers + diff --git a/src/modules/cmdpal/extensionsdk/nuget/BuildSDKHelper.ps1 b/src/modules/cmdpal/extensionsdk/nuget/BuildSDKHelper.ps1 index 8270e7bb4a..4390f0120e 100644 --- a/src/modules/cmdpal/extensionsdk/nuget/BuildSDKHelper.ps1 +++ b/src/modules/cmdpal/extensionsdk/nuget/BuildSDKHelper.ps1 @@ -56,7 +56,7 @@ if ($IsAzurePipelineBuild) { } if (($BuildStep -ieq "all") -Or ($BuildStep -ieq "build")) { - & $nugetPath restore (Join-Path $PSScriptRoot "..\..\..\..\..\PowerToys.sln") + & $nugetPath restore (Join-Path $PSScriptRoot "..\..\..\..\..\PowerToys.slnx") Try { foreach ($config in $Configuration.Split(",")) { diff --git a/src/modules/colorPicker/ColorPickerUI/Settings/UserSettings.cs b/src/modules/colorPicker/ColorPickerUI/Settings/UserSettings.cs index e15a792259..dfb5551a87 100644 --- a/src/modules/colorPicker/ColorPickerUI/Settings/UserSettings.cs +++ b/src/modules/colorPicker/ColorPickerUI/Settings/UserSettings.cs @@ -45,7 +45,7 @@ namespace ColorPicker.Settings [ImportingConstructor] public UserSettings(Helpers.IThrottledActionInvoker throttledActionInvoker) { - _settingsUtils = new SettingsUtils(); + _settingsUtils = SettingsUtils.Default; ChangeCursor = new SettingItem(true); ActivationShortcut = new SettingItem(DefaultActivationShortcut); CopiedColorRepresentation = new SettingItem(ColorRepresentationType.HEX.ToString()); diff --git a/src/modules/fancyzones/FancyZonesCLI/Commands/EditorCommands.cs b/src/modules/fancyzones/FancyZonesCLI/Commands/EditorCommands.cs new file mode 100644 index 0000000000..7bf15dda44 --- /dev/null +++ b/src/modules/fancyzones/FancyZonesCLI/Commands/EditorCommands.cs @@ -0,0 +1,90 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; + +namespace FancyZonesCLI.Commands; + +/// +/// Editor and Settings commands. +/// +internal static class EditorCommands +{ + public static (int ExitCode, string Output) OpenEditor() + { + var editorExe = "PowerToys.FancyZonesEditor.exe"; + + // Check if editor-parameters.json exists + if (!FancyZonesData.EditorParametersExist()) + { + return (1, "Error: editor-parameters.json not found.\nPlease launch FancyZones Editor using Win+` (Win+Backtick) hotkey first."); + } + + // Check if editor is already running + var existingProcess = Process.GetProcessesByName("PowerToys.FancyZonesEditor").FirstOrDefault(); + if (existingProcess != null) + { + NativeMethods.SetForegroundWindow(existingProcess.MainWindowHandle); + return (0, "FancyZones Editor is already running. Brought window to foreground."); + } + + // Only check same directory as CLI + var editorPath = Path.Combine(AppContext.BaseDirectory, editorExe); + + if (File.Exists(editorPath)) + { + try + { + Process.Start(new ProcessStartInfo + { + FileName = editorPath, + UseShellExecute = true, + }); + return (0, "FancyZones Editor launched successfully."); + } + catch (Exception ex) + { + return (1, $"Failed to launch: {ex.Message}"); + } + } + + return (1, $"Error: Could not find {editorExe} in {AppContext.BaseDirectory}"); + } + + public static (int ExitCode, string Output) OpenSettings() + { + try + { + // Find PowerToys.exe in common locations + string powertoysExe = null; + + // Check in the same directory as the CLI (typical for dev builds) + var sameDirPath = Path.Combine(AppContext.BaseDirectory, "PowerToys.exe"); + if (File.Exists(sameDirPath)) + { + powertoysExe = sameDirPath; + } + + if (powertoysExe == null) + { + return (1, "Error: PowerToys.exe not found. Please ensure PowerToys is installed."); + } + + Process.Start(new ProcessStartInfo + { + FileName = powertoysExe, + Arguments = "--open-settings=FancyZones", + UseShellExecute = false, + }); + return (0, "FancyZones Settings opened successfully."); + } + catch (Exception ex) + { + return (1, $"Error: Failed to open FancyZones Settings. {ex.Message}"); + } + } +} diff --git a/src/modules/fancyzones/FancyZonesCLI/Commands/HotkeyCommands.cs b/src/modules/fancyzones/FancyZonesCLI/Commands/HotkeyCommands.cs new file mode 100644 index 0000000000..cfaf93a5d4 --- /dev/null +++ b/src/modules/fancyzones/FancyZonesCLI/Commands/HotkeyCommands.cs @@ -0,0 +1,98 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; + +namespace FancyZonesCLI.Commands; + +/// +/// Hotkey-related commands. +/// +internal static class HotkeyCommands +{ + public static (int ExitCode, string Output) GetHotkeys() + { + var hotkeys = FancyZonesData.ReadLayoutHotkeys(); + if (hotkeys?.Hotkeys == null || hotkeys.Hotkeys.Count == 0) + { + return (0, "No hotkeys configured."); + } + + var sb = new System.Text.StringBuilder(); + sb.AppendLine("=== Layout Hotkeys ===\n"); + sb.AppendLine("Press Win + Ctrl + Alt + to switch layouts:\n"); + + foreach (var hotkey in hotkeys.Hotkeys.OrderBy(h => h.Key)) + { + sb.AppendLine(CultureInfo.InvariantCulture, $" [{hotkey.Key}] => {hotkey.LayoutId}"); + } + + return (0, sb.ToString().TrimEnd()); + } + + public static (int ExitCode, string Output) SetHotkey(int key, string layoutUuid, Action notifyFancyZones, uint wmPrivLayoutHotkeysFileUpdate) + { + if (key < 0 || key > 9) + { + return (1, "Error: Key must be between 0 and 9"); + } + + // Check if this is a custom layout UUID + var customLayouts = FancyZonesData.ReadCustomLayouts(); + var matchedLayout = customLayouts?.Layouts?.FirstOrDefault(l => l.Uuid.Equals(layoutUuid, StringComparison.OrdinalIgnoreCase)); + bool isCustomLayout = matchedLayout != null; + string layoutName = matchedLayout?.Name ?? layoutUuid; + + var hotkeys = FancyZonesData.ReadLayoutHotkeys() ?? new LayoutHotkeys(); + + hotkeys.Hotkeys ??= new List(); + + // Remove existing hotkey for this key + hotkeys.Hotkeys.RemoveAll(h => h.Key == key); + + // Add new hotkey + hotkeys.Hotkeys.Add(new LayoutHotkey { Key = key, LayoutId = layoutUuid }); + + // Save + FancyZonesData.WriteLayoutHotkeys(hotkeys); + + // Notify FancyZones + notifyFancyZones(wmPrivLayoutHotkeysFileUpdate); + + if (isCustomLayout) + { + return (0, $"✓ Hotkey {key} assigned to custom layout '{layoutName}'\n Press Win + Ctrl + Alt + {key} to switch to this layout"); + } + else + { + return (0, $"⚠ Warning: Hotkey {key} assigned to '{layoutUuid}'\n Note: FancyZones hotkeys only work with CUSTOM layouts.\n Template layouts (focus, columns, rows, etc.) cannot be used with hotkeys.\n Create a custom layout in the FancyZones Editor to use this hotkey."); + } + } + + public static (int ExitCode, string Output) RemoveHotkey(int key, Action notifyFancyZones, uint wmPrivLayoutHotkeysFileUpdate) + { + var hotkeys = FancyZonesData.ReadLayoutHotkeys(); + if (hotkeys?.Hotkeys == null) + { + return (0, $"No hotkey assigned to key {key}"); + } + + var removed = hotkeys.Hotkeys.RemoveAll(h => h.Key == key); + if (removed == 0) + { + return (0, $"No hotkey assigned to key {key}"); + } + + // Save + FancyZonesData.WriteLayoutHotkeys(hotkeys); + + // Notify FancyZones + notifyFancyZones(wmPrivLayoutHotkeysFileUpdate); + + return (0, $"Hotkey {key} removed"); + } +} diff --git a/src/modules/fancyzones/FancyZonesCLI/Commands/LayoutCommands.cs b/src/modules/fancyzones/FancyZonesCLI/Commands/LayoutCommands.cs new file mode 100644 index 0000000000..4400b32d46 --- /dev/null +++ b/src/modules/fancyzones/FancyZonesCLI/Commands/LayoutCommands.cs @@ -0,0 +1,276 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text.Json; + +namespace FancyZonesCLI.Commands; + +/// +/// Layout-related commands. +/// +internal static class LayoutCommands +{ + public static (int ExitCode, string Output) GetLayouts() + { + var sb = new System.Text.StringBuilder(); + + // Print template layouts + var templatesJson = FancyZonesData.ReadLayoutTemplates(); + if (templatesJson?.Templates != null) + { + sb.AppendLine(CultureInfo.InvariantCulture, $"=== Built-in Template Layouts ({templatesJson.Templates.Count} total) ===\n"); + + for (int i = 0; i < templatesJson.Templates.Count; i++) + { + var template = templatesJson.Templates[i]; + sb.AppendLine(CultureInfo.InvariantCulture, $"[T{i + 1}] {template.Type}"); + sb.Append(CultureInfo.InvariantCulture, $" Zones: {template.ZoneCount}"); + if (template.ShowSpacing && template.Spacing > 0) + { + sb.Append(CultureInfo.InvariantCulture, $", Spacing: {template.Spacing}px"); + } + + sb.AppendLine(); + sb.AppendLine(); + + // Draw visual preview + sb.Append(LayoutVisualizer.DrawTemplateLayout(template)); + + if (i < templatesJson.Templates.Count - 1) + { + sb.AppendLine(); + } + } + + sb.AppendLine("\n"); + } + + // Print custom layouts + var customLayouts = FancyZonesData.ReadCustomLayouts(); + if (customLayouts?.Layouts != null) + { + sb.AppendLine(CultureInfo.InvariantCulture, $"=== Custom Layouts ({customLayouts.Layouts.Count} total) ==="); + + for (int i = 0; i < customLayouts.Layouts.Count; i++) + { + var layout = customLayouts.Layouts[i]; + sb.AppendLine(CultureInfo.InvariantCulture, $"[{i + 1}] {layout.Name}"); + sb.AppendLine(CultureInfo.InvariantCulture, $" UUID: {layout.Uuid}"); + sb.Append(CultureInfo.InvariantCulture, $" Type: {layout.Type}"); + + bool isCanvasLayout = false; + if (layout.Info.ValueKind != JsonValueKind.Undefined && layout.Info.ValueKind != JsonValueKind.Null) + { + if (layout.Type == "grid" && layout.Info.TryGetProperty("rows", out var rows) && layout.Info.TryGetProperty("columns", out var cols)) + { + sb.Append(CultureInfo.InvariantCulture, $" ({rows.GetInt32()}x{cols.GetInt32()} grid)"); + } + else if (layout.Type == "canvas" && layout.Info.TryGetProperty("zones", out var zones)) + { + sb.Append(CultureInfo.InvariantCulture, $" ({zones.GetArrayLength()} zones)"); + isCanvasLayout = true; + } + } + + sb.AppendLine("\n"); + + // Draw visual preview + sb.Append(LayoutVisualizer.DrawCustomLayout(layout)); + + // Add note for canvas layouts + if (isCanvasLayout) + { + sb.AppendLine("\n Note: Canvas layout preview is approximate."); + sb.AppendLine(" Open FancyZones Editor for precise zone boundaries."); + } + + if (i < customLayouts.Layouts.Count - 1) + { + sb.AppendLine(); + } + } + + sb.AppendLine("\nUse 'FancyZonesCLI.exe set-layout ' to apply a layout."); + } + + return (0, sb.ToString().TrimEnd()); + } + + public static (int ExitCode, string Output) GetActiveLayout() + { + if (!FancyZonesData.TryReadAppliedLayouts(out var appliedLayouts, out var error)) + { + return (1, $"Error: {error}"); + } + + if (appliedLayouts.Layouts == null || appliedLayouts.Layouts.Count == 0) + { + return (0, "No active layouts found."); + } + + var sb = new System.Text.StringBuilder(); + sb.AppendLine("\n=== Active FancyZones Layout(s) ===\n"); + + for (int i = 0; i < appliedLayouts.Layouts.Count; i++) + { + var layout = appliedLayouts.Layouts[i]; + sb.AppendLine(CultureInfo.InvariantCulture, $"Monitor {i + 1}:"); + sb.AppendLine(CultureInfo.InvariantCulture, $" Name: {layout.AppliedLayout.Type}"); + sb.AppendLine(CultureInfo.InvariantCulture, $" UUID: {layout.AppliedLayout.Uuid}"); + sb.AppendLine(CultureInfo.InvariantCulture, $" Type: {layout.AppliedLayout.Type} ({layout.AppliedLayout.ZoneCount} zones)"); + + if (layout.AppliedLayout.ShowSpacing) + { + sb.AppendLine(CultureInfo.InvariantCulture, $" Spacing: {layout.AppliedLayout.Spacing}px"); + } + + sb.AppendLine(CultureInfo.InvariantCulture, $" Sensitivity Radius: {layout.AppliedLayout.SensitivityRadius}px"); + + if (i < appliedLayouts.Layouts.Count - 1) + { + sb.AppendLine(); + } + } + + return (0, sb.ToString().TrimEnd()); + } + + public static (int ExitCode, string Output) SetLayout(string[] args, Action notifyFancyZones, uint wmPrivAppliedLayoutsFileUpdate) + { + Logger.LogInfo($"SetLayout called with args: [{string.Join(", ", args)}]"); + + if (args.Length == 0) + { + return (1, "Error: set-layout requires a UUID parameter"); + } + + string uuid = args[0]; + int? targetMonitor = null; + bool applyToAll = false; + + // Parse options + for (int i = 1; i < args.Length; i++) + { + if (args[i] == "--monitor" && i + 1 < args.Length) + { + if (int.TryParse(args[i + 1], out int monitorNum)) + { + targetMonitor = monitorNum; + i++; // Skip next arg + } + else + { + return (1, $"Error: Invalid monitor number: {args[i + 1]}"); + } + } + else if (args[i] == "--all") + { + applyToAll = true; + } + } + + if (targetMonitor.HasValue && applyToAll) + { + return (1, "Error: Cannot specify both --monitor and --all"); + } + + // Try to find layout in custom layouts first (by UUID) + var customLayouts = FancyZonesData.ReadCustomLayouts(); + var targetCustomLayout = customLayouts?.Layouts?.FirstOrDefault(l => l.Uuid.Equals(uuid, StringComparison.OrdinalIgnoreCase)); + + // If not found in custom layouts, try template layouts (by type name) + TemplateLayout targetTemplate = null; + if (targetCustomLayout == null) + { + var templates = FancyZonesData.ReadLayoutTemplates(); + targetTemplate = templates?.Templates?.FirstOrDefault(t => t.Type.Equals(uuid, StringComparison.OrdinalIgnoreCase)); + } + + if (targetCustomLayout == null && targetTemplate == null) + { + return (1, $"Error: Layout '{uuid}' not found\nTip: For templates, use the type name (e.g., 'focus', 'columns', 'rows', 'grid', 'priority-grid')\n For custom layouts, use the UUID from 'get-layouts'"); + } + + // Read current applied layouts + if (!FancyZonesData.TryReadAppliedLayouts(out var appliedLayouts, out var error)) + { + return (1, $"Error: {error}"); + } + + if (appliedLayouts.Layouts == null || appliedLayouts.Layouts.Count == 0) + { + return (1, "Error: No monitors configured"); + } + + // Determine which monitors to update + List monitorsToUpdate = new List(); + if (applyToAll) + { + for (int i = 0; i < appliedLayouts.Layouts.Count; i++) + { + monitorsToUpdate.Add(i); + } + } + else if (targetMonitor.HasValue) + { + int monitorIndex = targetMonitor.Value - 1; // Convert to 0-based + if (monitorIndex < 0 || monitorIndex >= appliedLayouts.Layouts.Count) + { + return (1, $"Error: Monitor {targetMonitor.Value} not found. Available monitors: 1-{appliedLayouts.Layouts.Count}"); + } + + monitorsToUpdate.Add(monitorIndex); + } + else + { + // Default: first monitor + monitorsToUpdate.Add(0); + } + + // Update selected monitors + foreach (int monitorIndex in monitorsToUpdate) + { + if (targetCustomLayout != null) + { + appliedLayouts.Layouts[monitorIndex].AppliedLayout.Uuid = targetCustomLayout.Uuid; + appliedLayouts.Layouts[monitorIndex].AppliedLayout.Type = targetCustomLayout.Type; + } + else if (targetTemplate != null) + { + // For templates, use all-zeros UUID and the template type + appliedLayouts.Layouts[monitorIndex].AppliedLayout.Uuid = "{00000000-0000-0000-0000-000000000000}"; + appliedLayouts.Layouts[monitorIndex].AppliedLayout.Type = targetTemplate.Type; + appliedLayouts.Layouts[monitorIndex].AppliedLayout.ZoneCount = targetTemplate.ZoneCount; + appliedLayouts.Layouts[monitorIndex].AppliedLayout.ShowSpacing = targetTemplate.ShowSpacing; + appliedLayouts.Layouts[monitorIndex].AppliedLayout.Spacing = targetTemplate.Spacing; + } + } + + // Write back to file + FancyZonesData.WriteAppliedLayouts(appliedLayouts); + Logger.LogInfo($"Applied layouts file updated for {monitorsToUpdate.Count} monitor(s)"); + + // Notify FancyZones to reload + notifyFancyZones(wmPrivAppliedLayoutsFileUpdate); + Logger.LogInfo("FancyZones notified of layout change"); + + string layoutName = targetCustomLayout?.Name ?? targetTemplate?.Type ?? uuid; + if (applyToAll) + { + return (0, $"Layout '{layoutName}' applied to all {monitorsToUpdate.Count} monitors"); + } + else if (targetMonitor.HasValue) + { + return (0, $"Layout '{layoutName}' applied to monitor {targetMonitor.Value}"); + } + else + { + return (0, $"Layout '{layoutName}' applied to monitor 1"); + } + } +} diff --git a/src/modules/fancyzones/FancyZonesCLI/Commands/MonitorCommands.cs b/src/modules/fancyzones/FancyZonesCLI/Commands/MonitorCommands.cs new file mode 100644 index 0000000000..f542b901cc --- /dev/null +++ b/src/modules/fancyzones/FancyZonesCLI/Commands/MonitorCommands.cs @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Globalization; + +namespace FancyZonesCLI.Commands; + +/// +/// Monitor-related commands. +/// +internal static class MonitorCommands +{ + public static (int ExitCode, string Output) GetMonitors() + { + if (!FancyZonesData.TryReadAppliedLayouts(out var appliedLayouts, out var error)) + { + return (1, $"Error: {error}"); + } + + if (appliedLayouts.Layouts == null || appliedLayouts.Layouts.Count == 0) + { + return (0, "No monitors found."); + } + + var sb = new System.Text.StringBuilder(); + sb.AppendLine(CultureInfo.InvariantCulture, $"=== Monitors ({appliedLayouts.Layouts.Count} total) ==="); + sb.AppendLine(); + + for (int i = 0; i < appliedLayouts.Layouts.Count; i++) + { + var layout = appliedLayouts.Layouts[i]; + var monitorNum = i + 1; + + sb.AppendLine(CultureInfo.InvariantCulture, $"Monitor {monitorNum}:"); + sb.AppendLine(CultureInfo.InvariantCulture, $" Monitor: {layout.Device.Monitor}"); + sb.AppendLine(CultureInfo.InvariantCulture, $" Monitor Instance: {layout.Device.MonitorInstance}"); + sb.AppendLine(CultureInfo.InvariantCulture, $" Monitor Number: {layout.Device.MonitorNumber}"); + sb.AppendLine(CultureInfo.InvariantCulture, $" Serial Number: {layout.Device.SerialNumber}"); + sb.AppendLine(CultureInfo.InvariantCulture, $" Virtual Desktop: {layout.Device.VirtualDesktop}"); + sb.AppendLine(CultureInfo.InvariantCulture, $" Sensitivity Radius: {layout.AppliedLayout.SensitivityRadius}px"); + sb.AppendLine(CultureInfo.InvariantCulture, $" Active Layout: {layout.AppliedLayout.Type}"); + sb.AppendLine(CultureInfo.InvariantCulture, $" Zone Count: {layout.AppliedLayout.ZoneCount}"); + sb.AppendLine(); + } + + return (0, sb.ToString().TrimEnd()); + } +} diff --git a/src/modules/fancyzones/FancyZonesCLI/FancyZonesCLI.csproj b/src/modules/fancyzones/FancyZonesCLI/FancyZonesCLI.csproj new file mode 100644 index 0000000000..85c2fa30e5 --- /dev/null +++ b/src/modules/fancyzones/FancyZonesCLI/FancyZonesCLI.csproj @@ -0,0 +1,32 @@ + + + + + + + + PowerToys.FancyZonesCLI + PowerToys FancyZones Command Line Interface + PowerToys FancyZones CLI + Exe + x64;ARM64 + true + true + false + false + ..\..\..\..\$(Platform)\$(Configuration) + FancyZonesCLI + $(NoWarn);SA1500;SA1402;CA1852 + + + + + + + + + + + + + diff --git a/src/modules/fancyzones/FancyZonesCLI/FancyZonesData.cs b/src/modules/fancyzones/FancyZonesCLI/FancyZonesData.cs new file mode 100644 index 0000000000..2396c51f44 --- /dev/null +++ b/src/modules/fancyzones/FancyZonesCLI/FancyZonesData.cs @@ -0,0 +1,142 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.IO; +using System.Text.Json; +using System.Text.Json.Serialization.Metadata; + +namespace FancyZonesCLI; + +/// +/// Provides methods to read and write FancyZones configuration data. +/// +internal static class FancyZonesData +{ + /// + /// Try to read applied layouts configuration. + /// + public static bool TryReadAppliedLayouts(out AppliedLayouts result, out string error) + { + return TryReadJsonFile(FancyZonesPaths.AppliedLayouts, FancyZonesJsonContext.Default.AppliedLayouts, out result, out error); + } + + /// + /// Read applied layouts or return null if not found. + /// + public static AppliedLayouts ReadAppliedLayouts() + { + return ReadJsonFileOrDefault(FancyZonesPaths.AppliedLayouts, FancyZonesJsonContext.Default.AppliedLayouts); + } + + /// + /// Write applied layouts configuration. + /// + public static void WriteAppliedLayouts(AppliedLayouts layouts) + { + WriteJsonFile(FancyZonesPaths.AppliedLayouts, layouts, FancyZonesJsonContext.Default.AppliedLayouts); + } + + /// + /// Read custom layouts or return null if not found. + /// + public static CustomLayouts ReadCustomLayouts() + { + return ReadJsonFileOrDefault(FancyZonesPaths.CustomLayouts, FancyZonesJsonContext.Default.CustomLayouts); + } + + /// + /// Read layout templates or return null if not found. + /// + public static LayoutTemplates ReadLayoutTemplates() + { + return ReadJsonFileOrDefault(FancyZonesPaths.LayoutTemplates, FancyZonesJsonContext.Default.LayoutTemplates); + } + + /// + /// Read layout hotkeys or return null if not found. + /// + public static LayoutHotkeys ReadLayoutHotkeys() + { + return ReadJsonFileOrDefault(FancyZonesPaths.LayoutHotkeys, FancyZonesJsonContext.Default.LayoutHotkeys); + } + + /// + /// Write layout hotkeys configuration. + /// + public static void WriteLayoutHotkeys(LayoutHotkeys hotkeys) + { + WriteJsonFile(FancyZonesPaths.LayoutHotkeys, hotkeys, FancyZonesJsonContext.Default.LayoutHotkeys); + } + + /// + /// Check if editor parameters file exists. + /// + public static bool EditorParametersExist() + { + return File.Exists(FancyZonesPaths.EditorParameters); + } + + private static bool TryReadJsonFile(string filePath, JsonTypeInfo jsonTypeInfo, out T result, out string error) + where T : class + { + result = null; + error = null; + + Logger.LogDebug($"Reading file: {filePath}"); + + if (!File.Exists(filePath)) + { + error = $"File not found: {Path.GetFileName(filePath)}"; + Logger.LogWarning(error); + return false; + } + + try + { + var json = File.ReadAllText(filePath); + result = JsonSerializer.Deserialize(json, jsonTypeInfo); + if (result == null) + { + error = $"Failed to parse {Path.GetFileName(filePath)}"; + Logger.LogError(error); + return false; + } + + Logger.LogDebug($"Successfully read {Path.GetFileName(filePath)}"); + return true; + } + catch (JsonException ex) + { + error = $"JSON parse error in {Path.GetFileName(filePath)}: {ex.Message}"; + Logger.LogError(error, ex); + return false; + } + catch (IOException ex) + { + error = $"Failed to read {Path.GetFileName(filePath)}: {ex.Message}"; + Logger.LogError(error, ex); + return false; + } + } + + private static T ReadJsonFileOrDefault(string filePath, JsonTypeInfo jsonTypeInfo, T defaultValue = null) + where T : class + { + if (TryReadJsonFile(filePath, jsonTypeInfo, out var result, out _)) + { + return result; + } + + return defaultValue; + } + + private static void WriteJsonFile(string filePath, T data, JsonTypeInfo jsonTypeInfo) + { + Logger.LogDebug($"Writing file: {filePath}"); + var json = JsonSerializer.Serialize(data, jsonTypeInfo); + File.WriteAllText(filePath, json); + Logger.LogInfo($"Successfully wrote {Path.GetFileName(filePath)}"); + } +} diff --git a/src/modules/fancyzones/FancyZonesCLI/FancyZonesPaths.cs b/src/modules/fancyzones/FancyZonesCLI/FancyZonesPaths.cs new file mode 100644 index 0000000000..f04d375392 --- /dev/null +++ b/src/modules/fancyzones/FancyZonesCLI/FancyZonesPaths.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.IO; + +namespace FancyZonesCLI; + +/// +/// Provides paths to FancyZones configuration files. +/// +internal static class FancyZonesPaths +{ + private static readonly string DataPath = Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + "Microsoft", + "PowerToys", + "FancyZones"); + + public static string AppliedLayouts => Path.Combine(DataPath, "applied-layouts.json"); + + public static string CustomLayouts => Path.Combine(DataPath, "custom-layouts.json"); + + public static string LayoutTemplates => Path.Combine(DataPath, "layout-templates.json"); + + public static string LayoutHotkeys => Path.Combine(DataPath, "layout-hotkeys.json"); + + public static string EditorParameters => Path.Combine(DataPath, "editor-parameters.json"); +} diff --git a/src/modules/fancyzones/FancyZonesCLI/LayoutVisualizer.cs b/src/modules/fancyzones/FancyZonesCLI/LayoutVisualizer.cs new file mode 100644 index 0000000000..fecdf33dbe --- /dev/null +++ b/src/modules/fancyzones/FancyZonesCLI/LayoutVisualizer.cs @@ -0,0 +1,550 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; +using System.Text.Json; + +namespace FancyZonesCLI; + +public static class LayoutVisualizer +{ + public static string DrawTemplateLayout(TemplateLayout template) + { + var sb = new StringBuilder(); + sb.AppendLine(" Visual Preview:"); + + switch (template.Type.ToLowerInvariant()) + { + case "focus": + sb.Append(RenderFocusLayout(template.ZoneCount > 0 ? template.ZoneCount : 3)); + break; + case "columns": + sb.Append(RenderGridLayout(1, template.ZoneCount > 0 ? template.ZoneCount : 3)); + break; + case "rows": + sb.Append(RenderGridLayout(template.ZoneCount > 0 ? template.ZoneCount : 3, 1)); + break; + case "grid": + // Grid layout: calculate rows and columns from zone count + // Algorithm from GridLayoutModel.InitGrid() - tries to make it close to square + // with cols >= rows preference + int zoneCount = template.ZoneCount > 0 ? template.ZoneCount : 3; + int rows = 1; + while (zoneCount / rows >= rows) + { + rows++; + } + + rows--; + int cols = zoneCount / rows; + if (zoneCount % rows != 0) + { + cols++; + } + + sb.Append(RenderGridLayoutWithZoneCount(rows, cols, zoneCount)); + break; + case "priority-grid": + sb.Append(RenderPriorityGridLayout(template.ZoneCount > 0 ? template.ZoneCount : 3)); + break; + case "blank": + sb.AppendLine(" (No zones)"); + break; + default: + sb.AppendLine(CultureInfo.InvariantCulture, $" ({template.Type} layout)"); + break; + } + + return sb.ToString(); + } + + public static string DrawCustomLayout(CustomLayout layout) + { + if (layout.Info.ValueKind == JsonValueKind.Undefined || layout.Info.ValueKind == JsonValueKind.Null) + { + return string.Empty; + } + + var sb = new StringBuilder(); + sb.AppendLine(" Visual Preview:"); + + if (layout.Type == "grid" && + layout.Info.TryGetProperty("rows", out var rows) && + layout.Info.TryGetProperty("columns", out var cols)) + { + int r = rows.GetInt32(); + int c = cols.GetInt32(); + + // Check if there's a cell-child-map (merged cells) + if (layout.Info.TryGetProperty("cell-child-map", out var cellMap)) + { + sb.Append(RenderGridLayoutWithMergedCells(r, c, cellMap)); + } + else + { + int height = r >= 4 ? 12 : 8; + sb.Append(RenderGridLayout(r, c, 30, height)); + } + } + else if (layout.Type == "canvas" && + layout.Info.TryGetProperty("zones", out var zones) && + layout.Info.TryGetProperty("ref-width", out var refWidth) && + layout.Info.TryGetProperty("ref-height", out var refHeight)) + { + sb.Append(RenderCanvasLayout(zones, refWidth.GetInt32(), refHeight.GetInt32())); + } + + return sb.ToString(); + } + + private static string RenderFocusLayout(int zoneCount = 3) + { + var sb = new StringBuilder(); + + // Focus layout: overlapping zones with cascading offset + if (zoneCount == 1) + { + sb.AppendLine(" +-------+"); + sb.AppendLine(" | |"); + sb.AppendLine(" | |"); + sb.AppendLine(" +-------+"); + } + else if (zoneCount == 2) + { + sb.AppendLine(" +-------+"); + sb.AppendLine(" | |"); + sb.AppendLine(" | +-------+"); + sb.AppendLine(" +-| |"); + sb.AppendLine(" | |"); + sb.AppendLine(" +-------+"); + } + else + { + sb.AppendLine(" +-------+"); + sb.AppendLine(" | |"); + sb.AppendLine(" | +-------+"); + sb.AppendLine(" +-| |"); + sb.AppendLine(" | +-------+"); + sb.AppendLine(" +-| |"); + sb.AppendLine(" ..."); + sb.AppendLine(CultureInfo.InvariantCulture, $" (total: {zoneCount} zones)"); + sb.AppendLine(" ..."); + sb.AppendLine(" | +-------+"); + sb.AppendLine(" +-| |"); + sb.AppendLine(" | |"); + sb.AppendLine(" +-------+"); + } + + return sb.ToString(); + } + + private static string RenderPriorityGridLayout(int zoneCount = 3) + { + // Priority Grid has predefined layouts for zone counts 1-11 + // Data format from GridLayoutModel._priorityData + if (zoneCount >= 1 && zoneCount <= 11) + { + int[,] cellMap = GetPriorityGridCellMap(zoneCount); + return RenderGridLayoutWithCellMap(cellMap); + } + else + { + // > 11 zones: use grid layout + int rows = 1; + while (zoneCount / rows >= rows) + { + rows++; + } + + rows--; + int cols = zoneCount / rows; + if (zoneCount % rows != 0) + { + cols++; + } + + return RenderGridLayoutWithZoneCount(rows, cols, zoneCount); + } + } + + private static int[,] GetPriorityGridCellMap(int zoneCount) + { + // Parsed from Editor's _priorityData byte arrays + return zoneCount switch + { + 1 => new int[,] { { 0 } }, + 2 => new int[,] { { 0, 1 } }, + 3 => new int[,] { { 0, 1, 2 } }, + 4 => new int[,] { { 0, 1, 2 }, { 0, 1, 3 } }, + 5 => new int[,] { { 0, 1, 2 }, { 3, 1, 4 } }, + 6 => new int[,] { { 0, 1, 2 }, { 0, 1, 3 }, { 4, 1, 5 } }, + 7 => new int[,] { { 0, 1, 2 }, { 3, 1, 4 }, { 5, 1, 6 } }, + 8 => new int[,] { { 0, 1, 2, 3 }, { 4, 1, 2, 5 }, { 6, 1, 2, 7 } }, + 9 => new int[,] { { 0, 1, 2, 3 }, { 4, 1, 2, 5 }, { 6, 1, 7, 8 } }, + 10 => new int[,] { { 0, 1, 2, 3 }, { 4, 1, 5, 6 }, { 7, 1, 8, 9 } }, + 11 => new int[,] { { 0, 1, 2, 3 }, { 4, 1, 5, 6 }, { 7, 8, 9, 10 } }, + _ => new int[,] { { 0 } }, + }; + } + + private static string RenderGridLayoutWithCellMap(int[,] cellMap, int width = 30, int height = 8) + { + var sb = new StringBuilder(); + int rows = cellMap.GetLength(0); + int cols = cellMap.GetLength(1); + + int cellWidth = width / cols; + int cellHeight = height / rows; + + for (int r = 0; r < rows; r++) + { + // Top border + sb.Append(" +"); + for (int c = 0; c < cols; c++) + { + bool mergeTop = r > 0 && cellMap[r, c] == cellMap[r - 1, c]; + bool mergeLeft = c > 0 && cellMap[r, c] == cellMap[r, c - 1]; + + if (mergeTop) + { + sb.Append(mergeLeft ? new string(' ', cellWidth) : new string(' ', cellWidth - 1) + "+"); + } + else + { + sb.Append(mergeLeft ? new string('-', cellWidth) : new string('-', cellWidth - 1) + "+"); + } + } + + sb.AppendLine(); + + // Cell content + for (int h = 0; h < cellHeight - 1; h++) + { + sb.Append(" "); + for (int c = 0; c < cols; c++) + { + bool mergeLeft = c > 0 && cellMap[r, c] == cellMap[r, c - 1]; + sb.Append(mergeLeft ? ' ' : '|'); + sb.Append(' ', cellWidth - 1); + } + + sb.AppendLine("|"); + } + } + + // Bottom border + sb.Append(" +"); + for (int c = 0; c < cols; c++) + { + sb.Append('-', cellWidth - 1); + sb.Append('+'); + } + + sb.AppendLine(); + return sb.ToString(); + } + + private static string RenderGridLayoutWithMergedCells(int rows, int cols, JsonElement cellMap) + { + var sb = new StringBuilder(); + const int displayWidth = 39; + const int displayHeight = 12; + + // Build zone map from cell-child-map + int[,] zoneMap = new int[rows, cols]; + for (int r = 0; r < rows; r++) + { + var rowArray = cellMap[r]; + for (int c = 0; c < cols; c++) + { + zoneMap[r, c] = rowArray[c].GetInt32(); + } + } + + int cellHeight = displayHeight / rows; + int cellWidth = displayWidth / cols; + + // Draw top border + sb.Append(" +"); + sb.Append('-', displayWidth); + sb.AppendLine("+"); + + // Draw rows + for (int r = 0; r < rows; r++) + { + for (int h = 0; h < cellHeight; h++) + { + sb.Append(" |"); + + for (int c = 0; c < cols; c++) + { + int currentZone = zoneMap[r, c]; + int leftZone = c > 0 ? zoneMap[r, c - 1] : -1; + bool needLeftBorder = c > 0 && currentZone != leftZone; + + bool zoneHasTopBorder = r > 0 && h == 0 && currentZone != zoneMap[r - 1, c]; + + if (needLeftBorder) + { + sb.Append('|'); + sb.Append(zoneHasTopBorder ? '-' : ' ', cellWidth - 1); + } + else + { + sb.Append(zoneHasTopBorder ? '-' : ' ', cellWidth); + } + } + + sb.AppendLine("|"); + } + } + + // Draw bottom border + sb.Append(" +"); + sb.Append('-', displayWidth); + sb.AppendLine("+"); + + return sb.ToString(); + } + + public static string RenderGridLayoutWithZoneCount(int rows, int cols, int zoneCount, int width = 30, int height = 8) + { + var sb = new StringBuilder(); + + // Build zone map like Editor's InitGrid + int[,] zoneMap = new int[rows, cols]; + int index = 0; + for (int r = 0; r < rows; r++) + { + for (int c = 0; c < cols; c++) + { + zoneMap[r, c] = index++; + if (index == zoneCount) + { + index--; // Remaining cells use the last zone index + } + } + } + + int cellWidth = width / cols; + int cellHeight = height / rows; + + for (int r = 0; r < rows; r++) + { + // Top border + sb.Append(" +"); + for (int c = 0; c < cols; c++) + { + bool mergeLeft = c > 0 && zoneMap[r, c] == zoneMap[r, c - 1]; + sb.Append('-', mergeLeft ? cellWidth : cellWidth - 1); + if (!mergeLeft) + { + sb.Append('+'); + } + } + + sb.AppendLine(); + + // Cell content + for (int h = 0; h < cellHeight - 1; h++) + { + sb.Append(" "); + for (int c = 0; c < cols; c++) + { + bool mergeLeft = c > 0 && zoneMap[r, c] == zoneMap[r, c - 1]; + sb.Append(mergeLeft ? ' ' : '|'); + sb.Append(' ', cellWidth - 1); + } + + sb.AppendLine("|"); + } + } + + // Bottom border + sb.Append(" +"); + for (int c = 0; c < cols; c++) + { + sb.Append('-', cellWidth - 1); + sb.Append('+'); + } + + sb.AppendLine(); + return sb.ToString(); + } + + public static string RenderGridLayout(int rows, int cols, int width = 30, int height = 8) + { + var sb = new StringBuilder(); + int cellWidth = width / cols; + int cellHeight = height / rows; + + for (int r = 0; r < rows; r++) + { + // Top border + sb.Append(" +"); + for (int c = 0; c < cols; c++) + { + sb.Append('-', cellWidth - 1); + sb.Append('+'); + } + + sb.AppendLine(); + + // Cell content + for (int h = 0; h < cellHeight - 1; h++) + { + sb.Append(" "); + for (int c = 0; c < cols; c++) + { + sb.Append('|'); + sb.Append(' ', cellWidth - 1); + } + + sb.AppendLine("|"); + } + } + + // Bottom border + sb.Append(" +"); + for (int c = 0; c < cols; c++) + { + sb.Append('-', cellWidth - 1); + sb.Append('+'); + } + + sb.AppendLine(); + return sb.ToString(); + } + + private static string RenderCanvasLayout(JsonElement zones, int refWidth, int refHeight) + { + var sb = new StringBuilder(); + const int displayWidth = 49; + const int displayHeight = 15; + + // Create a 2D array to track which zones occupy each position + var zoneGrid = new List[displayHeight, displayWidth]; + for (int i = 0; i < displayHeight; i++) + { + for (int j = 0; j < displayWidth; j++) + { + zoneGrid[i, j] = new List(); + } + } + + // Map each zone to the grid + int zoneId = 0; + var zoneList = new List<(int X, int Y, int Width, int Height, int Id)>(); + + foreach (var zone in zones.EnumerateArray()) + { + int x = zone.GetProperty("X").GetInt32(); + int y = zone.GetProperty("Y").GetInt32(); + int w = zone.GetProperty("width").GetInt32(); + int h = zone.GetProperty("height").GetInt32(); + + int dx = Math.Max(0, Math.Min(displayWidth - 1, x * displayWidth / refWidth)); + int dy = Math.Max(0, Math.Min(displayHeight - 1, y * displayHeight / refHeight)); + int dw = Math.Max(3, w * displayWidth / refWidth); + int dh = Math.Max(2, h * displayHeight / refHeight); + + if (dx + dw > displayWidth) + { + dw = displayWidth - dx; + } + + if (dy + dh > displayHeight) + { + dh = displayHeight - dy; + } + + zoneList.Add((dx, dy, dw, dh, zoneId)); + + for (int r = dy; r < dy + dh && r < displayHeight; r++) + { + for (int c = dx; c < dx + dw && c < displayWidth; c++) + { + zoneGrid[r, c].Add(zoneId); + } + } + + zoneId++; + } + + // Draw top border + sb.Append(" +"); + sb.Append('-', displayWidth); + sb.AppendLine("+"); + + // Draw each row + char[] shades = { '.', ':', '░', '▒', '▓', '█', '◆', '●', '■', '▪' }; + + for (int r = 0; r < displayHeight; r++) + { + sb.Append(" |"); + for (int c = 0; c < displayWidth; c++) + { + var zonesHere = zoneGrid[r, c]; + + if (zonesHere.Count == 0) + { + sb.Append(' '); + } + else + { + int topZone = zonesHere[zonesHere.Count - 1]; + var rect = zoneList[topZone]; + + bool isTopEdge = r == rect.Y; + bool isBottomEdge = r == rect.Y + rect.Height - 1; + bool isLeftEdge = c == rect.X; + bool isRightEdge = c == rect.X + rect.Width - 1; + + if ((isTopEdge || isBottomEdge) && (isLeftEdge || isRightEdge)) + { + sb.Append('+'); + } + else if (isTopEdge || isBottomEdge) + { + sb.Append('-'); + } + else if (isLeftEdge || isRightEdge) + { + sb.Append('|'); + } + else + { + sb.Append(shades[topZone % shades.Length]); + } + } + } + + sb.AppendLine("|"); + } + + // Draw bottom border + sb.Append(" +"); + sb.Append('-', displayWidth); + sb.AppendLine("+"); + + // Draw legend + sb.AppendLine(); + sb.Append(" Legend: "); + for (int i = 0; i < Math.Min(zoneId, shades.Length); i++) + { + if (i > 0) + { + sb.Append(", "); + } + + sb.Append(CultureInfo.InvariantCulture, $"Zone {i} = {shades[i]}"); + } + + sb.AppendLine(); + return sb.ToString(); + } +} diff --git a/src/modules/fancyzones/FancyZonesCLI/Logger.cs b/src/modules/fancyzones/FancyZonesCLI/Logger.cs new file mode 100644 index 0000000000..3f62abf7eb --- /dev/null +++ b/src/modules/fancyzones/FancyZonesCLI/Logger.cs @@ -0,0 +1,126 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Globalization; +using System.IO; +using System.Runtime.CompilerServices; + +namespace FancyZonesCLI; + +/// +/// Simple logger for FancyZones CLI. +/// Logs to %LOCALAPPDATA%\Microsoft\PowerToys\FancyZones\CLI\Logs +/// +internal static class Logger +{ + private static readonly object LockObj = new(); + private static string _logFilePath = string.Empty; + private static bool _isInitialized; + + /// + /// Gets the path to the current log file. + /// + public static string LogFilePath => _logFilePath; + + /// + /// Initializes the logger. + /// + public static void InitializeLogger() + { + if (_isInitialized) + { + return; + } + + try + { + var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + var logDirectory = Path.Combine(localAppData, "Microsoft", "PowerToys", "FancyZones", "CLI", "Logs"); + + if (!Directory.Exists(logDirectory)) + { + Directory.CreateDirectory(logDirectory); + } + + var logFileName = $"FancyZonesCLI_{DateTime.Now:yyyy-MM-dd}.log"; + _logFilePath = Path.Combine(logDirectory, logFileName); + _isInitialized = true; + + LogInfo("FancyZones CLI started"); + } + catch + { + // Silently fail if logging cannot be initialized + } + } + + /// + /// Logs an error message. + /// + public static void LogError(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + Log("ERROR", message, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Logs an error message with exception details. + /// + public static void LogError(string message, Exception ex, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + var fullMessage = ex == null + ? message + : $"{message} | Exception: {ex.GetType().Name}: {ex.Message}"; + Log("ERROR", fullMessage, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Logs a warning message. + /// + public static void LogWarning(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + Log("WARN", message, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Logs an informational message. + /// + public static void LogInfo(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + Log("INFO", message, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Logs a debug message (only in DEBUG builds). + /// + [System.Diagnostics.Conditional("DEBUG")] + public static void LogDebug(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + Log("DEBUG", message, memberName, sourceFilePath, sourceLineNumber); + } + + private static void Log(string level, string message, string memberName, string sourceFilePath, int sourceLineNumber) + { + if (!_isInitialized || string.IsNullOrEmpty(_logFilePath)) + { + return; + } + + try + { + var fileName = Path.GetFileName(sourceFilePath); + var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture); + var logEntry = $"[{timestamp}] [{level}] [{fileName}:{sourceLineNumber}] [{memberName}] {message}{Environment.NewLine}"; + + lock (LockObj) + { + File.AppendAllText(_logFilePath, logEntry); + } + } + catch + { + // Silently fail if logging fails + } + } +} diff --git a/src/modules/fancyzones/FancyZonesCLI/Models.cs b/src/modules/fancyzones/FancyZonesCLI/Models.cs new file mode 100644 index 0000000000..0c8bbefe54 --- /dev/null +++ b/src/modules/fancyzones/FancyZonesCLI/Models.cs @@ -0,0 +1,137 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace FancyZonesCLI; + +// JSON Source Generator for AOT compatibility +[JsonSerializable(typeof(LayoutTemplates))] +[JsonSerializable(typeof(CustomLayouts))] +[JsonSerializable(typeof(AppliedLayouts))] +[JsonSerializable(typeof(LayoutHotkeys))] +[JsonSourceGenerationOptions(WriteIndented = true)] +internal partial class FancyZonesJsonContext : JsonSerializerContext +{ +} + +// Layout Templates +public sealed class LayoutTemplates +{ + [JsonPropertyName("layout-templates")] + public List Templates { get; set; } +} + +public sealed class TemplateLayout +{ + [JsonPropertyName("type")] + public string Type { get; set; } = string.Empty; + + [JsonPropertyName("zone-count")] + public int ZoneCount { get; set; } + + [JsonPropertyName("show-spacing")] + public bool ShowSpacing { get; set; } + + [JsonPropertyName("spacing")] + public int Spacing { get; set; } + + [JsonPropertyName("sensitivity-radius")] + public int SensitivityRadius { get; set; } +} + +// Custom Layouts +public sealed class CustomLayouts +{ + [JsonPropertyName("custom-layouts")] + public List Layouts { get; set; } +} + +public sealed class CustomLayout +{ + [JsonPropertyName("uuid")] + public string Uuid { get; set; } = string.Empty; + + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; + + [JsonPropertyName("type")] + public string Type { get; set; } = string.Empty; + + [JsonPropertyName("info")] + public JsonElement Info { get; set; } +} + +// Applied Layouts +public sealed class AppliedLayouts +{ + [JsonPropertyName("applied-layouts")] + public List Layouts { get; set; } +} + +public sealed class AppliedLayoutWrapper +{ + [JsonPropertyName("device")] + public DeviceInfo Device { get; set; } = new(); + + [JsonPropertyName("applied-layout")] + public AppliedLayoutInfo AppliedLayout { get; set; } = new(); +} + +public sealed class DeviceInfo +{ + [JsonPropertyName("monitor")] + public string Monitor { get; set; } = string.Empty; + + [JsonPropertyName("monitor-instance")] + public string MonitorInstance { get; set; } = string.Empty; + + [JsonPropertyName("monitor-number")] + public int MonitorNumber { get; set; } + + [JsonPropertyName("serial-number")] + public string SerialNumber { get; set; } = string.Empty; + + [JsonPropertyName("virtual-desktop")] + public string VirtualDesktop { get; set; } = string.Empty; +} + +public sealed class AppliedLayoutInfo +{ + [JsonPropertyName("uuid")] + public string Uuid { get; set; } = string.Empty; + + [JsonPropertyName("type")] + public string Type { get; set; } = string.Empty; + + [JsonPropertyName("show-spacing")] + public bool ShowSpacing { get; set; } + + [JsonPropertyName("spacing")] + public int Spacing { get; set; } + + [JsonPropertyName("zone-count")] + public int ZoneCount { get; set; } + + [JsonPropertyName("sensitivity-radius")] + public int SensitivityRadius { get; set; } +} + +// Layout Hotkeys +public sealed class LayoutHotkeys +{ + [JsonPropertyName("layout-hotkeys")] + public List Hotkeys { get; set; } +} + +public sealed class LayoutHotkey +{ + [JsonPropertyName("key")] + public int Key { get; set; } + + [JsonPropertyName("layout-id")] + public string LayoutId { get; set; } = string.Empty; +} diff --git a/src/modules/fancyzones/FancyZonesCLI/NativeMethods.cs b/src/modules/fancyzones/FancyZonesCLI/NativeMethods.cs new file mode 100644 index 0000000000..efab0859bd --- /dev/null +++ b/src/modules/fancyzones/FancyZonesCLI/NativeMethods.cs @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Windows.Win32; +using Windows.Win32.Foundation; + +namespace FancyZonesCLI; + +/// +/// Native Windows API methods for FancyZones CLI. +/// +internal static class NativeMethods +{ + // Registered Windows messages for notifying FancyZones + private static uint wmPrivAppliedLayoutsFileUpdate; + private static uint wmPrivLayoutHotkeysFileUpdate; + + /// + /// Gets the Windows message ID for applied layouts file update notification. + /// + public static uint WM_PRIV_APPLIED_LAYOUTS_FILE_UPDATE => wmPrivAppliedLayoutsFileUpdate; + + /// + /// Gets the Windows message ID for layout hotkeys file update notification. + /// + public static uint WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE => wmPrivLayoutHotkeysFileUpdate; + + /// + /// Initializes the Windows messages used for FancyZones notifications. + /// + public static void InitializeWindowMessages() + { + wmPrivAppliedLayoutsFileUpdate = PInvoke.RegisterWindowMessage("{2ef2c8a7-e0d5-4f31-9ede-52aade2d284d}"); + wmPrivLayoutHotkeysFileUpdate = PInvoke.RegisterWindowMessage("{07229b7e-4f22-4357-b136-33c289be2295}"); + } + + /// + /// Broadcasts a notification message to FancyZones. + /// + /// The Windows message ID to broadcast. + public static void NotifyFancyZones(uint message) + { + PInvoke.PostMessage(HWND.HWND_BROADCAST, message, 0, 0); + } + + /// + /// Brings the specified window to the foreground. + /// + /// A handle to the window. + /// True if the window was brought to the foreground. + public static bool SetForegroundWindow(nint hWnd) + { + return PInvoke.SetForegroundWindow(new HWND(hWnd)); + } +} diff --git a/src/modules/fancyzones/FancyZonesCLI/NativeMethods.json b/src/modules/fancyzones/FancyZonesCLI/NativeMethods.json new file mode 100644 index 0000000000..89cee38a92 --- /dev/null +++ b/src/modules/fancyzones/FancyZonesCLI/NativeMethods.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://aka.ms/CsWin32.schema.json", + "emitSingleFile": true, + "allowMarshaling": false +} diff --git a/src/modules/fancyzones/FancyZonesCLI/NativeMethods.txt b/src/modules/fancyzones/FancyZonesCLI/NativeMethods.txt new file mode 100644 index 0000000000..e3555c2333 --- /dev/null +++ b/src/modules/fancyzones/FancyZonesCLI/NativeMethods.txt @@ -0,0 +1,4 @@ +PostMessage +SetForegroundWindow +RegisterWindowMessage +HWND_BROADCAST diff --git a/src/modules/fancyzones/FancyZonesCLI/Program.cs b/src/modules/fancyzones/FancyZonesCLI/Program.cs new file mode 100644 index 0000000000..1b133dfa36 --- /dev/null +++ b/src/modules/fancyzones/FancyZonesCLI/Program.cs @@ -0,0 +1,115 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Globalization; +using System.Linq; +using FancyZonesCLI.Commands; + +namespace FancyZonesCLI; + +internal sealed class Program +{ + private static int Main(string[] args) + { + // Initialize logger + Logger.InitializeLogger(); + Logger.LogInfo($"CLI invoked with args: [{string.Join(", ", args)}]"); + + // Initialize Windows messages + NativeMethods.InitializeWindowMessages(); + + (int ExitCode, string Output) result; + + if (args.Length == 0) + { + result = (1, GetUsageText()); + } + else + { + var command = args[0].ToLowerInvariant(); + + result = command switch + { + "open-editor" or "editor" or "e" => EditorCommands.OpenEditor(), + "get-monitors" or "monitors" or "m" => MonitorCommands.GetMonitors(), + "get-layouts" or "layouts" or "ls" => LayoutCommands.GetLayouts(), + "get-active-layout" or "active" or "get-active" or "a" => LayoutCommands.GetActiveLayout(), + "set-layout" or "set" or "s" => args.Length >= 2 + ? LayoutCommands.SetLayout(args.Skip(1).ToArray(), NativeMethods.NotifyFancyZones, NativeMethods.WM_PRIV_APPLIED_LAYOUTS_FILE_UPDATE) + : (1, "Error: set-layout requires a UUID parameter"), + "open-settings" or "settings" => EditorCommands.OpenSettings(), + "get-hotkeys" or "hotkeys" or "hk" => HotkeyCommands.GetHotkeys(), + "set-hotkey" or "shk" => args.Length >= 3 + ? HotkeyCommands.SetHotkey(int.Parse(args[1], CultureInfo.InvariantCulture), args[2], NativeMethods.NotifyFancyZones, NativeMethods.WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE) + : (1, "Error: set-hotkey requires "), + "remove-hotkey" or "rhk" => args.Length >= 2 + ? HotkeyCommands.RemoveHotkey(int.Parse(args[1], CultureInfo.InvariantCulture), NativeMethods.NotifyFancyZones, NativeMethods.WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE) + : (1, "Error: remove-hotkey requires "), + "help" or "--help" or "-h" => (0, GetUsageText()), + _ => (1, $"Error: Unknown command: {command}\n\n{GetUsageText()}"), + }; + } + + // Log result + if (result.ExitCode == 0) + { + Logger.LogInfo($"Command completed successfully"); + } + else + { + Logger.LogWarning($"Command failed with exit code {result.ExitCode}: {result.Output}"); + } + + // Output result + if (!string.IsNullOrEmpty(result.Output)) + { + Console.WriteLine(result.Output); + } + + return result.ExitCode; + } + + private static string GetUsageText() + { + return """ + FancyZones CLI - Command line interface for FancyZones + ====================================================== + + Usage: FancyZonesCLI.exe [options] + + Commands: + open-editor (editor, e) Launch FancyZones layout editor + get-monitors (monitors, m) List all monitors and their properties + get-layouts (layouts, ls) List all available layouts + get-active-layout (get-active, active, a) + Show currently active layout + set-layout (set, s) [options] + Set layout by UUID + --monitor Apply to monitor N (1-based) + --all Apply to all monitors + open-settings (settings) Open FancyZones settings page + get-hotkeys (hotkeys, hk) List all layout hotkeys + set-hotkey (shk) Assign hotkey (0-9) to CUSTOM layout + Note: Only custom layouts work with hotkeys + remove-hotkey (rhk) Remove hotkey assignment + help Show this help message + + + Examples: + FancyZonesCLI.exe e # Open editor (short) + FancyZonesCLI.exe m # List monitors (short) + FancyZonesCLI.exe ls # List layouts (short) + FancyZonesCLI.exe a # Get active layout (short) + FancyZonesCLI.exe s focus --all # Set layout (short) + FancyZonesCLI.exe open-editor # Open editor (long) + FancyZonesCLI.exe get-monitors + FancyZonesCLI.exe get-layouts + FancyZonesCLI.exe set-layout {12345678-1234-1234-1234-123456789012} + FancyZonesCLI.exe set-layout focus --monitor 2 + FancyZonesCLI.exe set-layout columns --all + FancyZonesCLI.exe set-hotkey 3 {12345678-1234-1234-1234-123456789012} + """; + } +} diff --git a/src/modules/imageresizer/tests/Models/ResizeOperationTests.cs b/src/modules/imageresizer/tests/Models/ResizeOperationTests.cs index d1eeae664e..d91a4e4879 100644 --- a/src/modules/imageresizer/tests/Models/ResizeOperationTests.cs +++ b/src/modules/imageresizer/tests/Models/ResizeOperationTests.cs @@ -394,6 +394,93 @@ namespace ImageResizer.Models }); } + [TestMethod] + public void TransformHonorsFillWithShrinkOnlyWhenCropRequired() + { + // Testing original 96x96 pixel Test.jpg cropped to 48x96 (Fill mode). + // + // ScaleX = 48/96 = 0.5 + // ScaleY = 96/96 = 1.0 + // Fill mode takes the max of these = 1.0. + // + // Previously, the transform logic saw the scale of 1.0 and returned the + // original dimensions. The corrected logic recognizes that a crop is + // required on one dimension and proceeds with the operation. + var operation = new ResizeOperation( + "Test.jpg", + _directory, + Settings(x => + { + x.ShrinkOnly = true; + x.SelectedSize.Fit = ResizeFit.Fill; + x.SelectedSize.Width = 48; + x.SelectedSize.Height = 96; + })); + + operation.Execute(); + + AssertEx.Image( + _directory.File(), + image => + { + Assert.AreEqual(48, image.Frames[0].PixelWidth); + Assert.AreEqual(96, image.Frames[0].PixelHeight); + }); + } + + [TestMethod] + public void TransformHonorsFillWithShrinkOnlyWhenUpscaleAttempted() + { + // Confirm that attempting to upscale the original image will return the + // original dimensions when Shrink Only is enabled. + var operation = new ResizeOperation( + "Test.jpg", + _directory, + Settings(x => + { + x.ShrinkOnly = true; + x.SelectedSize.Fit = ResizeFit.Fill; + x.SelectedSize.Width = 192; + x.SelectedSize.Height = 192; + })); + + operation.Execute(); + + AssertEx.Image( + _directory.File(), + image => + { + Assert.AreEqual(96, image.Frames[0].PixelWidth); + Assert.AreEqual(96, image.Frames[0].PixelHeight); + }); + } + + [TestMethod] + public void TransformHonorsFillWithShrinkOnlyWhenNoChangeRequired() + { + // With a scale of 1.0 on both axes, the original should be returned. + var operation = new ResizeOperation( + "Test.jpg", + _directory, + Settings(x => + { + x.ShrinkOnly = true; + x.SelectedSize.Fit = ResizeFit.Fill; + x.SelectedSize.Width = 96; + x.SelectedSize.Height = 96; + })); + + operation.Execute(); + + AssertEx.Image( + _directory.File(), + image => + { + Assert.AreEqual(96, image.Frames[0].PixelWidth); + Assert.AreEqual(96, image.Frames[0].PixelHeight); + }); + } + [TestMethod] public void GetDestinationPathUniquifiesOutputFilename() { diff --git a/src/modules/imageresizer/ui/Models/ResizeOperation.cs b/src/modules/imageresizer/ui/Models/ResizeOperation.cs index 2c81076012..a56cd2f658 100644 --- a/src/modules/imageresizer/ui/Models/ResizeOperation.cs +++ b/src/modules/imageresizer/ui/Models/ResizeOperation.cs @@ -167,49 +167,89 @@ namespace ImageResizer.Models private BitmapSource Transform(BitmapSource source) { - var originalWidth = source.PixelWidth; - var originalHeight = source.PixelHeight; - var width = _settings.SelectedSize.GetPixelWidth(originalWidth, source.DpiX); - var height = _settings.SelectedSize.GetPixelHeight(originalHeight, source.DpiY); + int originalWidth = source.PixelWidth; + int originalHeight = source.PixelHeight; - if (_settings.IgnoreOrientation - && !_settings.SelectedSize.HasAuto - && _settings.SelectedSize.Unit != ResizeUnit.Percent - && originalWidth < originalHeight != (width < height)) + // Convert from the chosen size unit to pixels, if necessary. + double width = _settings.SelectedSize.GetPixelWidth(originalWidth, source.DpiX); + double height = _settings.SelectedSize.GetPixelHeight(originalHeight, source.DpiY); + + // Swap target width/height dimensions if orientation correction is required. + // Ensures that we don't try to fit a landscape image into a portrait box by + // distorting it, unless specific Auto/Percent rules are applied. + bool canSwapDimensions = _settings.IgnoreOrientation && + !_settings.SelectedSize.HasAuto && + _settings.SelectedSize.Unit != ResizeUnit.Percent; + + if (canSwapDimensions) { - var temp = width; - width = height; - height = temp; + bool isInputLandscape = originalWidth > originalHeight; + bool isInputPortrait = originalHeight > originalWidth; + bool isTargetLandscape = width > height; + bool isTargetPortrait = height > width; + + // Swap dimensions if there is a mismatch between input and target. + if ((isInputLandscape && isTargetPortrait) || + (isInputPortrait && isTargetLandscape)) + { + (width, height) = (height, width); + } } - var scaleX = width / originalWidth; - var scaleY = height / originalHeight; + double scaleX = width / originalWidth; + double scaleY = height / originalHeight; + // Normalize scales based on the chosen Fit/Fill mode. if (_settings.SelectedSize.Fit == ResizeFit.Fit) { + // Fit: use the smaller scale to ensure the image fits within the target. scaleX = Math.Min(scaleX, scaleY); scaleY = scaleX; } else if (_settings.SelectedSize.Fit == ResizeFit.Fill) { + // Fill: use the larger scale to ensure the target area is fully covered. + // This often results in one dimension overflowing, which is handled by + // cropping later. scaleX = Math.Max(scaleX, scaleY); scaleY = scaleX; } - if (_settings.ShrinkOnly - && _settings.SelectedSize.Unit != ResizeUnit.Percent - && (scaleX >= 1 || scaleY >= 1)) + // Handle Shrink Only mode. + if (_settings.ShrinkOnly && _settings.SelectedSize.Unit != ResizeUnit.Percent) { - return source; + // Shrink Only mode should never return an image larger than the original. + if (scaleX > 1 || scaleY > 1) + { + return source; + } + + // Allow for crop-only when in Fill mode. + // At this point, the scale is <= 1.0. In Fill mode, it is possible for + // the scale to be 1.0 (no resize needed) while the target dimensions are + // smaller than the originals, requiring a crop. + bool isFillCropRequired = _settings.SelectedSize.Fit == ResizeFit.Fill && + (originalWidth > width || originalHeight > height); + + // If the scale is exactly 1.0 and a crop isn't required, we return the + // original image to prevent a re-encode. + if (scaleX == 1 && scaleY == 1 && !isFillCropRequired) + { + return source; + } } + // Apply the scaling. var scaledBitmap = new TransformedBitmap(source, new ScaleTransform(scaleX, scaleY)); + + // Apply the centered crop for Fill mode, if necessary. Applies when Fill + // mode caused the scaled image to exceed the target dimensions. if (_settings.SelectedSize.Fit == ResizeFit.Fill && (scaledBitmap.PixelWidth > width || scaledBitmap.PixelHeight > height)) { - var x = (int)(((originalWidth * scaleX) - width) / 2); - var y = (int)(((originalHeight * scaleY) - height) / 2); + int x = (int)(((originalWidth * scaleX) - width) / 2); + int y = (int)(((originalHeight * scaleY) - height) / 2); return new CroppedBitmap(scaledBitmap, new Int32Rect(x, y, (int)width, (int)height)); } diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.PowerToys/Components/UtilityProvider.cs b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.PowerToys/Components/UtilityProvider.cs index a953496500..74d35a5b18 100644 --- a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.PowerToys/Components/UtilityProvider.cs +++ b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.PowerToys/Components/UtilityProvider.cs @@ -27,7 +27,7 @@ namespace Microsoft.PowerToys.Run.Plugin.PowerToys public UtilityProvider() { - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; var generalSettings = settingsUtils.GetSettings(); _utilities = new List(); @@ -228,7 +228,7 @@ namespace Microsoft.PowerToys.Run.Plugin.PowerToys { retryCount++; - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; var generalSettings = settingsUtils.GetSettings(); foreach (var u in _utilities) diff --git a/src/modules/launcher/PowerLauncher/SettingsReader.cs b/src/modules/launcher/PowerLauncher/SettingsReader.cs index 41d0524f69..dbba7e7906 100644 --- a/src/modules/launcher/PowerLauncher/SettingsReader.cs +++ b/src/modules/launcher/PowerLauncher/SettingsReader.cs @@ -38,7 +38,7 @@ namespace PowerLauncher public SettingsReader(PowerToysRunSettings settings, ThemeManager themeManager) { - _settingsUtils = new SettingsUtils(); + _settingsUtils = SettingsUtils.Default; _settings = settings; _themeManager = themeManager; diff --git a/src/modules/peek/Peek.FilePreviewer/Models/PreviewSettings.cs b/src/modules/peek/Peek.FilePreviewer/Models/PreviewSettings.cs index 3df7fc23a1..1ba5e676a5 100644 --- a/src/modules/peek/Peek.FilePreviewer/Models/PreviewSettings.cs +++ b/src/modules/peek/Peek.FilePreviewer/Models/PreviewSettings.cs @@ -34,7 +34,7 @@ namespace Peek.FilePreviewer.Models public PreviewSettings() { - _settingsUtils = new SettingsUtils(); + _settingsUtils = SettingsUtils.Default; SourceCodeWrapText = false; SourceCodeTryFormat = false; SourceCodeFontSize = 14; diff --git a/src/modules/peek/Peek.UI/Services/UserSettings.cs b/src/modules/peek/Peek.UI/Services/UserSettings.cs index 77257eaf80..e3750fe8e1 100644 --- a/src/modules/peek/Peek.UI/Services/UserSettings.cs +++ b/src/modules/peek/Peek.UI/Services/UserSettings.cs @@ -77,7 +77,7 @@ namespace Peek.UI public UserSettings() { - _settingsUtils = new SettingsUtils(); + _settingsUtils = SettingsUtils.Default; LoadSettingsFromJson(); diff --git a/src/modules/poweraccent/PowerAccent.Core/Languages.cs b/src/modules/poweraccent/PowerAccent.Core/Languages.cs index 06c3a2bea3..73dca3ee72 100644 --- a/src/modules/poweraccent/PowerAccent.Core/Languages.cs +++ b/src/modules/poweraccent/PowerAccent.Core/Languages.cs @@ -224,13 +224,13 @@ namespace PowerAccent.Core LetterKey.VK_X => new[] { "ẋ", "×" }, LetterKey.VK_Y => new[] { "ẏ", "ꝡ" }, LetterKey.VK_Z => new[] { "ʒ", "ǯ", "ℤ" }, - LetterKey.VK_COMMA => new[] { "∙", "₋", "⁻", "–", "√" }, // – is in VK_MINUS for other languages, but not VK_COMMA, so we add it here. + LetterKey.VK_COMMA => new[] { "∙", "₋", "⁻", "–", "√", "‟", "《", "》", "‛", "〈", "〉", "″", "‴", "⁗" }, // – is in VK_MINUS for other languages, but not VK_COMMA, so we add it here. LetterKey.VK_PERIOD => new[] { "…", "⁝", "\u0300", "\u0301", "\u0302", "\u0303", "\u0304", "\u0308", "\u030B", "\u030C" }, LetterKey.VK_MINUS => new[] { "~", "‐", "‑", "‒", "—", "―", "⁓", "−", "⸺", "⸻", "∓" }, LetterKey.VK_SLASH_ => new[] { "÷", "√" }, LetterKey.VK_DIVIDE_ => new[] { "÷", "√" }, LetterKey.VK_MULTIPLY_ => new[] { "×", "⋅" }, - LetterKey.VK_PLUS => new[] { "≤", "≥", "≠", "≈", "≙", "⊕", "⊗", "∓", "≅", "≡" }, + LetterKey.VK_PLUS => new[] { "≤", "≥", "≠", "≈", "≙", "⊕", "⊗", "±", "≅", "≡", "₊", "⁺" }, LetterKey.VK_BACKSLASH => new[] { "`", "~" }, _ => Array.Empty(), }; @@ -302,6 +302,7 @@ namespace PowerAccent.Core LetterKey.VK_E => new[] { "€" }, LetterKey.VK_S => new[] { "š" }, LetterKey.VK_Z => new[] { "ž" }, + LetterKey.VK_COMMA => new[] { "„", "“", "»", "«" }, _ => Array.Empty(), }; } @@ -317,6 +318,7 @@ namespace PowerAccent.Core LetterKey.VK_U => new[] { "ü" }, LetterKey.VK_Z => new[] { "ž" }, LetterKey.VK_S => new[] { "š" }, + LetterKey.VK_COMMA => new[] { "„", "“", "«", "»" }, _ => Array.Empty(), }; } @@ -344,6 +346,7 @@ namespace PowerAccent.Core LetterKey.VK_A => new[] { "ä", "å" }, LetterKey.VK_E => new[] { "€" }, LetterKey.VK_O => new[] { "ö" }, + LetterKey.VK_COMMA => new[] { "”", "’", "»" }, _ => Array.Empty(), }; } @@ -360,6 +363,7 @@ namespace PowerAccent.Core LetterKey.VK_O => new[] { "ô", "ö", "ó", "ò", "õ", "œ" }, LetterKey.VK_U => new[] { "û", "ù", "ü", "ú" }, LetterKey.VK_Y => new[] { "ÿ", "ý" }, + LetterKey.VK_COMMA => new[] { "«", "»", "‹", "›", "“", "”", "‘", "’" }, _ => Array.Empty(), }; } @@ -376,6 +380,7 @@ namespace PowerAccent.Core LetterKey.VK_U => new[] { "ú" }, LetterKey.VK_Y => new[] { "ý" }, LetterKey.VK_T => new[] { "þ" }, + LetterKey.VK_COMMA => new[] { "„", "“", "‚", "‘" }, _ => Array.Empty(), }; } @@ -393,7 +398,7 @@ namespace PowerAccent.Core LetterKey.VK_N => new[] { "ñ" }, LetterKey.VK_O => new[] { "ó" }, LetterKey.VK_U => new[] { "ú", "ü" }, - LetterKey.VK_COMMA => new[] { "¿", "?", "¡", "!" }, + LetterKey.VK_COMMA => new[] { "¿", "?", "¡", "!", "«", "»", "“", "”", "‘", "’" }, _ => Array.Empty(), }; } @@ -411,7 +416,7 @@ namespace PowerAccent.Core LetterKey.VK_O => new[] { "ò", "ó" }, LetterKey.VK_U => new[] { "ù", "ú", "ü" }, LetterKey.VK_L => new[] { "·" }, - LetterKey.VK_COMMA => new[] { "¿", "?", "¡", "!" }, + LetterKey.VK_COMMA => new[] { "¿", "?", "¡", "!", "«", "»", "“", "”", "‘", "’" }, _ => Array.Empty(), }; } @@ -427,6 +432,7 @@ namespace PowerAccent.Core LetterKey.VK_O => new[] { "ō" }, LetterKey.VK_S => new[] { "$" }, LetterKey.VK_U => new[] { "ū" }, + LetterKey.VK_COMMA => new[] { "“", "”", "‘", "’" }, _ => Array.Empty(), }; } @@ -443,6 +449,7 @@ namespace PowerAccent.Core LetterKey.VK_N => new[] { "ñ" }, LetterKey.VK_O => new[] { "ó", "ö", "ô" }, LetterKey.VK_U => new[] { "ú", "ü", "û" }, + LetterKey.VK_COMMA => new[] { "“", "„", "”", "‘", ",", "’" }, _ => Array.Empty(), }; } @@ -469,6 +476,7 @@ namespace PowerAccent.Core LetterKey.VK_V => new[] { "ü", "ǖ", "ǘ", "ǚ", "ǜ" }, LetterKey.VK_Y => new[] { "¥" }, LetterKey.VK_Z => new[] { "ẑ" }, + LetterKey.VK_COMMA => new[] { "“", "”", "‘", "’", "「", "」", "『", "』" }, _ => Array.Empty(), }; } @@ -505,6 +513,7 @@ namespace PowerAccent.Core LetterKey.VK_S => new[] { "ş" }, LetterKey.VK_T => new[] { "₺" }, LetterKey.VK_U => new[] { "ü", "û" }, + LetterKey.VK_COMMA => new[] { "“", "”", "‘", "’", "«", "»", "‹", "›" }, _ => Array.Empty(), }; } @@ -522,6 +531,7 @@ namespace PowerAccent.Core LetterKey.VK_O => new[] { "ó" }, LetterKey.VK_S => new[] { "ś" }, LetterKey.VK_Z => new[] { "ż", "ź" }, + LetterKey.VK_COMMA => new[] { "„", "”", "‘", "’", "»", "«" }, _ => Array.Empty(), }; } @@ -536,10 +546,9 @@ namespace PowerAccent.Core LetterKey.VK_E => new[] { "é", "ê", "€" }, LetterKey.VK_I => new[] { "í" }, LetterKey.VK_O => new[] { "ô", "ó", "õ", "º" }, - LetterKey.VK_P => new[] { "π" }, LetterKey.VK_S => new[] { "$" }, LetterKey.VK_U => new[] { "ú" }, - LetterKey.VK_COMMA => new[] { "≤", "≥", "≠", "≈", "≙", "±", "₊", "⁺" }, + LetterKey.VK_COMMA => new[] { "“", "”", "‘", "’", "«", "»" }, _ => Array.Empty(), }; } @@ -594,6 +603,7 @@ namespace PowerAccent.Core LetterKey.VK_U => new[] { "ú" }, LetterKey.VK_Y => new[] { "ý" }, LetterKey.VK_Z => new[] { "ž" }, + LetterKey.VK_COMMA => new[] { "„", "“", "‚", "‘", "»", "«", "›", "‹" }, _ => Array.Empty(), }; } @@ -608,6 +618,7 @@ namespace PowerAccent.Core LetterKey.VK_I => new[] { "í" }, LetterKey.VK_O => new[] { "ó" }, LetterKey.VK_U => new[] { "ú" }, + LetterKey.VK_COMMA => new[] { "“", "”", "‘", "’" }, _ => Array.Empty(), }; } @@ -623,6 +634,7 @@ namespace PowerAccent.Core LetterKey.VK_O => new[] { "ò" }, LetterKey.VK_P => new[] { "£" }, LetterKey.VK_U => new[] { "ù" }, + LetterKey.VK_COMMA => new[] { "“", "”", "‘", "’" }, _ => Array.Empty(), }; } @@ -645,6 +657,7 @@ namespace PowerAccent.Core LetterKey.VK_U => new[] { "ů", "ú" }, LetterKey.VK_Y => new[] { "ý" }, LetterKey.VK_Z => new[] { "ž" }, + LetterKey.VK_COMMA => new[] { "„", "“", "‚", "‘", "»", "«", "›", "‹" }, _ => Array.Empty(), }; } @@ -659,6 +672,7 @@ namespace PowerAccent.Core LetterKey.VK_O => new[] { "ö" }, LetterKey.VK_S => new[] { "ß" }, LetterKey.VK_U => new[] { "ü" }, + LetterKey.VK_COMMA => new[] { "„", "“", "‚", "‘", "»", "«", "›", "‹" }, _ => Array.Empty(), }; } @@ -689,6 +703,7 @@ namespace PowerAccent.Core LetterKey.VK_X => new string[] { "ξ" }, LetterKey.VK_Y => new string[] { "υ" }, LetterKey.VK_Z => new string[] { "ζ" }, + LetterKey.VK_COMMA => new[] { "“", "”", "«", "»", }, _ => Array.Empty(), }; } @@ -710,9 +725,9 @@ namespace PowerAccent.Core LetterKey.VK_U => new[] { "וֹ", "וּ", "װ", "\u05b9" }, LetterKey.VK_X => new[] { "\u05b6", "\u05b1" }, LetterKey.VK_Y => new[] { "ױ" }, - LetterKey.VK_COMMA => new[] { "”", "’", "״", "׳" }, + LetterKey.VK_COMMA => new[] { "”", "’", "'", "״", "׳" }, LetterKey.VK_PERIOD => new[] { "\u05ab", "\u05bd", "\u05bf" }, - LetterKey.VK_MINUS => new[] { "–", "־" }, + LetterKey.VK_MINUS => new[] { "־" }, _ => Array.Empty(), }; } @@ -727,6 +742,7 @@ namespace PowerAccent.Core LetterKey.VK_I => new[] { "í" }, LetterKey.VK_O => new[] { "ó", "ő", "ö" }, LetterKey.VK_U => new[] { "ú", "ű", "ü" }, + LetterKey.VK_COMMA => new[] { "„", "”", "»", "«" }, _ => Array.Empty(), }; } @@ -740,6 +756,7 @@ namespace PowerAccent.Core LetterKey.VK_I => new[] { "î" }, LetterKey.VK_S => new[] { "ș" }, LetterKey.VK_T => new[] { "ț" }, + LetterKey.VK_COMMA => new[] { "„", "”", "«", "»" }, _ => Array.Empty(), }; } @@ -754,6 +771,7 @@ namespace PowerAccent.Core LetterKey.VK_I => new[] { "ì", "í" }, LetterKey.VK_O => new[] { "ò", "ó" }, LetterKey.VK_U => new[] { "ù", "ú" }, + LetterKey.VK_COMMA => new[] { "«", "»", "“", "”", "‘", "’" }, _ => Array.Empty(), }; } @@ -772,6 +790,7 @@ namespace PowerAccent.Core LetterKey.VK_R => new[] { "ř" }, LetterKey.VK_S => new[] { "ş" }, LetterKey.VK_U => new[] { "û", "ü" }, + LetterKey.VK_COMMA => new[] { "«", "»", "“", "”" }, _ => Array.Empty(), }; } @@ -789,6 +808,7 @@ namespace PowerAccent.Core LetterKey.VK_U => new[] { "û", "ü", "ù", "ú" }, LetterKey.VK_Y => new[] { "ŷ", "ÿ", "ỳ", "ý" }, LetterKey.VK_W => new[] { "ŵ", "ẅ", "ẁ", "ẃ" }, + LetterKey.VK_COMMA => new[] { "‘", "’", "“", "“" }, _ => Array.Empty(), }; } @@ -801,6 +821,7 @@ namespace PowerAccent.Core LetterKey.VK_A => new[] { "å", "ä" }, LetterKey.VK_E => new[] { "é" }, LetterKey.VK_O => new[] { "ö" }, + LetterKey.VK_COMMA => new[] { "”", "’", "»", "«" }, _ => Array.Empty(), }; } @@ -814,6 +835,7 @@ namespace PowerAccent.Core LetterKey.VK_D => new[] { "đ" }, LetterKey.VK_S => new[] { "š" }, LetterKey.VK_Z => new[] { "ž" }, + LetterKey.VK_COMMA => new[] { "„", "“", "‚", "’", "»", "«", "›", "‹" }, _ => Array.Empty(), }; } @@ -838,6 +860,7 @@ namespace PowerAccent.Core { LetterKey.VK_E => new[] { "ѐ" }, LetterKey.VK_I => new[] { "ѝ" }, + LetterKey.VK_COMMA => new[] { "„", "“", "’", "‘" }, _ => Array.Empty(), }; } @@ -869,6 +892,7 @@ namespace PowerAccent.Core LetterKey.VK_E => new[] { "€", "é" }, LetterKey.VK_O => new[] { "ø" }, LetterKey.VK_S => new[] { "$" }, + LetterKey.VK_COMMA => new[] { "«", "»", ",", "‘", "’", "„", "“" }, _ => Array.Empty(), }; } @@ -881,6 +905,7 @@ namespace PowerAccent.Core LetterKey.VK_A => new[] { "å", "æ" }, LetterKey.VK_E => new[] { "€" }, LetterKey.VK_O => new[] { "ø" }, + LetterKey.VK_COMMA => new[] { "»", "«", "“", "”", "›", "‹", "‘", "’" }, _ => Array.Empty(), }; } @@ -897,6 +922,7 @@ namespace PowerAccent.Core LetterKey.VK_S => new[] { "š" }, LetterKey.VK_U => new[] { "ų", "ū" }, LetterKey.VK_Z => new[] { "ž" }, + LetterKey.VK_COMMA => new[] { "„", "“", "‚", "‘" }, _ => Array.Empty(), }; } @@ -910,6 +936,7 @@ namespace PowerAccent.Core LetterKey.VK_E => new[] { "€" }, LetterKey.VK_S => new[] { "š" }, LetterKey.VK_Z => new[] { "ž" }, + LetterKey.VK_COMMA => new[] { "„", "“", "»", "«" }, _ => Array.Empty(), }; } diff --git a/src/modules/poweraccent/PowerAccent.Core/PowerAccent.cs b/src/modules/poweraccent/PowerAccent.Core/PowerAccent.cs index fa020ee4fe..4811118adb 100644 --- a/src/modules/poweraccent/PowerAccent.Core/PowerAccent.cs +++ b/src/modules/poweraccent/PowerAccent.Core/PowerAccent.cs @@ -20,6 +20,7 @@ public partial class PowerAccent : IDisposable // Keys that show a description (like dashes) when ShowCharacterInfoSetting is 1 private readonly LetterKey[] _letterKeysShowingDescription = new LetterKey[] { LetterKey.VK_O }; + private const double ScreenMinPadding = 150; private bool _visible; private string[] _characters = Array.Empty(); @@ -323,13 +324,17 @@ public partial class PowerAccent : IDisposable public Point GetDisplayCoordinates(Size window) { (Point Location, Size Size, double Dpi) activeDisplay = WindowsFunctions.GetActiveDisplay(); - double primaryDPI = Screen.PrimaryScreen.Bounds.Width / SystemParameters.PrimaryScreenWidth; - Rect screen = new Rect(activeDisplay.Location, activeDisplay.Size) / primaryDPI; + Rect screen = new(activeDisplay.Location, activeDisplay.Size); Position position = _settingService.Position; /* Debug.WriteLine("Dpi: " + activeDisplay.Dpi); */ - return Calculation.GetRawCoordinatesFromPosition(position, screen, window); + return Calculation.GetRawCoordinatesFromPosition(position, screen, window, activeDisplay.Dpi) / activeDisplay.Dpi; + } + + public double GetDisplayMaxWidth() + { + return WindowsFunctions.GetActiveDisplay().Size.Width - ScreenMinPadding; } public Position GetToolbarPosition() @@ -353,20 +358,21 @@ public partial class PowerAccent : IDisposable public static string[] ToUpper(string[] array) { - string[] result = new string[array.Length]; + List result = new(array.Length); for (int i = 0; i < array.Length; i++) { switch (array[i]) { - case "ß": result[i] = "ẞ"; break; - case "ǰ": result[i] = "J\u030c"; break; - case "ı\u0307\u0304": result[i] = "İ\u0304"; break; - case "ı": result[i] = "İ"; break; - case "ᵛ": result[i] = "ⱽ"; break; - default: result[i] = array[i].ToUpper(System.Globalization.CultureInfo.InvariantCulture); break; + case "ß": result.Add("ẞ"); break; + case "ǰ": result.Add("J\u030c"); break; + case "ı\u0307\u0304": result.Add("İ\u0304"); break; + case "ı": result.Add("İ"); break; + case "ᵛ": result.Add("ⱽ"); break; + case "ϑ": break; + default: result.Add(array[i].ToUpper(CultureInfo.InvariantCulture)); break; } } - return result; + return [..result]; } } diff --git a/src/modules/poweraccent/PowerAccent.Core/Services/SettingsService.cs b/src/modules/poweraccent/PowerAccent.Core/Services/SettingsService.cs index 1a1657ecaf..81e3d5c56f 100644 --- a/src/modules/poweraccent/PowerAccent.Core/Services/SettingsService.cs +++ b/src/modules/poweraccent/PowerAccent.Core/Services/SettingsService.cs @@ -24,7 +24,7 @@ public class SettingsService public SettingsService(KeyboardListener keyboardListener) { - _settingsUtils = new SettingsUtils(); + _settingsUtils = SettingsUtils.Default; _keyboardListener = keyboardListener; ReadSettings(); _watcher = Helper.GetFileWatcher(PowerAccentModuleName, "settings.json", () => { ReadSettings(); }); diff --git a/src/modules/poweraccent/PowerAccent.Core/Tools/Calculation.cs b/src/modules/poweraccent/PowerAccent.Core/Tools/Calculation.cs index 4929af535b..0945bfc99f 100644 --- a/src/modules/poweraccent/PowerAccent.Core/Tools/Calculation.cs +++ b/src/modules/poweraccent/PowerAccent.Core/Tools/Calculation.cs @@ -18,18 +18,18 @@ namespace PowerAccent.Core.Tools top < screen.Y ? caret.Y + 20 : top); } - public static Point GetRawCoordinatesFromPosition(Position position, Rect screen, Size window) + public static Point GetRawCoordinatesFromPosition(Position position, Rect screen, Size window, double dpi) { int offset = 24; double pointX = position switch { Position.Top or Position.Bottom or Position.Center - => screen.X + (screen.Width / 2) - (window.Width / 2), + => screen.X + (screen.Width / 2) - (window.Width * dpi / 2), Position.TopLeft or Position.Left or Position.BottomLeft => screen.X + offset, Position.TopRight or Position.Right or Position.BottomRight - => screen.X + screen.Width - (window.Width + offset), + => screen.X + screen.Width - ((window.Width * dpi) + offset), _ => throw new NotImplementedException(), }; @@ -38,9 +38,9 @@ namespace PowerAccent.Core.Tools Position.TopLeft or Position.Top or Position.TopRight => screen.Y + offset, Position.Left or Position.Center or Position.Right - => screen.Y + (screen.Height / 2) - (window.Height / 2), + => screen.Y + (screen.Height / 2) - (window.Height * dpi / 2), Position.BottomLeft or Position.Bottom or Position.BottomRight - => screen.Y + screen.Height - (window.Height + offset), + => screen.Y + screen.Height - ((window.Height * dpi) + offset), _ => throw new NotImplementedException(), }; diff --git a/src/modules/poweraccent/PowerAccent.Core/Tools/CharactersUsageInfo.cs b/src/modules/poweraccent/PowerAccent.Core/Tools/CharactersUsageInfo.cs index 492a9828d9..ef2fa1db7e 100644 --- a/src/modules/poweraccent/PowerAccent.Core/Tools/CharactersUsageInfo.cs +++ b/src/modules/poweraccent/PowerAccent.Core/Tools/CharactersUsageInfo.cs @@ -19,7 +19,7 @@ namespace PowerAccent.Core.Tools public CharactersUsageInfo() { - _filePath = new SettingsUtils().GetSettingsFilePath(PowerAccentSettings.ModuleName, "UsageInfo.json"); + _filePath = SettingsUtils.Default.GetSettingsFilePath(PowerAccentSettings.ModuleName, "UsageInfo.json"); var data = GetUsageInfoData(); _characterUsageCounters = data.CharacterUsageCounters; _characterUsageTimestamp = data.CharacterUsageTimestamp; diff --git a/src/modules/poweraccent/PowerAccent.UI/Selector.xaml.cs b/src/modules/poweraccent/PowerAccent.UI/Selector.xaml.cs index 311417851a..7eed6a9a1b 100644 --- a/src/modules/poweraccent/PowerAccent.UI/Selector.xaml.cs +++ b/src/modules/poweraccent/PowerAccent.UI/Selector.xaml.cs @@ -59,6 +59,7 @@ public partial class Selector : FluentWindow, IDisposable, INotifyPropertyChange _selectedIndex = index; characters.SelectedIndex = _selectedIndex; characterName.Text = _powerAccent.CharacterDescriptions[_selectedIndex]; + characters.ScrollIntoView(character); } private void PowerAccent_OnChangeDisplay(bool isActive, string[] chars) @@ -73,6 +74,7 @@ public partial class Selector : FluentWindow, IDisposable, INotifyPropertyChange characters.ItemsSource = chars; characters.SelectedIndex = _selectedIndex; this.UpdateLayout(); // Required for filling the actual width/height before positioning. + SetWindowsSize(); SetWindowPosition(); Show(); Microsoft.PowerToys.Telemetry.PowerToysTelemetry.Log.WriteEvent(new PowerAccent.Core.Telemetry.PowerAccentShowAccentMenuEvent()); @@ -96,6 +98,11 @@ public partial class Selector : FluentWindow, IDisposable, INotifyPropertyChange this.Top = position.Y; } + private void SetWindowsSize() + { + this.characters.MaxWidth = _powerAccent.GetDisplayMaxWidth(); + } + protected override void OnClosed(EventArgs e) { _powerAccent.SaveUsageInfo(); diff --git a/src/modules/powerrename/PowerRenameUILib/PowerRenameUI.vcxproj b/src/modules/powerrename/PowerRenameUILib/PowerRenameUI.vcxproj index eb21a94049..de71eb2188 100644 --- a/src/modules/powerrename/PowerRenameUILib/PowerRenameUI.vcxproj +++ b/src/modules/powerrename/PowerRenameUILib/PowerRenameUI.vcxproj @@ -1,18 +1,16 @@  - - - - - - - - - - - - - + + + PackageReference + + + native,Version=v0.0 + + + Windows + $(WindowsTargetPlatformVersion) + true true @@ -37,9 +35,17 @@ true PowerToys.PowerRename.pri + win10-x64;win10-arm64 + false + + + + + + + - Application v143 @@ -212,54 +218,10 @@ - - - - - - - - - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - - - - - - - - - - - - - - - - - - - + - \ No newline at end of file + diff --git a/src/modules/previewpane/MonacoPreviewHandler/Settings.cs b/src/modules/previewpane/MonacoPreviewHandler/Settings.cs index 94eeab308f..80ee876104 100644 --- a/src/modules/previewpane/MonacoPreviewHandler/Settings.cs +++ b/src/modules/previewpane/MonacoPreviewHandler/Settings.cs @@ -16,7 +16,7 @@ namespace Microsoft.PowerToys.PreviewHandler.Monaco /// public class Settings { - private static SettingsUtils moduleSettings = new SettingsUtils(); + private static SettingsUtils moduleSettings = SettingsUtils.Default; /// /// Gets a value indicating whether word wrapping should be applied. Set by PT settings. diff --git a/src/modules/previewpane/StlThumbnailProvider/StlThumbnailProvider.cs b/src/modules/previewpane/StlThumbnailProvider/StlThumbnailProvider.cs index 2301c7beb0..d6dbd74251 100644 --- a/src/modules/previewpane/StlThumbnailProvider/StlThumbnailProvider.cs +++ b/src/modules/previewpane/StlThumbnailProvider/StlThumbnailProvider.cs @@ -155,7 +155,7 @@ namespace Microsoft.PowerToys.ThumbnailHandler.Stl { try { - var moduleSettings = new SettingsUtils(); + var moduleSettings = SettingsUtils.Default; var colorString = moduleSettings.GetSettings(PowerPreviewSettings.ModuleName).Properties.StlThumbnailColor.Value; diff --git a/src/modules/previewpane/SvgPreviewHandler/Settings.cs b/src/modules/previewpane/SvgPreviewHandler/Settings.cs index 925da8307a..dfde5bed03 100644 --- a/src/modules/previewpane/SvgPreviewHandler/Settings.cs +++ b/src/modules/previewpane/SvgPreviewHandler/Settings.cs @@ -8,7 +8,7 @@ namespace SvgPreviewHandler { internal sealed class Settings { - private static readonly SettingsUtils ModuleSettings = new SettingsUtils(); + private static readonly SettingsUtils ModuleSettings = SettingsUtils.Default; public int ColorMode { diff --git a/src/runner/packages.config b/src/runner/packages.config deleted file mode 100644 index 74d5ef5747..0000000000 --- a/src/runner/packages.config +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/runner/runner.base.rc b/src/runner/runner.base.rc index 367735ade45b0cdbe086a95fb5a2ce45f3cec744..55b4e13fdd3476cd015adeb718e40f73826ed8b7 100644 GIT binary patch delta 104 zcmbOuzDZ(33uAB~Ln%WhLo!1)g91Y$kWOYuWhe&17={uCA0RsoNb3ScbD*k}7<7Ot rJsDgW;u!)NLV+x225%tS5lA~TxH1GY1W&%mtUfu8S!#0=qZAhad!`iu delta 12 TcmdlaF-Lqu3*%-fCJ8P89h?KC diff --git a/src/runner/runner.vcxproj b/src/runner/runner.vcxproj index 1eae5a3573..35a68e220f 100644 --- a/src/runner/runner.vcxproj +++ b/src/runner/runner.vcxproj @@ -1,27 +1,34 @@  - + 81010002 + + + PackageReference + + native,Version=v0.0 + + Windows + $(WindowsTargetPlatformVersion) + 15.0 {9412D5C6-2CF2-4FC2-A601-B55508EA9B27} powertoys runner + + + + + + - - - - - - - - Application @@ -31,10 +38,6 @@ true - - - - @@ -140,39 +143,16 @@ - - - - - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - - - - - - - - - - - - + + + + + + + + + NotUsing + + \ No newline at end of file diff --git a/src/settings-ui/Settings.UI.Library/AdvancedPasteCustomActions.cs b/src/settings-ui/Settings.UI.Library/AdvancedPasteCustomActions.cs index 5ab4331393..87d74bae5f 100644 --- a/src/settings-ui/Settings.UI.Library/AdvancedPasteCustomActions.cs +++ b/src/settings-ui/Settings.UI.Library/AdvancedPasteCustomActions.cs @@ -10,7 +10,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library; public sealed class AdvancedPasteCustomActions { - private static readonly JsonSerializerOptions _serializerOptions = new() + private static readonly JsonSerializerOptions _serializerOptions = new(SettingsSerializationContext.Default.Options) { WriteIndented = true, }; diff --git a/src/settings-ui/Settings.UI.Library/AdvancedPasteProperties.cs b/src/settings-ui/Settings.UI.Library/AdvancedPasteProperties.cs index e3f6081266..9e2fa7ee12 100644 --- a/src/settings-ui/Settings.UI.Library/AdvancedPasteProperties.cs +++ b/src/settings-ui/Settings.UI.Library/AdvancedPasteProperties.cs @@ -104,6 +104,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library public PasteAIConfiguration PasteAIConfiguration { get; set; } public override string ToString() - => JsonSerializer.Serialize(this); + => JsonSerializer.Serialize(this, SettingsSerializationContext.Default.AdvancedPasteProperties); } } diff --git a/src/settings-ui/Settings.UI.Library/BasePTModuleSettings.cs b/src/settings-ui/Settings.UI.Library/BasePTModuleSettings.cs index ef99b37216..82869fd9aa 100644 --- a/src/settings-ui/Settings.UI.Library/BasePTModuleSettings.cs +++ b/src/settings-ui/Settings.UI.Library/BasePTModuleSettings.cs @@ -2,13 +2,32 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Text.Json; using System.Text.Json.Serialization; namespace Microsoft.PowerToys.Settings.UI.Library { + /// + /// Base class for all PowerToys module settings. + /// + /// + /// IMPORTANT for Native AOT compatibility: + /// When creating a new class that inherits from , + /// you MUST register it in by adding a + /// [JsonSerializable(typeof(YourNewSettingsClass))] attribute. + /// Failure to register the type will cause to throw + /// at runtime. + /// See for registration instructions. + /// public abstract class BasePTModuleSettings { + // Cached JsonSerializerOptions for Native AOT compatibility + private static readonly JsonSerializerOptions _jsonSerializerOptions = new JsonSerializerOptions + { + TypeInfoResolver = SettingsSerializationContext.Default, + }; + // Gets or sets name of the powertoy module. [JsonPropertyName("name")] public string Name { get; set; } @@ -17,11 +36,33 @@ namespace Microsoft.PowerToys.Settings.UI.Library [JsonPropertyName("version")] public string Version { get; set; } - // converts the current to a json string. + /// + /// Converts the current settings object to a JSON string. + /// + /// JSON string representation of this settings object. + /// + /// Thrown when the runtime type is not registered in . + /// All derived types must be registered with [JsonSerializable(typeof(YourType))] attribute. + /// + /// + /// This method uses Native AOT-compatible JSON serialization. The runtime type must be + /// registered in for serialization to work. + /// public virtual string ToJsonString() { // By default JsonSerializer will only serialize the properties in the base class. This can be avoided by passing the object type (more details at https://stackoverflow.com/a/62498888) - return JsonSerializer.Serialize(this, GetType()); + var runtimeType = GetType(); + + // For Native AOT compatibility, get JsonTypeInfo from the TypeInfoResolver + var typeInfo = _jsonSerializerOptions.TypeInfoResolver?.GetTypeInfo(runtimeType, _jsonSerializerOptions); + + if (typeInfo == null) + { + throw new InvalidOperationException($"Type {runtimeType.FullName} is not registered in SettingsSerializationContext. Please add it to the [JsonSerializable] attributes."); + } + + // Use AOT-friendly serialization + return JsonSerializer.Serialize(this, typeInfo); } public override int GetHashCode() diff --git a/src/settings-ui/Settings.UI.Library/BoolProperty.cs b/src/settings-ui/Settings.UI.Library/BoolProperty.cs index 6842770a79..96b0807dd1 100644 --- a/src/settings-ui/Settings.UI.Library/BoolProperty.cs +++ b/src/settings-ui/Settings.UI.Library/BoolProperty.cs @@ -37,7 +37,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public override string ToString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.BoolProperty); } public bool TryToCmdRepresentable(out string result) diff --git a/src/settings-ui/Settings.UI.Library/BoolPropertyJsonConverter.cs b/src/settings-ui/Settings.UI.Library/BoolPropertyJsonConverter.cs index 3cbc0b72b5..140bbffec1 100644 --- a/src/settings-ui/Settings.UI.Library/BoolPropertyJsonConverter.cs +++ b/src/settings-ui/Settings.UI.Library/BoolPropertyJsonConverter.cs @@ -12,14 +12,14 @@ namespace Microsoft.PowerToys.Settings.UI.Library { public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - var boolProperty = JsonSerializer.Deserialize(ref reader, options); + var boolProperty = JsonSerializer.Deserialize(ref reader, SettingsSerializationContext.Default.BoolProperty); return boolProperty.Value; } public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOptions options) { var boolProperty = new BoolProperty(value); - JsonSerializer.Serialize(writer, boolProperty, options); + JsonSerializer.Serialize(writer, boolProperty, SettingsSerializationContext.Default.BoolProperty); } } } diff --git a/src/settings-ui/Settings.UI.Library/CmdPalProperties.cs b/src/settings-ui/Settings.UI.Library/CmdPalProperties.cs index 9102609b6b..c738335827 100644 --- a/src/settings-ui/Settings.UI.Library/CmdPalProperties.cs +++ b/src/settings-ui/Settings.UI.Library/CmdPalProperties.cs @@ -43,7 +43,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library if (doc.RootElement.TryGetProperty(nameof(Hotkey), out JsonElement hotkeyElement)) { - Hotkey = JsonSerializer.Deserialize(hotkeyElement.GetRawText()); + Hotkey = JsonSerializer.Deserialize(hotkeyElement.GetRawText(), SettingsSerializationContext.Default.HotkeySettings); } } catch (Exception) diff --git a/src/settings-ui/Settings.UI.Library/ColorPickerProperties.cs b/src/settings-ui/Settings.UI.Library/ColorPickerProperties.cs index c4d870cfbd..45548791b6 100644 --- a/src/settings-ui/Settings.UI.Library/ColorPickerProperties.cs +++ b/src/settings-ui/Settings.UI.Library/ColorPickerProperties.cs @@ -87,6 +87,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library public bool ShowColorName { get; set; } public override string ToString() - => JsonSerializer.Serialize(this); + => JsonSerializer.Serialize(this, SettingsSerializationContext.Default.ColorPickerProperties); } } diff --git a/src/settings-ui/Settings.UI.Library/ColorPickerPropertiesVersion1.cs b/src/settings-ui/Settings.UI.Library/ColorPickerPropertiesVersion1.cs index 24f593213b..bc9f0d9f6f 100644 --- a/src/settings-ui/Settings.UI.Library/ColorPickerPropertiesVersion1.cs +++ b/src/settings-ui/Settings.UI.Library/ColorPickerPropertiesVersion1.cs @@ -54,6 +54,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library public bool ShowColorName { get; set; } public override string ToString() - => JsonSerializer.Serialize(this); + => JsonSerializer.Serialize(this, SettingsSerializationContext.Default.ColorPickerPropertiesVersion1); } } diff --git a/src/settings-ui/Settings.UI.Library/DoubleProperty.cs b/src/settings-ui/Settings.UI.Library/DoubleProperty.cs index 7854f70529..701268b3be 100644 --- a/src/settings-ui/Settings.UI.Library/DoubleProperty.cs +++ b/src/settings-ui/Settings.UI.Library/DoubleProperty.cs @@ -27,7 +27,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library // Returns a JSON version of the class settings configuration class. public override string ToString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.DoubleProperty); } } } diff --git a/src/settings-ui/Settings.UI.Library/FileLocksmithLocalProperties.cs b/src/settings-ui/Settings.UI.Library/FileLocksmithLocalProperties.cs index 747baf6dff..57e3d842c4 100644 --- a/src/settings-ui/Settings.UI.Library/FileLocksmithLocalProperties.cs +++ b/src/settings-ui/Settings.UI.Library/FileLocksmithLocalProperties.cs @@ -21,7 +21,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public string ToJsonString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.FileLocksmithLocalProperties); } // This function is required to implement the ISettingsConfig interface and obtain the settings configurations. diff --git a/src/settings-ui/Settings.UI.Library/FileLocksmithProperties.cs b/src/settings-ui/Settings.UI.Library/FileLocksmithProperties.cs index 3ec6e6d492..a6e37e9ba3 100644 --- a/src/settings-ui/Settings.UI.Library/FileLocksmithProperties.cs +++ b/src/settings-ui/Settings.UI.Library/FileLocksmithProperties.cs @@ -17,6 +17,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library [JsonPropertyName("bool_show_extended_menu")] public BoolProperty ExtendedContextMenuOnly { get; set; } - public override string ToString() => JsonSerializer.Serialize(this); + public override string ToString() => JsonSerializer.Serialize(this, SettingsSerializationContext.Default.FileLocksmithProperties); } } diff --git a/src/settings-ui/Settings.UI.Library/GeneralSettings.cs b/src/settings-ui/Settings.UI.Library/GeneralSettings.cs index 0f380aca78..8bd9390df7 100644 --- a/src/settings-ui/Settings.UI.Library/GeneralSettings.cs +++ b/src/settings-ui/Settings.UI.Library/GeneralSettings.cs @@ -119,7 +119,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library // converts the current to a json string. public string ToJsonString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.GeneralSettings); } private static string DefaultPowertoysVersion() diff --git a/src/settings-ui/Settings.UI.Library/GeneralSettingsCustomAction.cs b/src/settings-ui/Settings.UI.Library/GeneralSettingsCustomAction.cs index f180ca3186..d9cc2727e8 100644 --- a/src/settings-ui/Settings.UI.Library/GeneralSettingsCustomAction.cs +++ b/src/settings-ui/Settings.UI.Library/GeneralSettingsCustomAction.cs @@ -23,7 +23,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public override string ToString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.GeneralSettingsCustomAction); } } } diff --git a/src/settings-ui/Settings.UI.Library/Helpers/SunTimes.cs b/src/settings-ui/Settings.UI.Library/Helpers/SunTimes.cs index 2f4f31fc57..6c24d1c557 100644 --- a/src/settings-ui/Settings.UI.Library/Helpers/SunTimes.cs +++ b/src/settings-ui/Settings.UI.Library/Helpers/SunTimes.cs @@ -12,13 +12,18 @@ namespace Microsoft.PowerToys.Settings.UI.Library.Helpers { public struct SunTimes { - public int SunriseHour; - public int SunriseMinute; - public int SunsetHour; - public int SunsetMinute; - public string Text; + public int SunriseHour { get; set; } - public bool HasSunrise; - public bool HasSunset; + public int SunriseMinute { get; set; } + + public int SunsetHour { get; set; } + + public int SunsetMinute { get; set; } + + public string Text { get; set; } + + public bool HasSunrise { get; set; } + + public bool HasSunset { get; set; } } } diff --git a/src/settings-ui/Settings.UI.Library/ImageResizerProperties.cs b/src/settings-ui/Settings.UI.Library/ImageResizerProperties.cs index acef5a2f4d..90080d1c5a 100644 --- a/src/settings-ui/Settings.UI.Library/ImageResizerProperties.cs +++ b/src/settings-ui/Settings.UI.Library/ImageResizerProperties.cs @@ -86,7 +86,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public string ToJsonString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.ImageResizerProperties); } } diff --git a/src/settings-ui/Settings.UI.Library/ImageResizerSettings.cs b/src/settings-ui/Settings.UI.Library/ImageResizerSettings.cs index 97f785d6c2..f3dffca9a0 100644 --- a/src/settings-ui/Settings.UI.Library/ImageResizerSettings.cs +++ b/src/settings-ui/Settings.UI.Library/ImageResizerSettings.cs @@ -37,8 +37,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public override string ToJsonString() { - var options = _serializerOptions; - return JsonSerializer.Serialize(this, options); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.ImageResizerSettings); } public string GetModuleName() diff --git a/src/settings-ui/Settings.UI.Library/IntProperty.cs b/src/settings-ui/Settings.UI.Library/IntProperty.cs index ac6a87ad4a..63fae3e22b 100644 --- a/src/settings-ui/Settings.UI.Library/IntProperty.cs +++ b/src/settings-ui/Settings.UI.Library/IntProperty.cs @@ -42,7 +42,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library // Returns a JSON version of the class settings configuration class. public override string ToString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.IntProperty); } public static implicit operator IntProperty(int v) diff --git a/src/settings-ui/Settings.UI.Library/KeyboardManagerProfile.cs b/src/settings-ui/Settings.UI.Library/KeyboardManagerProfile.cs index 983f9a1f6a..091c70eb39 100644 --- a/src/settings-ui/Settings.UI.Library/KeyboardManagerProfile.cs +++ b/src/settings-ui/Settings.UI.Library/KeyboardManagerProfile.cs @@ -34,7 +34,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public string ToJsonString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.KeyboardManagerProfile); } public string GetModuleName() diff --git a/src/settings-ui/Settings.UI.Library/MeasureToolProperties.cs b/src/settings-ui/Settings.UI.Library/MeasureToolProperties.cs index 5edc9f9175..48fc544ed4 100644 --- a/src/settings-ui/Settings.UI.Library/MeasureToolProperties.cs +++ b/src/settings-ui/Settings.UI.Library/MeasureToolProperties.cs @@ -46,6 +46,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library public IntProperty DefaultMeasureStyle { get; set; } - public override string ToString() => JsonSerializer.Serialize(this); + public override string ToString() => JsonSerializer.Serialize(this, SettingsSerializationContext.Default.MeasureToolProperties); } } diff --git a/src/settings-ui/Settings.UI.Library/MouseWithoutBordersProperties.cs b/src/settings-ui/Settings.UI.Library/MouseWithoutBordersProperties.cs index e234ee6b2f..2970cdb654 100644 --- a/src/settings-ui/Settings.UI.Library/MouseWithoutBordersProperties.cs +++ b/src/settings-ui/Settings.UI.Library/MouseWithoutBordersProperties.cs @@ -15,8 +15,9 @@ namespace Microsoft.PowerToys.Settings.UI.Library public struct ConnectionRequest #pragma warning restore SA1649 // File name should match first type name { - public string PCName; - public string SecurityKey; + public string PCName { get; set; } + + public string SecurityKey { get; set; } } public struct NewKeyGenerationRequest diff --git a/src/settings-ui/Settings.UI.Library/NewPlusProperties.cs b/src/settings-ui/Settings.UI.Library/NewPlusProperties.cs index ccdbeb9601..c2ad8cc328 100644 --- a/src/settings-ui/Settings.UI.Library/NewPlusProperties.cs +++ b/src/settings-ui/Settings.UI.Library/NewPlusProperties.cs @@ -33,6 +33,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library [JsonPropertyName("ReplaceVariables")] public BoolProperty ReplaceVariables { get; set; } - public override string ToString() => JsonSerializer.Serialize(this); + public override string ToString() => JsonSerializer.Serialize(this, SettingsSerializationContext.Default.NewPlusProperties); } } diff --git a/src/settings-ui/Settings.UI.Library/OutGoingGeneralSettings.cs b/src/settings-ui/Settings.UI.Library/OutGoingGeneralSettings.cs index d040016660..dad5f02b25 100644 --- a/src/settings-ui/Settings.UI.Library/OutGoingGeneralSettings.cs +++ b/src/settings-ui/Settings.UI.Library/OutGoingGeneralSettings.cs @@ -23,7 +23,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public override string ToString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.OutGoingGeneralSettings); } } } diff --git a/src/settings-ui/Settings.UI.Library/OutGoingLanguageSettings.cs b/src/settings-ui/Settings.UI.Library/OutGoingLanguageSettings.cs index 61a16eb778..7f2d55faf6 100644 --- a/src/settings-ui/Settings.UI.Library/OutGoingLanguageSettings.cs +++ b/src/settings-ui/Settings.UI.Library/OutGoingLanguageSettings.cs @@ -23,7 +23,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public override string ToString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.OutGoingLanguageSettings); } } } diff --git a/src/settings-ui/Settings.UI.Library/PasteAIConfiguration.cs b/src/settings-ui/Settings.UI.Library/PasteAIConfiguration.cs index 3308ab535e..2b743c4670 100644 --- a/src/settings-ui/Settings.UI.Library/PasteAIConfiguration.cs +++ b/src/settings-ui/Settings.UI.Library/PasteAIConfiguration.cs @@ -64,7 +64,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public AIServiceType ActiveServiceTypeKind => ActiveProvider?.ServiceTypeKind ?? AIServiceType.OpenAI; public override string ToString() - => JsonSerializer.Serialize(this); + => JsonSerializer.Serialize(this, SettingsSerializationContext.Default.PasteAIConfiguration); protected bool SetProperty(ref T field, T value, [CallerMemberName] string propertyName = null) { diff --git a/src/settings-ui/Settings.UI.Library/PeekPreviewSettings.cs b/src/settings-ui/Settings.UI.Library/PeekPreviewSettings.cs index fa2fb3bf6c..b139076fe8 100644 --- a/src/settings-ui/Settings.UI.Library/PeekPreviewSettings.cs +++ b/src/settings-ui/Settings.UI.Library/PeekPreviewSettings.cs @@ -34,7 +34,7 @@ namespace Settings.UI.Library public string ToJsonString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, Microsoft.PowerToys.Settings.UI.Library.SettingsSerializationContext.Default.PeekPreviewSettings); } public string GetModuleName() diff --git a/src/settings-ui/Settings.UI.Library/PeekProperties.cs b/src/settings-ui/Settings.UI.Library/PeekProperties.cs index e6eea746d6..e8b8692888 100644 --- a/src/settings-ui/Settings.UI.Library/PeekProperties.cs +++ b/src/settings-ui/Settings.UI.Library/PeekProperties.cs @@ -32,6 +32,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library public BoolProperty EnableSpaceToActivate { get; set; } - public override string ToString() => JsonSerializer.Serialize(this); + public override string ToString() => JsonSerializer.Serialize(this, SettingsSerializationContext.Default.PeekProperties); } } diff --git a/src/settings-ui/Settings.UI.Library/PowerOcrProperties.cs b/src/settings-ui/Settings.UI.Library/PowerOcrProperties.cs index 5cba3cfb3e..1570038f22 100644 --- a/src/settings-ui/Settings.UI.Library/PowerOcrProperties.cs +++ b/src/settings-ui/Settings.UI.Library/PowerOcrProperties.cs @@ -24,6 +24,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library public string PreferredLanguage { get; set; } public override string ToString() - => JsonSerializer.Serialize(this); + => JsonSerializer.Serialize(this, SettingsSerializationContext.Default.PowerOcrProperties); } } diff --git a/src/settings-ui/Settings.UI.Library/PowerPreviewProperties.cs b/src/settings-ui/Settings.UI.Library/PowerPreviewProperties.cs index 72113e67fc..b99b19aae7 100644 --- a/src/settings-ui/Settings.UI.Library/PowerPreviewProperties.cs +++ b/src/settings-ui/Settings.UI.Library/PowerPreviewProperties.cs @@ -340,7 +340,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public override string ToString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.PowerPreviewProperties); } private static void LogTelemetryEvent(bool value, [CallerMemberName] string propertyName = null) diff --git a/src/settings-ui/Settings.UI.Library/PowerRenameLocalProperties.cs b/src/settings-ui/Settings.UI.Library/PowerRenameLocalProperties.cs index 726faf2bc0..cec4b472c7 100644 --- a/src/settings-ui/Settings.UI.Library/PowerRenameLocalProperties.cs +++ b/src/settings-ui/Settings.UI.Library/PowerRenameLocalProperties.cs @@ -54,7 +54,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public string ToJsonString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.PowerRenameLocalProperties); } // This function is required to implement the ISettingsConfig interface and obtain the settings configurations. diff --git a/src/settings-ui/Settings.UI.Library/SettingsBackupAndRestoreUtils.cs b/src/settings-ui/Settings.UI.Library/SettingsBackupAndRestoreUtils.cs index 10ebf74314..08708009d0 100644 --- a/src/settings-ui/Settings.UI.Library/SettingsBackupAndRestoreUtils.cs +++ b/src/settings-ui/Settings.UI.Library/SettingsBackupAndRestoreUtils.cs @@ -592,7 +592,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library /// public (bool Success, string Message, string Severity, bool LastBackupExists, string OptionalMessage) DryRunBackup() { - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; var appBasePath = Path.GetDirectoryName(settingsUtils.GetSettingsFilePath()); string settingsBackupAndRestoreDir = GetSettingsBackupAndRestoreDir(); var results = BackupSettings(appBasePath, settingsBackupAndRestoreDir, true); diff --git a/src/settings-ui/Settings.UI.Library/SettingsSerializationContext.cs b/src/settings-ui/Settings.UI.Library/SettingsSerializationContext.cs new file mode 100644 index 0000000000..8ffcfb2e7c --- /dev/null +++ b/src/settings-ui/Settings.UI.Library/SettingsSerializationContext.cs @@ -0,0 +1,172 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Text.Json.Serialization; +using SettingsUILibrary = Settings.UI.Library; +using SettingsUILibraryHelpers = Settings.UI.Library.Helpers; + +namespace Microsoft.PowerToys.Settings.UI.Library +{ + /// + /// JSON serialization context for Native AOT compatibility. + /// This context provides source-generated serialization for all PowerToys settings types. + /// + /// + /// ⚠️ CRITICAL REQUIREMENT FOR ALL NEW SETTINGS CLASSES ⚠️ + /// + /// When adding a new PowerToys module or any class that inherits from , + /// you MUST add a [JsonSerializable(typeof(YourNewSettingsClass))] attribute + /// to this class. This is a MANDATORY step for Native AOT compatibility. + /// + /// Steps to add a new settings class: + /// + /// Create your new settings class (e.g., MyNewModuleSettings) that inherits from + /// Add [JsonSerializable(typeof(MyNewModuleSettings))] attribute to this class + /// If you have a corresponding Properties class, also add [JsonSerializable(typeof(MyNewModuleProperties))] + /// Rebuild the project - source generator will create serialization code at compile time + /// + /// ⚠️ Failure to register types will cause runtime errors: + /// + /// If you forget to add the [JsonSerializable] attribute, calling ToJsonString() or + /// deserialization methods will throw at runtime with a clear + /// error message indicating which type is missing registration. + /// + /// + [JsonSourceGenerationOptions( + WriteIndented = false, + DefaultIgnoreCondition = JsonIgnoreCondition.Never, + IncludeFields = true)] + + // Main Settings Classes + [JsonSerializable(typeof(GeneralSettings))] + [JsonSerializable(typeof(AdvancedPasteSettings))] + [JsonSerializable(typeof(AlwaysOnTopSettings))] + [JsonSerializable(typeof(AwakeSettings))] + [JsonSerializable(typeof(CmdNotFoundSettings))] + [JsonSerializable(typeof(ColorPickerSettings))] + [JsonSerializable(typeof(ColorPickerSettingsVersion1))] + [JsonSerializable(typeof(CropAndLockSettings))] + [JsonSerializable(typeof(CursorWrapSettings))] + [JsonSerializable(typeof(EnvironmentVariablesSettings))] + [JsonSerializable(typeof(FancyZonesSettings))] + [JsonSerializable(typeof(FileLocksmithSettings))] + [JsonSerializable(typeof(FindMyMouseSettings))] + [JsonSerializable(typeof(HostsSettings))] + [JsonSerializable(typeof(ImageResizerSettings))] + [JsonSerializable(typeof(KeyboardManagerSettings))] + [JsonSerializable(typeof(SettingsUILibrary.LightSwitchSettings))] + [JsonSerializable(typeof(MeasureToolSettings))] + [JsonSerializable(typeof(MouseHighlighterSettings))] + [JsonSerializable(typeof(MouseJumpSettings))] + [JsonSerializable(typeof(MousePointerCrosshairsSettings))] + [JsonSerializable(typeof(MouseWithoutBordersSettings))] + [JsonSerializable(typeof(NewPlusSettings))] + [JsonSerializable(typeof(PeekSettings))] + [JsonSerializable(typeof(PowerAccentSettings))] + [JsonSerializable(typeof(PowerLauncherSettings))] + [JsonSerializable(typeof(PowerOcrSettings))] + [JsonSerializable(typeof(PowerPreviewSettings))] + [JsonSerializable(typeof(PowerRenameSettings))] + [JsonSerializable(typeof(RegistryPreviewSettings))] + [JsonSerializable(typeof(ShortcutGuideSettings))] + [JsonSerializable(typeof(WorkspacesSettings))] + [JsonSerializable(typeof(ZoomItSettings))] + + // Properties Classes + [JsonSerializable(typeof(AdvancedPasteProperties))] + [JsonSerializable(typeof(AlwaysOnTopProperties))] + [JsonSerializable(typeof(AwakeProperties))] + [JsonSerializable(typeof(CmdPalProperties))] + [JsonSerializable(typeof(ColorPickerProperties))] + [JsonSerializable(typeof(ColorPickerPropertiesVersion1))] + [JsonSerializable(typeof(CropAndLockProperties))] + [JsonSerializable(typeof(CursorWrapProperties))] + [JsonSerializable(typeof(EnvironmentVariablesProperties))] + [JsonSerializable(typeof(FileLocksmithProperties))] + [JsonSerializable(typeof(FileLocksmithLocalProperties))] + [JsonSerializable(typeof(FindMyMouseProperties))] + [JsonSerializable(typeof(FZConfigProperties))] + [JsonSerializable(typeof(HostsProperties))] + [JsonSerializable(typeof(ImageResizerProperties))] + [JsonSerializable(typeof(KeyboardManagerProperties))] + [JsonSerializable(typeof(KeyboardManagerProfile))] + [JsonSerializable(typeof(LightSwitchProperties))] + [JsonSerializable(typeof(MeasureToolProperties))] + [JsonSerializable(typeof(MouseHighlighterProperties))] + [JsonSerializable(typeof(MouseJumpProperties))] + [JsonSerializable(typeof(MousePointerCrosshairsProperties))] + [JsonSerializable(typeof(MouseWithoutBordersProperties))] + [JsonSerializable(typeof(NewPlusProperties))] + [JsonSerializable(typeof(PeekProperties))] + [JsonSerializable(typeof(SettingsUILibrary.PeekPreviewSettings))] + [JsonSerializable(typeof(PowerAccentProperties))] + [JsonSerializable(typeof(PowerLauncherProperties))] + [JsonSerializable(typeof(PowerOcrProperties))] + [JsonSerializable(typeof(PowerPreviewProperties))] + [JsonSerializable(typeof(PowerRenameProperties))] + [JsonSerializable(typeof(PowerRenameLocalProperties))] + [JsonSerializable(typeof(RegistryPreviewProperties))] + [JsonSerializable(typeof(ShortcutConflictProperties))] + [JsonSerializable(typeof(ShortcutGuideProperties))] + [JsonSerializable(typeof(WorkspacesProperties))] + [JsonSerializable(typeof(ZoomItProperties))] + + // Base Property Types (used throughout settings) + [JsonSerializable(typeof(BoolProperty))] + [JsonSerializable(typeof(StringProperty))] + [JsonSerializable(typeof(IntProperty))] + [JsonSerializable(typeof(DoubleProperty))] + + // Helper and Utility Types + [JsonSerializable(typeof(HotkeySettings))] + [JsonSerializable(typeof(ColorFormatModel))] + [JsonSerializable(typeof(ImageSize))] + [JsonSerializable(typeof(KeysDataModel))] + [JsonSerializable(typeof(EnabledModules))] + [JsonSerializable(typeof(GeneralSettingsCustomAction))] + [JsonSerializable(typeof(OutGoingGeneralSettings))] + [JsonSerializable(typeof(OutGoingLanguageSettings))] + [JsonSerializable(typeof(AdvancedPasteCustomActions))] + [JsonSerializable(typeof(AdvancedPasteAdditionalActions))] + [JsonSerializable(typeof(AdvancedPasteCustomAction))] + [JsonSerializable(typeof(AdvancedPasteAdditionalAction))] + [JsonSerializable(typeof(AdvancedPastePasteAsFileAction))] + [JsonSerializable(typeof(AdvancedPasteTranscodeAction))] + [JsonSerializable(typeof(PasteAIConfiguration))] + [JsonSerializable(typeof(PasteAIProviderDefinition))] + [JsonSerializable(typeof(ImageResizerSizes))] + [JsonSerializable(typeof(ImageResizerCustomSizeProperty))] + [JsonSerializable(typeof(KeyboardKeysProperty))] + [JsonSerializable(typeof(SettingsUILibraryHelpers.SearchLocation))] + + // IPC Send Message Wrapper Classes (Snd*) + [JsonSerializable(typeof(SndAwakeSettings))] + [JsonSerializable(typeof(SndCursorWrapSettings))] + [JsonSerializable(typeof(SndFindMyMouseSettings))] + [JsonSerializable(typeof(SndLightSwitchSettings))] + [JsonSerializable(typeof(SndMouseHighlighterSettings))] + [JsonSerializable(typeof(SndMouseJumpSettings))] + [JsonSerializable(typeof(SndMousePointerCrosshairsSettings))] + [JsonSerializable(typeof(SndPowerAccentSettings))] + [JsonSerializable(typeof(SndPowerPreviewSettings))] + [JsonSerializable(typeof(SndPowerRenameSettings))] + [JsonSerializable(typeof(SndShortcutGuideSettings))] + + // IPC Message Generic Wrapper Types (SndModuleSettings) + [JsonSerializable(typeof(SndModuleSettings))] + [JsonSerializable(typeof(SndModuleSettings))] + [JsonSerializable(typeof(SndModuleSettings))] + [JsonSerializable(typeof(SndModuleSettings))] + [JsonSerializable(typeof(SndModuleSettings))] + [JsonSerializable(typeof(SndModuleSettings))] + [JsonSerializable(typeof(SndModuleSettings))] + [JsonSerializable(typeof(SndModuleSettings))] + [JsonSerializable(typeof(SndModuleSettings))] + [JsonSerializable(typeof(SndModuleSettings))] + [JsonSerializable(typeof(SndModuleSettings))] + + public partial class SettingsSerializationContext : JsonSerializerContext + { + } +} diff --git a/src/settings-ui/Settings.UI.Library/SettingsUtils.cs b/src/settings-ui/Settings.UI.Library/SettingsUtils.cs index ea466f7077..eb4169f422 100644 --- a/src/settings-ui/Settings.UI.Library/SettingsUtils.cs +++ b/src/settings-ui/Settings.UI.Library/SettingsUtils.cs @@ -2,6 +2,8 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable + using System; using System.IO; using System.IO.Abstractions; @@ -18,27 +20,35 @@ namespace Microsoft.PowerToys.Settings.UI.Library private const string DefaultModuleName = ""; private readonly IFile _file; private readonly ISettingsPath _settingsPath; + private readonly JsonSerializerOptions _serializerOptions; - private static readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions - { - MaxDepth = 0, - IncludeFields = true, - }; + /// + /// Gets the default instance of the class for general use. + /// Same as instantiating a new instance with the constructor with a new object as the first argument and null as the second argument. + /// + /// For using in tests, you should use one of the public constructors. + public static SettingsUtils Default { get; } = new SettingsUtils(); - public SettingsUtils() + private SettingsUtils() : this(new FileSystem()) { } - public SettingsUtils(IFileSystem fileSystem) - : this(fileSystem?.File, new SettingPath(fileSystem?.Directory, fileSystem?.Path)) + public SettingsUtils(IFileSystem? fileSystem, JsonSerializerOptions? serializerOptions = null) + : this(fileSystem?.File!, new SettingPath(fileSystem?.Directory, fileSystem?.Path), serializerOptions) { } - public SettingsUtils(IFile file, ISettingsPath settingPath) + public SettingsUtils(IFile file, ISettingsPath settingPath, JsonSerializerOptions? serializerOptions = null) { _file = file ?? throw new ArgumentNullException(nameof(file)); _settingsPath = settingPath; + _serializerOptions = serializerOptions ?? new JsonSerializerOptions + { + MaxDepth = 0, + IncludeFields = true, + TypeInfoResolver = SettingsSerializationContext.Default, + }; } public bool SettingsExists(string powertoy = DefaultModuleName, string fileName = DefaultFileName) @@ -108,7 +118,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library /// This function creates a file in the powertoy folder if it does not exist and returns an object with default properties. /// /// Deserialized json settings object. - public T GetSettingsOrDefault(string powertoy = DefaultModuleName, string fileName = DefaultFileName, Func settingsUpgrader = null) + public T GetSettingsOrDefault(string powertoy = DefaultModuleName, string fileName = DefaultFileName, Func? settingsUpgrader = null) where T : ISettingsConfig, new() where T2 : ISettingsConfig, new() { @@ -128,7 +138,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library try { T2 oldSettings = GetSettings(powertoy, fileName); - T newSettings = (T)settingsUpgrader(oldSettings); + T newSettings = (T)settingsUpgrader!(oldSettings); Logger.LogInfo($"Settings file {fileName} for {powertoy} was read successfully in the old format."); // If the file needs to be modified, to save the new configurations accordingly. @@ -156,7 +166,22 @@ namespace Microsoft.PowerToys.Settings.UI.Library return newSettingsItem; } - // Given the powerToy folder name and filename to be accessed, this function deserializes and returns the file. + /// + /// Deserializes settings from a JSON file. + /// + /// The settings type to deserialize. Must be registered in . + /// The PowerToy module folder name. + /// The settings file name. + /// Deserialized settings object of type T. + /// + /// Thrown when type T is not registered in . + /// All settings types must be registered with [JsonSerializable(typeof(T))] attribute + /// for Native AOT compatibility. + /// + /// + /// This method uses Native AOT-compatible JSON deserialization. Type T must be registered + /// in before calling this method. + /// private T GetFile(string powertoyFolderName = DefaultModuleName, string fileName = DefaultFileName) { // Adding Trim('\0') to overcome possible NTFS file corruption. @@ -165,8 +190,16 @@ namespace Microsoft.PowerToys.Settings.UI.Library // The file itself did write the content correctly but something is off with the actual end of the file, hence the 0x00 bug var jsonSettingsString = _file.ReadAllText(_settingsPath.GetSettingsPath(powertoyFolderName, fileName)).Trim('\0'); - var options = _serializerOptions; - return JsonSerializer.Deserialize(jsonSettingsString, options); + // For Native AOT compatibility, get JsonTypeInfo from the TypeInfoResolver + var typeInfo = _serializerOptions.TypeInfoResolver?.GetTypeInfo(typeof(T), _serializerOptions); + + if (typeInfo == null) + { + throw new InvalidOperationException($"Type {typeof(T).FullName} is not registered in SettingsSerializationContext. Please add it to the [JsonSerializable] attributes."); + } + + // Use AOT-friendly deserialization + return (T)JsonSerializer.Deserialize(jsonSettingsString, typeInfo)!; } // Save settings to a json file. @@ -208,7 +241,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public static (bool Success, string Message, string Severity, bool LastBackupExists, string OptionalMessage) BackupSettings() { var settingsBackupAndRestoreUtilsX = SettingsBackupAndRestoreUtils.Instance; - var settingsUtils = new SettingsUtils(); + var settingsUtils = Default; var appBasePath = Path.GetDirectoryName(settingsUtils._settingsPath.GetSettingsPath(string.Empty, string.Empty)); string settingsBackupAndRestoreDir = settingsBackupAndRestoreUtilsX.GetSettingsBackupAndRestoreDir(); @@ -221,7 +254,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public static (bool Success, string Message, string Severity) RestoreSettings() { var settingsBackupAndRestoreUtilsX = SettingsBackupAndRestoreUtils.Instance; - var settingsUtils = new SettingsUtils(); + var settingsUtils = Default; var appBasePath = Path.GetDirectoryName(settingsUtils._settingsPath.GetSettingsPath(string.Empty, string.Empty)); string settingsBackupAndRestoreDir = settingsBackupAndRestoreUtilsX.GetSettingsBackupAndRestoreDir(); return settingsBackupAndRestoreUtilsX.RestoreSettings(appBasePath, settingsBackupAndRestoreDir); diff --git a/src/settings-ui/Settings.UI.Library/StringProperty.cs b/src/settings-ui/Settings.UI.Library/StringProperty.cs index 8b0d86b177..5d521189dc 100644 --- a/src/settings-ui/Settings.UI.Library/StringProperty.cs +++ b/src/settings-ui/Settings.UI.Library/StringProperty.cs @@ -27,7 +27,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library // Returns a JSON version of the class settings configuration class. public override string ToString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.StringProperty); } public static StringProperty ToStringProperty(string v) diff --git a/src/settings-ui/Settings.UI.Library/Utilities/GetSettingCommandLineCommand.cs b/src/settings-ui/Settings.UI.Library/Utilities/GetSettingCommandLineCommand.cs index a4ad1d1862..5780b95392 100644 --- a/src/settings-ui/Settings.UI.Library/Utilities/GetSettingCommandLineCommand.cs +++ b/src/settings-ui/Settings.UI.Library/Utilities/GetSettingCommandLineCommand.cs @@ -48,7 +48,7 @@ public sealed class GetSettingCommandLineCommand var modulesSettings = new Dictionary>(); var settingsAssembly = CommandLineUtils.GetSettingsAssembly(); - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; var enabledModules = SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Enabled; diff --git a/src/settings-ui/Settings.UI.UnitTests/ModelsTests/BasePTModuleSettingsSerializationTests.cs b/src/settings-ui/Settings.UI.UnitTests/ModelsTests/BasePTModuleSettingsSerializationTests.cs new file mode 100644 index 0000000000..29fe1d0508 --- /dev/null +++ b/src/settings-ui/Settings.UI.UnitTests/ModelsTests/BasePTModuleSettingsSerializationTests.cs @@ -0,0 +1,127 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Linq; +using System.Reflection; +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.PowerToys.Settings.UI.Library; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace CommonLibTest +{ + [TestClass] + public class BasePTModuleSettingsSerializationTests + { + /// + /// Test to verify that all classes derived from BasePTModuleSettings are registered + /// in the SettingsSerializationContext for Native AOT compatibility. + /// + [TestMethod] + public void AllBasePTModuleSettingsClasses_ShouldBeRegisteredInSerializationContext() + { + // Arrange + var assembly = typeof(BasePTModuleSettings).Assembly; + var settingsClasses = assembly.GetTypes() + .Where(t => typeof(BasePTModuleSettings).IsAssignableFrom(t) && !t.IsAbstract && t != typeof(BasePTModuleSettings)) + .OrderBy(t => t.Name) + .ToList(); + + Assert.IsTrue(settingsClasses.Count > 0, "No BasePTModuleSettings derived classes found. This test may be broken."); + + var jsonSerializerOptions = new JsonSerializerOptions + { + TypeInfoResolver = SettingsSerializationContext.Default, + }; + + var unregisteredTypes = new System.Collections.Generic.List(); + + // Act & Assert + foreach (var settingsType in settingsClasses) + { + var typeInfo = jsonSerializerOptions.TypeInfoResolver?.GetTypeInfo(settingsType, jsonSerializerOptions); + + if (typeInfo == null) + { + unregisteredTypes.Add(settingsType.FullName ?? settingsType.Name); + } + } + + // Assert + if (unregisteredTypes.Count > 0) + { + var errorMessage = $"The following {unregisteredTypes.Count} settings class(es) are NOT registered in SettingsSerializationContext:\n" + + $"{string.Join("\n", unregisteredTypes.Select(t => $" - {t}"))}\n\n" + + $"Please add [JsonSerializable(typeof(ClassName))] attribute to SettingsSerializationContext.cs for each missing type."; + Assert.Fail(errorMessage); + } + + // Print success message with count + Console.WriteLine($"✓ All {settingsClasses.Count} BasePTModuleSettings derived classes are properly registered in SettingsSerializationContext."); + } + + /// + /// Test to verify that calling ToJsonString() on an unregistered type throws InvalidOperationException + /// with a helpful error message. + /// + [TestMethod] + [ExpectedException(typeof(InvalidOperationException))] + public void ToJsonString_UnregisteredType_ShouldThrowInvalidOperationException() + { + // Arrange + var unregisteredSettings = new UnregisteredTestSettings + { + Name = "UnregisteredModule", + Version = "1.0.0", + }; + + // Act - This should throw InvalidOperationException + var jsonString = unregisteredSettings.ToJsonString(); + + // Assert - Exception should be thrown, so this line should never be reached + Assert.Fail("Expected InvalidOperationException was not thrown."); + } + + /// + /// Test to verify that the error message for unregistered types is helpful and contains + /// necessary information for developers. + /// + [TestMethod] + public void ToJsonString_UnregisteredType_ShouldHaveHelpfulErrorMessage() + { + // Arrange + var unregisteredSettings = new UnregisteredTestSettings + { + Name = "UnregisteredModule", + Version = "1.0.0", + }; + + // Act & Assert + try + { + var jsonString = unregisteredSettings.ToJsonString(); + Assert.Fail("Expected InvalidOperationException was not thrown."); + } + catch (InvalidOperationException ex) + { + // Verify the error message contains helpful information + Assert.IsTrue(ex.Message.Contains("UnregisteredTestSettings"), "Error message should contain the type name."); + Assert.IsTrue(ex.Message.Contains("SettingsSerializationContext"), "Error message should mention SettingsSerializationContext."); + Assert.IsTrue(ex.Message.Contains("JsonSerializable"), "Error message should mention JsonSerializable attribute."); + + Console.WriteLine($"✓ Error message is helpful: {ex.Message}"); + } + } + + /// + /// Test class that is intentionally NOT registered in SettingsSerializationContext + /// to verify error handling for unregistered types. + /// + private sealed class UnregisteredTestSettings : BasePTModuleSettings + { + // Intentionally empty - this class should NOT be registered in SettingsSerializationContext + } + } +} diff --git a/src/settings-ui/Settings.UI.UnitTests/ModelsTests/BasePTSettingsTest.cs b/src/settings-ui/Settings.UI.UnitTests/ModelsTests/BasePTSettingsTest.cs index 8d73d2a6ee..c4e92fb322 100644 --- a/src/settings-ui/Settings.UI.UnitTests/ModelsTests/BasePTSettingsTest.cs +++ b/src/settings-ui/Settings.UI.UnitTests/ModelsTests/BasePTSettingsTest.cs @@ -2,8 +2,10 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Text.Json; using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library.Interfaces; +using Microsoft.PowerToys.Settings.UI.UnitTests; namespace Microsoft.PowerToys.Settings.UnitTest { @@ -24,5 +26,11 @@ namespace Microsoft.PowerToys.Settings.UnitTest { return false; } + + // Override ToJsonString to use test-specific serialization context + public override string ToJsonString() + { + return JsonSerializer.Serialize(this, TestSettingsSerializationContext.Default.BasePTSettingsTest); + } } } diff --git a/src/settings-ui/Settings.UI.UnitTests/ModelsTests/SettingsUtilsTests.cs b/src/settings-ui/Settings.UI.UnitTests/ModelsTests/SettingsUtilsTests.cs index 9b75925cb8..37dfcee4d8 100644 --- a/src/settings-ui/Settings.UI.UnitTests/ModelsTests/SettingsUtilsTests.cs +++ b/src/settings-ui/Settings.UI.UnitTests/ModelsTests/SettingsUtilsTests.cs @@ -9,6 +9,7 @@ using System.Text.Json; using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library.Interfaces; +using Microsoft.PowerToys.Settings.UI.UnitTests; using Microsoft.PowerToys.Settings.UnitTest; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -22,7 +23,13 @@ namespace CommonLibTest { // Arrange var mockFileSystem = new MockFileSystem(); - var settingsUtils = new SettingsUtils(mockFileSystem); + var testSerializerOptions = new JsonSerializerOptions + { + MaxDepth = 0, + IncludeFields = true, + TypeInfoResolver = TestSettingsSerializationContext.Default, + }; + var settingsUtils = new SettingsUtils(mockFileSystem, testSerializerOptions); string file_name = "\\test"; string file_contents_correct_json_content = "{\"name\":\"powertoy module name\",\"version\":\"powertoy version\"}"; @@ -42,7 +49,13 @@ namespace CommonLibTest { // Arrange var mockFileSystem = new MockFileSystem(); - var settingsUtils = new SettingsUtils(mockFileSystem); + var testSerializerOptions = new JsonSerializerOptions + { + MaxDepth = 0, + IncludeFields = true, + TypeInfoResolver = TestSettingsSerializationContext.Default, + }; + var settingsUtils = new SettingsUtils(mockFileSystem, testSerializerOptions); string file_name = "test\\Test Folder"; string file_contents_correct_json_content = "{\"name\":\"powertoy module name\",\"version\":\"powertoy version\"}"; diff --git a/src/settings-ui/Settings.UI.UnitTests/TestSettingsSerializationContext.cs b/src/settings-ui/Settings.UI.UnitTests/TestSettingsSerializationContext.cs new file mode 100644 index 0000000000..bf38245105 --- /dev/null +++ b/src/settings-ui/Settings.UI.UnitTests/TestSettingsSerializationContext.cs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Text.Json.Serialization; +using Microsoft.PowerToys.Settings.UnitTest; + +namespace Microsoft.PowerToys.Settings.UI.UnitTests +{ + /// + /// JSON serialization context for unit tests. + /// This context provides source-generated serialization for test-specific types. + /// + [JsonSourceGenerationOptions( + WriteIndented = false, + DefaultIgnoreCondition = JsonIgnoreCondition.Never, + IncludeFields = true)] + [JsonSerializable(typeof(BasePTSettingsTest))] + public partial class TestSettingsSerializationContext : JsonSerializerContext + { + } +} diff --git a/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/ColorPicker.cs b/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/ColorPicker.cs index baf46827c4..19e2ca3b67 100644 --- a/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/ColorPicker.cs +++ b/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/ColorPicker.cs @@ -67,7 +67,7 @@ namespace ViewModelTests using (var viewModel = new ColorPickerViewModel( ISettingsUtilsMocks.GetStubSettingsUtils().Object, SettingsRepository.GetInstance(ISettingsUtilsMocks.GetStubSettingsUtils().Object), - SettingsRepository.GetInstance(new SettingsUtils()), + SettingsRepository.GetInstance(SettingsUtils.Default), ColorPickerIsEnabledByDefaultIPC)) { Assert.IsTrue(viewModel.IsEnabled); diff --git a/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/FancyZones.cs b/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/FancyZones.cs index ef230bde0a..bf8f9396c4 100644 --- a/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/FancyZones.cs +++ b/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/FancyZones.cs @@ -3,9 +3,11 @@ // See the LICENSE file in the project root for more information. using System; +using System.IO.Abstractions; using System.Text.Json; using Microsoft.PowerToys.Settings.UI.Library; +using Microsoft.PowerToys.Settings.UI.Library.Interfaces; using Microsoft.PowerToys.Settings.UI.UnitTests.BackwardsCompatibility; using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks; using Microsoft.PowerToys.Settings.UI.ViewModels; @@ -100,10 +102,26 @@ namespace ViewModelTests mockFancyZonesSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils(); } + [TestCleanup] + public void CleanUp() + { + // Reset singleton instances to prevent state pollution between tests + ResetSettingsRepository(); + ResetSettingsRepository(); + } + + private void ResetSettingsRepository() + where T : class, ISettingsConfig, new() + { + var repositoryType = typeof(SettingsRepository); + var field = repositoryType.GetField("settingsRepository", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); + field?.SetValue(null, null); + } + [TestMethod] public void IsEnabledShouldDisableModuleWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); Func sendMockIPCConfigMSG = msg => { @@ -123,7 +141,7 @@ namespace ViewModelTests [TestMethod] public void ShiftDragShouldSetValue2FalseWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); @@ -141,7 +159,7 @@ namespace ViewModelTests [TestMethod] public void OverrideSnapHotkeysShouldSetValue2TrueWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); @@ -159,7 +177,7 @@ namespace ViewModelTests [TestMethod] public void MoveWindowsAcrossMonitorsShouldSetValue2TrueWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); @@ -177,7 +195,7 @@ namespace ViewModelTests [TestMethod] public void MoveWindowsBasedOnPositionShouldSetValue2TrueWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); @@ -200,7 +218,7 @@ namespace ViewModelTests [TestMethod] public void QuickLayoutSwitchShouldSetValue2FalseWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); @@ -218,7 +236,7 @@ namespace ViewModelTests [TestMethod] public void FlashZonesOnQuickSwitchShouldSetValue2FalseWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); @@ -236,7 +254,7 @@ namespace ViewModelTests [TestMethod] public void MakeDraggedWindowsTransparentShouldSetValue2TrueWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); @@ -254,7 +272,7 @@ namespace ViewModelTests [TestMethod] public void MouseSwitchShouldSetValue2TrueWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); @@ -272,7 +290,7 @@ namespace ViewModelTests [TestMethod] public void DisplayOrWorkAreaChangeMoveWindowsShouldSetValue2FalseWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); @@ -290,7 +308,7 @@ namespace ViewModelTests [TestMethod] public void ZoneSetChangeMoveWindowsShouldSetValue2TrueWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); @@ -308,7 +326,7 @@ namespace ViewModelTests [TestMethod] public void AppLastZoneMoveWindowsShouldSetValue2TrueWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); @@ -326,7 +344,7 @@ namespace ViewModelTests [TestMethod] public void OpenWindowOnActiveMonitorShouldSetValue2TrueWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); @@ -344,7 +362,7 @@ namespace ViewModelTests [TestMethod] public void RestoreSizeShouldSetValue2TrueWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); @@ -362,7 +380,7 @@ namespace ViewModelTests [TestMethod] public void UseCursorPosEditorStartupScreenShouldSetValue2FalseWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); @@ -380,7 +398,7 @@ namespace ViewModelTests [TestMethod] public void ShowOnAllMonitorsShouldSetValue2TrueWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); @@ -398,7 +416,7 @@ namespace ViewModelTests [TestMethod] public void SpanZonesAcrossMonitorsShouldSetValue2TrueWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); @@ -416,7 +434,7 @@ namespace ViewModelTests [TestMethod] public void OverlappingZonesAlgorithmIndexShouldSetValue2AnotherWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); @@ -434,7 +452,7 @@ namespace ViewModelTests [TestMethod] public void AllowChildWindowsToSnapShouldSetValue2TrueWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); @@ -452,7 +470,7 @@ namespace ViewModelTests [TestMethod] public void DisableRoundCornersOnSnapShouldSetValue2TrueWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); @@ -470,7 +488,7 @@ namespace ViewModelTests [TestMethod] public void ZoneHighlightColorShouldSetColorValue2WhiteWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); @@ -488,7 +506,7 @@ namespace ViewModelTests [TestMethod] public void ZoneBorderColorShouldSetColorValue2WhiteWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); @@ -506,7 +524,7 @@ namespace ViewModelTests [TestMethod] public void ZoneInActiveColorShouldSetColorValue2WhiteWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); @@ -524,7 +542,7 @@ namespace ViewModelTests [TestMethod] public void ExcludedAppsShouldSetColorValue2WhiteWhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); @@ -542,7 +560,7 @@ namespace ViewModelTests [TestMethod] public void HighlightOpacityShouldSetOpacityValueTo60WhenSuccessful() { - Mock mockSettingsUtils = new Mock(); + Mock mockSettingsUtils = new Mock(new FileSystem(), null); // arrange FancyZonesViewModel viewModel = new FancyZonesViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), sendMockIPCConfigMSG, FancyZonesTestFolderName); diff --git a/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/ShortcutGuide.cs b/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/ShortcutGuide.cs index 3613d0cfa3..897fc2bec6 100644 --- a/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/ShortcutGuide.cs +++ b/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/ShortcutGuide.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.IO.Abstractions; using System.Text.Json; using Microsoft.PowerToys.Settings.UI.Library; @@ -69,7 +70,7 @@ namespace ViewModelTests [TestMethod] public void IsEnabledShouldEnableModuleWhenSuccessful() { - var settingsUtilsMock = new Mock(); + var settingsUtilsMock = new Mock(new FileSystem(), null); // Assert // Initialize mock function of sending IPC message. diff --git a/src/settings-ui/Settings.UI/Helpers/HotkeyConflictIgnoreHelper.cs b/src/settings-ui/Settings.UI/Helpers/HotkeyConflictIgnoreHelper.cs index d2e737180a..1397fca0b7 100644 --- a/src/settings-ui/Settings.UI/Helpers/HotkeyConflictIgnoreHelper.cs +++ b/src/settings-ui/Settings.UI/Helpers/HotkeyConflictIgnoreHelper.cs @@ -22,7 +22,7 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers static HotkeyConflictIgnoreHelper() { - _settingsUtils = new SettingsUtils(); + _settingsUtils = SettingsUtils.Default; _generalSettingsRepository = SettingsRepository.GetInstance(_settingsUtils); } diff --git a/src/settings-ui/Settings.UI/SerializationContext/SourceGenerationContextContext.cs b/src/settings-ui/Settings.UI/SerializationContext/SourceGenerationContextContext.cs index 838149a04e..dafd6d828b 100644 --- a/src/settings-ui/Settings.UI/SerializationContext/SourceGenerationContextContext.cs +++ b/src/settings-ui/Settings.UI/SerializationContext/SourceGenerationContextContext.cs @@ -10,7 +10,7 @@ using System.Text.Json.Serialization; using System.Threading.Tasks; using Microsoft.PowerToys.Settings.UI.Helpers; using Microsoft.PowerToys.Settings.UI.Library; -using Settings.UI.Library; +using SettingsUILibrary = Settings.UI.Library; namespace Microsoft.PowerToys.Settings.UI.SerializationContext; @@ -23,7 +23,7 @@ namespace Microsoft.PowerToys.Settings.UI.SerializationContext; [JsonSerializable(typeof(FileLocksmithSettings))] [JsonSerializable(typeof(FindMyMouseSettings))] [JsonSerializable(typeof(IList))] -[JsonSerializable(typeof(LightSwitchSettings))] +[JsonSerializable(typeof(SettingsUILibrary.LightSwitchSettings))] [JsonSerializable(typeof(MeasureToolSettings))] [JsonSerializable(typeof(MouseHighlighterSettings))] [JsonSerializable(typeof(MouseJumpSettings))] diff --git a/src/settings-ui/Settings.UI/SettingsXAML/App.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/App.xaml.cs index 19cd75b022..3189f15b31 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/App.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/App.xaml.cs @@ -133,7 +133,7 @@ namespace Microsoft.PowerToys.Settings.UI var settingValue = cmdArgs[3]; try { - SetSettingCommandLineCommand.Execute(settingName, settingValue, new SettingsUtils()); + SetSettingCommandLineCommand.Execute(settingName, settingValue, SettingsUtils.Default); } catch (Exception ex) { @@ -151,7 +151,7 @@ namespace Microsoft.PowerToys.Settings.UI { using (var settings = JsonDocument.Parse(File.ReadAllText(ipcFileName))) { - SetAdditionalSettingsCommandLineCommand.Execute(moduleName, settings, new SettingsUtils()); + SetAdditionalSettingsCommandLineCommand.Execute(moduleName, settings, SettingsUtils.Default); } } catch (Exception ex) @@ -357,7 +357,7 @@ namespace Microsoft.PowerToys.Settings.UI return 0; } - private static ISettingsUtils settingsUtils = new SettingsUtils(); + private static ISettingsUtils settingsUtils = SettingsUtils.Default; private static ThemeService themeService = new ThemeService(SettingsRepository.GetInstance(settingsUtils)); public static ThemeService ThemeService => themeService; diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/Dashboard/Card.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Controls/Dashboard/Card.xaml index 34abbe993d..9563bfceb3 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Controls/Dashboard/Card.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Controls/Dashboard/Card.xaml @@ -33,6 +33,7 @@ diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/Dashboard/ShortcutConflictWindow.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Controls/Dashboard/ShortcutConflictWindow.xaml.cs index b9bee4ff08..19a6cb06ad 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Controls/Dashboard/ShortcutConflictWindow.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Controls/Dashboard/ShortcutConflictWindow.xaml.cs @@ -26,7 +26,7 @@ namespace Microsoft.PowerToys.Settings.UI.SettingsXAML.Controls.Dashboard public ShortcutConflictWindow() { - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new ShortcutConflictViewModel( settingsUtils, SettingsRepository.GetInstance(settingsUtils), diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Flyout/AppsListPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Flyout/AppsListPage.xaml.cs index b58636f41b..fd034239e1 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Flyout/AppsListPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Flyout/AppsListPage.xaml.cs @@ -24,7 +24,7 @@ namespace Microsoft.PowerToys.Settings.UI.Flyout { this.InitializeComponent(); - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new AllAppsViewModel(SettingsRepository.GetInstance(settingsUtils), Views.ShellPage.SendDefaultIPCMessage); DataContext = ViewModel; } diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Flyout/LaunchPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Flyout/LaunchPage.xaml.cs index 51219309e0..f82da1466c 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Flyout/LaunchPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Flyout/LaunchPage.xaml.cs @@ -27,7 +27,7 @@ namespace Microsoft.PowerToys.Settings.UI.Flyout public LaunchPage() { this.InitializeComponent(); - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new LauncherViewModel(SettingsRepository.GetInstance(settingsUtils), Views.ShellPage.SendDefaultIPCMessage); DataContext = ViewModel; } @@ -51,7 +51,7 @@ namespace Microsoft.PowerToys.Settings.UI.Flyout break; case ModuleType.EnvironmentVariables: // Launch Environment Variables { - bool launchAdmin = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.LaunchAdministrator; + bool launchAdmin = SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.LaunchAdministrator; string eventName = !App.IsElevated && launchAdmin ? Constants.ShowEnvironmentVariablesAdminSharedEvent() : Constants.ShowEnvironmentVariablesSharedEvent(); @@ -74,7 +74,7 @@ namespace Microsoft.PowerToys.Settings.UI.Flyout case ModuleType.Hosts: // Launch Hosts { - bool launchAdmin = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.LaunchAdministrator; + bool launchAdmin = SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.LaunchAdministrator; string eventName = !App.IsElevated && launchAdmin ? Constants.ShowHostsAdminSharedEvent() : Constants.ShowHostsSharedEvent(); diff --git a/src/settings-ui/Settings.UI/SettingsXAML/MainWindow.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/MainWindow.xaml.cs index 90b2577268..27d5456418 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/MainWindow.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/MainWindow.xaml.cs @@ -81,7 +81,7 @@ namespace Microsoft.PowerToys.Settings.UI // open main window ShellPage.SetUpdatingGeneralSettingsCallback((ModuleType moduleType, bool isEnabled) => { - SettingsRepository repository = SettingsRepository.GetInstance(new SettingsUtils()); + SettingsRepository repository = SettingsRepository.GetInstance(SettingsUtils.Default); GeneralSettings generalSettingsConfig = repository.SettingsConfig; bool needToUpdate = ModuleHelper.GetIsModuleEnabled(generalSettingsConfig, moduleType) != isEnabled; diff --git a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeAdvancedPaste.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeAdvancedPaste.xaml.cs index 52cbc6cef2..73e25ed856 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeAdvancedPaste.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeAdvancedPaste.xaml.cs @@ -35,9 +35,9 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views protected override void OnNavigatedTo(NavigationEventArgs e) { ViewModel.LogOpeningModuleEvent(); - AdvancedPasteUIHotkeyControl.Keys = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.AdvancedPasteUIShortcut.GetKeysList(); - PasteAsPlainTextHotkeyControl.Keys = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.PasteAsPlainTextShortcut.GetKeysList(); - PasteAsMarkdownHotkeyControl.Keys = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.PasteAsMarkdownShortcut.GetKeysList(); + AdvancedPasteUIHotkeyControl.Keys = SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.AdvancedPasteUIShortcut.GetKeysList(); + PasteAsPlainTextHotkeyControl.Keys = SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.PasteAsPlainTextShortcut.GetKeysList(); + PasteAsMarkdownHotkeyControl.Keys = SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.PasteAsMarkdownShortcut.GetKeysList(); // TODO(stefan): Check how to remove additional space if item is set to Collapsed. if (PasteAsMarkdownHotkeyControl.Keys.Count > 0) @@ -45,7 +45,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views PasteAsMarkdownHotkeyControl.Visibility = Microsoft.UI.Xaml.Visibility.Visible; } - PasteAsJsonHotkeyControl.Keys = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.PasteAsJsonShortcut.GetKeysList(); + PasteAsJsonHotkeyControl.Keys = SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.PasteAsJsonShortcut.GetKeysList(); if (PasteAsJsonHotkeyControl.Keys.Count > 0) { PasteAsJsonHotkeyControl.Visibility = Microsoft.UI.Xaml.Visibility.Visible; diff --git a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeAlwaysOnTop.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeAlwaysOnTop.xaml.cs index d22392e717..08fb0f8a80 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeAlwaysOnTop.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeAlwaysOnTop.xaml.cs @@ -35,7 +35,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views protected override void OnNavigatedTo(NavigationEventArgs e) { ViewModel.LogOpeningModuleEvent(); - HotkeyControl.Keys = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.Hotkey.Value.GetKeysList(); + HotkeyControl.Keys = SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.Hotkey.Value.GetKeysList(); } protected override void OnNavigatedFrom(NavigationEventArgs e) diff --git a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeColorPicker.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeColorPicker.xaml.cs index 444b2d7295..8fd2bfb28d 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeColorPicker.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeColorPicker.xaml.cs @@ -50,7 +50,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views protected override void OnNavigatedTo(NavigationEventArgs e) { ViewModel.LogOpeningModuleEvent(); - ColorPickerSettings settings = new SettingsUtils().GetSettingsOrDefault(ColorPickerSettings.ModuleName, settingsUpgrader: ColorPickerSettings.UpgradeSettings); + ColorPickerSettings settings = SettingsUtils.Default.GetSettingsOrDefault(ColorPickerSettings.ModuleName, settingsUpgrader: ColorPickerSettings.UpgradeSettings); HotkeyControl.Keys = settings.Properties.ActivationShortcut.GetKeysList(); } diff --git a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeCropAndLock.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeCropAndLock.xaml.cs index be05925ec3..914dd647f6 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeCropAndLock.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeCropAndLock.xaml.cs @@ -35,8 +35,8 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views protected override void OnNavigatedTo(NavigationEventArgs e) { ViewModel.LogOpeningModuleEvent(); - ReparentHotkeyControl.Keys = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ReparentHotkey.Value.GetKeysList(); - ThumbnailHotkeyControl.Keys = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ThumbnailHotkey.Value.GetKeysList(); + ReparentHotkeyControl.Keys = SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.ReparentHotkey.Value.GetKeysList(); + ThumbnailHotkeyControl.Keys = SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.ThumbnailHotkey.Value.GetKeysList(); } protected override void OnNavigatedFrom(NavigationEventArgs e) diff --git a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeEnvironmentVariables.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeEnvironmentVariables.xaml.cs index af20978b42..3e2b66b9d6 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeEnvironmentVariables.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeEnvironmentVariables.xaml.cs @@ -37,7 +37,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views private void Launch_EnvironmentVariables_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) { - bool launchAdmin = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.LaunchAdministrator; + bool launchAdmin = SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.LaunchAdministrator; string eventName = !App.IsElevated && launchAdmin ? Constants.ShowEnvironmentVariablesAdminSharedEvent() : Constants.ShowEnvironmentVariablesSharedEvent(); diff --git a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeFancyZones.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeFancyZones.xaml.cs index ccbc5c8cc7..5308336e16 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeFancyZones.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeFancyZones.xaml.cs @@ -35,7 +35,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views protected override void OnNavigatedTo(NavigationEventArgs e) { ViewModel.LogOpeningModuleEvent(); - HotkeyControl.Keys = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.FancyzonesEditorHotkey.Value.GetKeysList(); + HotkeyControl.Keys = SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.FancyzonesEditorHotkey.Value.GetKeysList(); } protected override void OnNavigatedFrom(NavigationEventArgs e) diff --git a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeHosts.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeHosts.xaml.cs index d47af96c7f..0a98df472e 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeHosts.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeHosts.xaml.cs @@ -37,7 +37,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views private void Launch_Hosts_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) { - bool launchAdmin = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.LaunchAdministrator; + bool launchAdmin = SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.LaunchAdministrator; string eventName = !App.IsElevated && launchAdmin ? Constants.ShowHostsAdminSharedEvent() : Constants.ShowHostsSharedEvent(); diff --git a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeMeasureTool.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeMeasureTool.xaml.cs index 7ca7739883..e8a24b9fc5 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeMeasureTool.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeMeasureTool.xaml.cs @@ -38,7 +38,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views protected override void OnNavigatedTo(NavigationEventArgs e) { ViewModel.LogOpeningModuleEvent(); - HotkeyActivation.Keys = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut.GetKeysList(); + HotkeyActivation.Keys = SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.ActivationShortcut.GetKeysList(); } protected override void OnNavigatedFrom(NavigationEventArgs e) diff --git a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeOverviewAlternate.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeOverviewAlternate.xaml.cs index d0ae488347..cbd05fc7ed 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeOverviewAlternate.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeOverviewAlternate.xaml.cs @@ -21,10 +21,10 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.Overview]); DataContext = ViewModel; - FancyZonesHotkeyControl.Keys = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.FancyzonesEditorHotkey.Value.GetKeysList(); - RunHotkeyControl.Keys = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.OpenPowerLauncher.GetKeysList(); - ColorPickerHotkeyControl.Keys = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut.GetKeysList(); - AlwaysOnTopHotkeyControl.Keys = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.Hotkey.Value.GetKeysList(); + FancyZonesHotkeyControl.Keys = SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.FancyzonesEditorHotkey.Value.GetKeysList(); + RunHotkeyControl.Keys = SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.OpenPowerLauncher.GetKeysList(); + ColorPickerHotkeyControl.Keys = SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.ActivationShortcut.GetKeysList(); + AlwaysOnTopHotkeyControl.Keys = SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.Hotkey.Value.GetKeysList(); } private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) diff --git a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobePeek.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobePeek.xaml.cs index 7817b13ca4..6782f4adc7 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobePeek.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobePeek.xaml.cs @@ -38,7 +38,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views protected override void OnNavigatedTo(NavigationEventArgs e) { ViewModel.LogOpeningModuleEvent(); - HotkeyControl.Keys = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut.GetKeysList(); + HotkeyControl.Keys = SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.ActivationShortcut.GetKeysList(); } protected override void OnNavigatedFrom(NavigationEventArgs e) diff --git a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobePowerOCR.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobePowerOCR.xaml.cs index 7fef84d2b9..cf607d370e 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobePowerOCR.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobePowerOCR.xaml.cs @@ -35,7 +35,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views protected override void OnNavigatedTo(NavigationEventArgs e) { ViewModel.LogOpeningModuleEvent(); - HotkeyControl.Keys = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut.GetKeysList(); + HotkeyControl.Keys = SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.ActivationShortcut.GetKeysList(); } protected override void OnNavigatedFrom(NavigationEventArgs e) diff --git a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeRun.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeRun.xaml.cs index 3cb8593922..796e05bdea 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeRun.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeRun.xaml.cs @@ -54,7 +54,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views { ViewModel.LogOpeningModuleEvent(); - HotkeyControl.Keys = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.OpenPowerLauncher.GetKeysList(); + HotkeyControl.Keys = SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.OpenPowerLauncher.GetKeysList(); } protected override void OnNavigatedFrom(NavigationEventArgs e) diff --git a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShellPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShellPage.xaml.cs index 8b01ab0bd0..7f8531286c 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShellPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShellPage.xaml.cs @@ -51,7 +51,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views public ObservableCollection Modules { get; } - private static ISettingsUtils settingsUtils = new SettingsUtils(); + private static ISettingsUtils settingsUtils = SettingsUtils.Default; /* NOTE: Experimentation for OOBE is currently turned off on server side. Keeping this code in a comment to allow future experiments. private bool ExperimentationToggleSwitchEnabled { get; set; } = true; diff --git a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShortcutGuide.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShortcutGuide.xaml.cs index 5702ddcb9f..e721deefd6 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShortcutGuide.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShortcutGuide.xaml.cs @@ -56,7 +56,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views protected override void OnNavigatedTo(NavigationEventArgs e) { ViewModel.LogOpeningModuleEvent(); - var settingsProperties = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties; + var settingsProperties = SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties; if ((bool)settingsProperties.UseLegacyPressWinKeyBehavior.Value) { diff --git a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeWorkspaces.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeWorkspaces.xaml.cs index 772807f735..98a8bccb84 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeWorkspaces.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeWorkspaces.xaml.cs @@ -38,7 +38,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views protected override void OnNavigatedTo(NavigationEventArgs e) { ViewModel.LogOpeningModuleEvent(); - HotkeyControl.Keys = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.Hotkey.Value.GetKeysList(); + HotkeyControl.Keys = SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.Hotkey.Value.GetKeysList(); } protected override void OnNavigatedFrom(NavigationEventArgs e) diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/AdvancedPastePage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/AdvancedPastePage.xaml.cs index 7b267107ee..faf31b0d4d 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/AdvancedPastePage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/AdvancedPastePage.xaml.cs @@ -44,7 +44,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public AdvancedPastePage() { - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new AdvancedPasteViewModel( settingsUtils, SettingsRepository.GetInstance(settingsUtils), diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/AlwaysOnTopPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/AlwaysOnTopPage.xaml.cs index c5d99e8e98..95ba8b595f 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/AlwaysOnTopPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/AlwaysOnTopPage.xaml.cs @@ -15,7 +15,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public AlwaysOnTopPage() { - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new AlwaysOnTopViewModel(settingsUtils, SettingsRepository.GetInstance(settingsUtils), SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage); DataContext = ViewModel; InitializeComponent(); diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/AwakePage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/AwakePage.xaml.cs index 91b2b0b781..f52e96fb8f 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/AwakePage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/AwakePage.xaml.cs @@ -36,7 +36,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views { _dispatcherQueue = DispatcherQueue.GetForCurrentThread(); _fileSystem = new FileSystem(); - _settingsUtils = new SettingsUtils(); + _settingsUtils = SettingsUtils.Default; _sendConfigMsg = ShellPage.SendDefaultIPCMessage; ViewModel = new AwakeViewModel(); diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/CmdPalPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/CmdPalPage.xaml.cs index ea318100f0..90dec43398 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/CmdPalPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/CmdPalPage.xaml.cs @@ -19,7 +19,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public CmdPalPage() { - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new CmdPalViewModel( settingsUtils, SettingsRepository.GetInstance(settingsUtils), diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/ColorPickerPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/ColorPickerPage.xaml.cs index 9e0ba6be07..652db49f4b 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/ColorPickerPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/ColorPickerPage.xaml.cs @@ -27,7 +27,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public ColorPickerPage() { - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new ColorPickerViewModel( settingsUtils, SettingsRepository.GetInstance(settingsUtils), diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/CropAndLockPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/CropAndLockPage.xaml.cs index 67ef238645..5c174b1f98 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/CropAndLockPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/CropAndLockPage.xaml.cs @@ -15,7 +15,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public CropAndLockPage() { - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new CropAndLockViewModel(settingsUtils, SettingsRepository.GetInstance(settingsUtils), SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage); DataContext = ViewModel; InitializeComponent(); diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml index 643811d2fc..e5ea54d21b 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml @@ -87,6 +87,7 @@ MaxWidth="{StaticResource PageMaxWidth}" Margin="1,0,0,0" VerticalAlignment="Center" + AutomationProperties.HeadingLevel="1" Style="{StaticResource TitleTextBlockStyle}" /> .GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage); diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/EnvironmentVariablesPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/EnvironmentVariablesPage.xaml.cs index 0772869249..a3e17ac491 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/EnvironmentVariablesPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/EnvironmentVariablesPage.xaml.cs @@ -16,7 +16,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public EnvironmentVariablesPage() { InitializeComponent(); - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new EnvironmentVariablesViewModel(settingsUtils, SettingsRepository.GetInstance(settingsUtils), SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, App.IsElevated); } diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/FancyZonesPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/FancyZonesPage.xaml.cs index e1d7f7ea4b..ddf7c1e8ee 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/FancyZonesPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/FancyZonesPage.xaml.cs @@ -16,7 +16,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public FancyZonesPage() { InitializeComponent(); - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new FancyZonesViewModel(settingsUtils, SettingsRepository.GetInstance(settingsUtils), SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage); DataContext = ViewModel; Loaded += (s, e) => ViewModel.OnPageLoaded(); diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/FileLocksmithPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/FileLocksmithPage.xaml.cs index 6020917b69..8f78ce2c8c 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/FileLocksmithPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/FileLocksmithPage.xaml.cs @@ -15,7 +15,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public FileLocksmithPage() { - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new FileLocksmithViewModel(settingsUtils, SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage); DataContext = ViewModel; InitializeComponent(); diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/GeneralPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/GeneralPage.xaml.cs index 56eb73c6ef..5e84711b86 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/GeneralPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/GeneralPage.xaml.cs @@ -38,7 +38,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views // Load string resources var loader = Helpers.ResourceLoaderInstance.ResourceLoader; - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; Action stateUpdatingAction = () => { diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/HostsPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/HostsPage.xaml.cs index 19375d90f7..b65f32d520 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/HostsPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/HostsPage.xaml.cs @@ -16,7 +16,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public HostsPage() { InitializeComponent(); - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new HostsViewModel(settingsUtils, SettingsRepository.GetInstance(settingsUtils), SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, App.IsElevated); BackupsCountInputSettingsCard.Header = ResourceLoaderInstance.ResourceLoader.GetString("Hosts_Backup_CountInput_Header"); BackupsCountInputSettingsCard.Description = ResourceLoaderInstance.ResourceLoader.GetString("Hosts_Backup_CountInput_Description"); diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/ImageResizerPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/ImageResizerPage.xaml.cs index 18e1aacc15..6a2068d5a8 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/ImageResizerPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/ImageResizerPage.xaml.cs @@ -21,7 +21,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public ImageResizerPage() { InitializeComponent(); - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; var resourceLoader = ResourceLoaderInstance.ResourceLoader; Func loader = resourceLoader.GetString; diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/KeyboardManagerPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/KeyboardManagerPage.xaml.cs index e32f5aa9cb..fce4dfc718 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/KeyboardManagerPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/KeyboardManagerPage.xaml.cs @@ -28,7 +28,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public KeyboardManagerPage() { - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new KeyboardManagerViewModel(settingsUtils, SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, FilterRemapKeysList); watcher = Helper.GetFileWatcher( diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/LightSwitchPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/LightSwitchPage.xaml.cs index 974447a20e..dcd40fdbc7 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/LightSwitchPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/LightSwitchPage.xaml.cs @@ -40,7 +40,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public LightSwitchPage() { - this.settingsUtils = new SettingsUtils(); + this.settingsUtils = SettingsUtils.Default; this.sendConfigMsg = ShellPage.SendDefaultIPCMessage; this.generalSettingsRepository = SettingsRepository.GetInstance(this.settingsUtils); diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/MeasureToolPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/MeasureToolPage.xaml.cs index bf516b557b..8f80f1c13b 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/MeasureToolPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/MeasureToolPage.xaml.cs @@ -17,7 +17,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public MeasureToolPage() { - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new MeasureToolViewModel( settingsUtils, SettingsRepository.GetInstance(settingsUtils), diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml.cs index ac4c7cc71d..fa34ca5293 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml.cs @@ -22,7 +22,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views { // By mistake, the first release of Find My Mouse was saving settings in two places at the same time. // Delete the wrong path for Find My Mouse settings. - var tempSettingsUtils = new SettingsUtils(); + var tempSettingsUtils = SettingsUtils.Default; if (tempSettingsUtils.SettingsExists("Find My Mouse")) { var settingsFilePath = tempSettingsUtils.GetSettingsFilePath("Find My Mouse"); @@ -34,7 +34,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views { } - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new MouseUtilsViewModel( settingsUtils, SettingsRepository.GetInstance(settingsUtils), diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseWithoutBordersPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseWithoutBordersPage.xaml.cs index 296a9a3deb..2db0d7a5d6 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseWithoutBordersPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseWithoutBordersPage.xaml.cs @@ -33,7 +33,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public MouseWithoutBordersPage() { - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new MouseWithoutBordersViewModel( settingsUtils, SettingsRepository.GetInstance(settingsUtils), diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/NewPlusPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/NewPlusPage.xaml.cs index daa4dca2b5..997f6c7771 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/NewPlusPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/NewPlusPage.xaml.cs @@ -16,7 +16,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public NewPlusPage() { InitializeComponent(); - var settings_utils = new SettingsUtils(); + var settings_utils = SettingsUtils.Default; ViewModel = new NewPlusViewModel(settings_utils, SettingsRepository.GetInstance(settings_utils), ShellPage.SendDefaultIPCMessage); DataContext = ViewModel; } diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/PeekPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/PeekPage.xaml.cs index 1a845e25ec..b848ae86dd 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/PeekPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/PeekPage.xaml.cs @@ -15,7 +15,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public PeekPage() { - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new PeekViewModel( settingsUtils, SettingsRepository.GetInstance(settingsUtils), diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerAccentPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerAccentPage.xaml.cs index fa666dd242..0f60a8dcd3 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerAccentPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerAccentPage.xaml.cs @@ -17,7 +17,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public PowerAccentPage() { - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new PowerAccentViewModel(settingsUtils, SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage); DataContext = ViewModel; this.InitializeComponent(); diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerLauncherPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerLauncherPage.xaml.cs index c734535d49..19973a69bc 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerLauncherPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerLauncherPage.xaml.cs @@ -34,7 +34,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public PowerLauncherPage() { InitializeComponent(); - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; _lastIPCMessageSentTick = Environment.TickCount; PowerLauncherSettings settings = SettingsRepository.GetInstance(settingsUtils)?.SettingsConfig; diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerOcrPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerOcrPage.xaml.cs index 27769b92ce..9198d338ef 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerOcrPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerOcrPage.xaml.cs @@ -15,7 +15,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public PowerOcrPage() { - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new PowerOcrViewModel( settingsUtils, SettingsRepository.GetInstance(settingsUtils), diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerPreviewPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerPreviewPage.xaml.cs index 9d56c686e3..ecc960651b 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerPreviewPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerPreviewPage.xaml.cs @@ -19,7 +19,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public PowerPreviewPage() { InitializeComponent(); - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new PowerPreviewViewModel(SettingsRepository.GetInstance(settingsUtils), SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage); DataContext = ViewModel; } diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerRenamePage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerRenamePage.xaml.cs index d97b83c499..10013b84a3 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerRenamePage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerRenamePage.xaml.cs @@ -16,7 +16,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public PowerRenamePage() { InitializeComponent(); - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new PowerRenameViewModel(settingsUtils, SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage); DataContext = ViewModel; diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/RegistryPreviewPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/RegistryPreviewPage.xaml.cs index 8c1ed319a3..41d814e48b 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/RegistryPreviewPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/RegistryPreviewPage.xaml.cs @@ -14,7 +14,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public RegistryPreviewPage() { - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new RegistryPreviewViewModel( SettingsRepository.GetInstance(settingsUtils), SettingsRepository.GetInstance(settingsUtils), diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml.cs index 06f7e222ce..853b66f164 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml.cs @@ -151,7 +151,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views { InitializeComponent(); SetWindowTitle(); - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new ShellViewModel(SettingsRepository.GetInstance(settingsUtils)); DataContext = ViewModel; ShellHandler = this; diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/ShortcutGuidePage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/ShortcutGuidePage.xaml.cs index ffca0184c7..feb0e4837d 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/ShortcutGuidePage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/ShortcutGuidePage.xaml.cs @@ -17,7 +17,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views { InitializeComponent(); - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new ShortcutGuideViewModel(settingsUtils, SettingsRepository.GetInstance(settingsUtils), SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage); DataContext = ViewModel; diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/WorkspacesPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/WorkspacesPage.xaml.cs index 0b0ca571c4..3028b46ea1 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/WorkspacesPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/WorkspacesPage.xaml.cs @@ -15,7 +15,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public WorkspacesPage() { - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new WorkspacesViewModel(settingsUtils, SettingsRepository.GetInstance(settingsUtils), SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage); DataContext = ViewModel; InitializeComponent(); diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/ZoomItPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/ZoomItPage.xaml.cs index 9018eb64e8..043ca7df8c 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/ZoomItPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/ZoomItPage.xaml.cs @@ -104,7 +104,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views public ZoomItPage() { - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; ViewModel = new ZoomItViewModel(settingsUtils, SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, PickFileDialog, PickFontDialog); DataContext = ViewModel; InitializeComponent(); diff --git a/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw b/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw index 7548d9da57..4994e2812b 100644 --- a/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw +++ b/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw @@ -638,9 +638,6 @@ Please review the placeholder content that represents the final terms and usage I have read and accept the information above. - - Enable OpenAI content moderation - Enable OpenAI content moderation @@ -2092,9 +2089,6 @@ Made with 💗 by Microsoft and the PowerToys community. Transcode to .mp4 (H.264/AAC) - - OpenAI API key: - Save @@ -4029,7 +4023,7 @@ Activate by holding the key for the character you want to add an accent to, then Product name: Navigation view item name for Advanced Paste - A tool to quickly format clipboard content into plain text, Markdown, JSON, and more. An AI-powered option requiring an OpenAI API key is available for advanced formatting. + Formats clipboard content into plain text, Markdown, JSON, and more. Advanced formatting can use an online or local language model endpoint. Advanced Paste @@ -4559,18 +4553,9 @@ Activate by holding the key for the character you want to add an accent to, then OpenAI Terms - - Paste with AI allows you to format your clipboard content into any format you need. Learn more about the terms of conditions while using OpenAI and privacy at Microsoft: - • Login into your - - Configure OpenAI key - - - OpenAI API keys overview - • Create a new secret key and paste it in the field below @@ -4588,9 +4573,6 @@ Activate by holding the key for the character you want to add an accent to, then Font size - - • NOTE: You need to have available paid credits in your OpenAI account to use this feature. If you do not have credits you will see an 'API key quota exceeded' error - If you do not have credits you will see an 'API key quota exceeded' error diff --git a/src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs index b0520dd38d..1afe76897e 100644 --- a/src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs @@ -251,7 +251,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels if (dashboardListItem.Tag == ModuleType.NewPlus && dashboardListItem.IsEnabled == true) { - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; var settings = NewPlusViewModel.LoadSettings(settingsUtils); NewPlusViewModel.CopyTemplateExamples(settings.Properties.TemplateLocation.Value); } @@ -390,7 +390,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private ObservableCollection GetModuleItemsAlwaysOnTop() { - ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(new SettingsUtils()); + ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(SettingsUtils.Default); var list = new List { new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("AlwaysOnTop_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.Hotkey.Value.GetKeysList() }, @@ -411,7 +411,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private ObservableCollection GetModuleItemsColorPicker() { - ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(new SettingsUtils()); + ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(SettingsUtils.Default); var settings = moduleSettingsRepository.SettingsConfig; var hotkey = settings.Properties.ActivationShortcut; var list = new List @@ -423,7 +423,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private ObservableCollection GetModuleItemsLightSwitch() { - ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(new SettingsUtils()); + ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(SettingsUtils.Default); var settings = moduleSettingsRepository.SettingsConfig; var list = new List { @@ -434,7 +434,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private ObservableCollection GetModuleItemsCropAndLock() { - ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(new SettingsUtils()); + ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(SettingsUtils.Default); var settings = moduleSettingsRepository.SettingsConfig; var list = new List { @@ -455,7 +455,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private ObservableCollection GetModuleItemsFancyZones() { - ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(new SettingsUtils()); + ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(SettingsUtils.Default); var settings = moduleSettingsRepository.SettingsConfig; string activationMode = $"{resourceLoader.GetString(settings.Properties.FancyzonesShiftDrag.Value ? "FancyZones_ActivationShiftDrag" : "FancyZones_ActivationNoShiftDrag")}."; @@ -470,7 +470,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private ObservableCollection GetModuleItemsFindMyMouse() { - ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(new SettingsUtils()); + ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(SettingsUtils.Default); string shortDescription = resourceLoader.GetString("FindMyMouse_ShortDescription"); var settings = moduleSettingsRepository.SettingsConfig; var activationMethod = settings.Properties.ActivationMethod.Value; @@ -508,7 +508,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private ObservableCollection GetModuleItemsMouseHighlighter() { - ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(new SettingsUtils()); + ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(SettingsUtils.Default); var list = new List { new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("MouseHighlighter_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.ActivationShortcut.GetKeysList() }, @@ -518,7 +518,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private ObservableCollection GetModuleItemsMouseJump() { - ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(new SettingsUtils()); + ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(SettingsUtils.Default); var list = new List { new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("MouseJump_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.ActivationShortcut.GetKeysList() }, @@ -528,7 +528,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private ObservableCollection GetModuleItemsMousePointerCrosshairs() { - ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(new SettingsUtils()); + ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(SettingsUtils.Default); var list = new List { new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("MouseCrosshairs_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.ActivationShortcut.GetKeysList() }, @@ -538,7 +538,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private ObservableCollection GetModuleItemsAdvancedPaste() { - ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(new SettingsUtils()); + ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(SettingsUtils.Default); var list = new List { new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("AdvancedPasteUI_Shortcut/Header"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.AdvancedPasteUIShortcut.GetKeysList() }, @@ -560,7 +560,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private ObservableCollection GetModuleItemsPeek() { - ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(new SettingsUtils()); + ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(SettingsUtils.Default); var list = new List { new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("Peek_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.ActivationShortcut.GetKeysList() }, @@ -570,7 +570,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private ObservableCollection GetModuleItemsPowerLauncher() { - ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(new SettingsUtils()); + ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(SettingsUtils.Default); var list = new List { new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("Run_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.OpenPowerLauncher.GetKeysList() }, @@ -580,7 +580,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private ObservableCollection GetModuleItemsPowerAccent() { - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; PowerAccentSettings moduleSettings = settingsUtils.GetSettingsOrDefault(PowerAccentSettings.ModuleName); var activationMethod = moduleSettings.Properties.ActivationKey; string activation = string.Empty; @@ -600,7 +600,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private ObservableCollection GetModuleItemsWorkspaces() { - ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(new SettingsUtils()); + ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(SettingsUtils.Default); var settings = moduleSettingsRepository.SettingsConfig; var list = new List @@ -622,7 +622,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private ObservableCollection GetModuleItemsMeasureTool() { - ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(new SettingsUtils()); + ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(SettingsUtils.Default); var list = new List { new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("ScreenRuler_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.ActivationShortcut.GetKeysList() }, @@ -632,7 +632,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private ObservableCollection GetModuleItemsShortcutGuide() { - ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(new SettingsUtils()); + ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(SettingsUtils.Default); var shortcut = moduleSettingsRepository.SettingsConfig.Properties.UseLegacyPressWinKeyBehavior.Value ? new List { 92 } // Right Windows key code @@ -647,7 +647,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private ObservableCollection GetModuleItemsPowerOCR() { - ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(new SettingsUtils()); + ISettingsRepository moduleSettingsRepository = SettingsRepository.GetInstance(SettingsUtils.Default); var list = new List { new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("PowerOcr_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.ActivationShortcut.GetKeysList() }, @@ -662,14 +662,14 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private void EnvironmentVariablesLaunchClicked(object sender, RoutedEventArgs e) { - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; var environmentVariablesViewModel = new EnvironmentVariablesViewModel(settingsUtils, SettingsRepository.GetInstance(settingsUtils), SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, App.IsElevated); environmentVariablesViewModel.Launch(); } private void HostLaunchClicked(object sender, RoutedEventArgs e) { - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; var hostsViewModel = new HostsViewModel(settingsUtils, SettingsRepository.GetInstance(settingsUtils), SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, App.IsElevated); hostsViewModel.Launch(); } diff --git a/src/settings-ui/Settings.UI/ViewModels/Flyout/LauncherViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/Flyout/LauncherViewModel.cs index a1db1e2dd0..7adc4bb933 100644 --- a/src/settings-ui/Settings.UI/ViewModels/Flyout/LauncherViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/Flyout/LauncherViewModel.cs @@ -88,12 +88,12 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels { return moduleType switch { - ModuleType.ColorPicker => SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut.ToString(), - ModuleType.FancyZones => SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.FancyzonesEditorHotkey.Value.ToString(), - ModuleType.PowerLauncher => SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.OpenPowerLauncher.ToString(), - ModuleType.PowerOCR => SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut.ToString(), - ModuleType.Workspaces => SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.Hotkey.Value.ToString(), - ModuleType.MeasureTool => SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut.ToString(), + ModuleType.ColorPicker => SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.ActivationShortcut.ToString(), + ModuleType.FancyZones => SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.FancyzonesEditorHotkey.Value.ToString(), + ModuleType.PowerLauncher => SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.OpenPowerLauncher.ToString(), + ModuleType.PowerOCR => SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.ActivationShortcut.ToString(), + ModuleType.Workspaces => SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.Hotkey.Value.ToString(), + ModuleType.MeasureTool => SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.ActivationShortcut.ToString(), ModuleType.ShortcutGuide => GetShortcutGuideToolTip(), _ => string.Empty, }; @@ -111,7 +111,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private string GetShortcutGuideToolTip() { - var shortcutGuideSettings = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig; + var shortcutGuideSettings = SettingsRepository.GetInstance(SettingsUtils.Default).SettingsConfig; return shortcutGuideSettings.Properties.UseLegacyPressWinKeyBehavior.Value ? "Win" : shortcutGuideSettings.Properties.OpenShortcutGuide.ToString(); diff --git a/src/settings-ui/Settings.UI/ViewModels/GeneralViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/GeneralViewModel.cs index 7a6a7fc284..25ab4db13a 100644 --- a/src/settings-ui/Settings.UI/ViewModels/GeneralViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/GeneralViewModel.cs @@ -1145,7 +1145,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels _settingsBackupMessage = GetResourceString(results.Message) + results.OptionalMessage; // now we do a dry run to get the results for "setting match" - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; var appBasePath = Path.GetDirectoryName(settingsUtils.GetSettingsFilePath()); settingsBackupAndRestoreUtils.BackupSettings(appBasePath, settingsBackupAndRestoreDir, true); diff --git a/src/settings-ui/Settings.UI/ViewModels/KeyboardManagerViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/KeyboardManagerViewModel.cs index 3aa90cbc24..a48742672c 100644 --- a/src/settings-ui/Settings.UI/ViewModels/KeyboardManagerViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/KeyboardManagerViewModel.cs @@ -274,7 +274,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels try { // Check if the experimentation toggle is enabled in the settings - var settingsUtils = new SettingsUtils(); + var settingsUtils = SettingsUtils.Default; bool isExperimentationEnabled = SettingsRepository.GetInstance(settingsUtils).SettingsConfig.EnableExperimentation; // Only read the registry value if the experimentation toggle is enabled diff --git a/tools/build/BUILD-GUIDELINES.md b/tools/build/BUILD-GUIDELINES.md index d9ce1d3f75..4a1c23b678 100644 --- a/tools/build/BUILD-GUIDELINES.md +++ b/tools/build/BUILD-GUIDELINES.md @@ -12,7 +12,7 @@ Tip: Add `D:\PowerToys\tools\build` to your PATH to use the wrappers anywhere. ## When to use which 1) `build-essentials.ps1` - - Restores NuGet for `PowerToys.sln` and builds essentials (runner, settings). + - Restores NuGet for `PowerToys.slnx` and builds essentials (runner, settings). - Auto-detects Platform; initializes VS Dev environment automatically. - Example (PowerShell): - `./tools/build/build-essentials.ps1` diff --git a/tools/build/build-common.ps1 b/tools/build/build-common.ps1 index eb3c604081..cadeba1542 100644 --- a/tools/build/build-common.ps1 +++ b/tools/build/build-common.ps1 @@ -113,7 +113,7 @@ function BuildProjectsInDirectory { $files = @() try { - $files = Get-ChildItem -Path (Join-Path $DirectoryPath '*') -Include *.sln,*.csproj,*.vcxproj -File -ErrorAction SilentlyContinue + $files = Get-ChildItem -Path (Join-Path $DirectoryPath '*') -Include *.sln,*.slnx,*.csproj,*.vcxproj -File -ErrorAction SilentlyContinue } catch { $files = @() } diff --git a/tools/build/build-essentials.ps1 b/tools/build/build-essentials.ps1 index 9b12e68334..37bf0a5cde 100644 --- a/tools/build/build-essentials.ps1 +++ b/tools/build/build-essentials.ps1 @@ -3,7 +3,7 @@ Build essential native PowerToys projects (runner and settings), restoring NuGet packages first. .DESCRIPTION -Lightweight script to build a small set of essential C++ projects used by PowerToys' runner and native modules. This script first restores NuGet packages for the full solution (`PowerToys.sln`) and then builds the runner and settings projects. Intended for fast local builds during development. +Lightweight script to build a small set of essential C++ projects used by PowerToys' runner and native modules. This script first restores NuGet packages for the full solution (`PowerToys.slnx`) and then builds the runner and settings projects. Intended for fast local builds during development. .PARAMETER Platform Target platform for the build (for example: 'x64', 'arm64'). If omitted the script will attempt to auto-detect the host platform. @@ -21,7 +21,7 @@ Restores packages and builds the essentials in Release mode for ARM64, even if y .NOTES - This script dot-sources `build-common.ps1` and uses the shared helper `RunMSBuild`. -- It will call `RestoreThenBuild 'PowerToys.sln'` before building the essential projects to ensure NuGet packages are restored. +- It will call `RestoreThenBuild 'PowerToys.slnx'` before building the essential projects to ensure NuGet packages are restored. - The script attempts to locate the repository root automatically and can be run from any folder inside the repo. #> @@ -33,7 +33,7 @@ param ( # Find repository root starting from the script location $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition $repoRoot = $ScriptDir -while ($repoRoot -and -not (Test-Path (Join-Path $repoRoot "PowerToys.sln"))) { +while ($repoRoot -and -not (Test-Path (Join-Path $repoRoot "PowerToys.slnx"))) { $parent = Split-Path -Parent $repoRoot if ($parent -eq $repoRoot) { Write-Error "Could not find PowerToys repository root." @@ -63,7 +63,7 @@ if (-not $Platform -or $Platform -eq '') { } # Ensure solution packages are restored -RestoreThenBuild 'PowerToys.sln' '' $Platform $Configuration $true +RestoreThenBuild 'PowerToys.slnx' '' $Platform $Configuration $true # Build both runner and settings $ProjectsToBuild = @(".\src\runner\runner.vcxproj", ".\src\settings-ui\Settings.UI\PowerToys.Settings.csproj") @@ -71,4 +71,4 @@ $ExtraArgs = "/p:SolutionDir=$repoRoot\" foreach ($proj in $ProjectsToBuild) { Write-Host ("[BUILD-ESSENTIALS] Building {0}" -f $proj) RunMSBuild $proj $ExtraArgs $Platform $Configuration -} \ No newline at end of file +} diff --git a/tools/build/build-installer.ps1 b/tools/build/build-installer.ps1 index 83a47f2092..65497aeeaa 100644 --- a/tools/build/build-installer.ps1 +++ b/tools/build/build-installer.ps1 @@ -73,18 +73,18 @@ $repoRoot = $scriptDir # Navigate up from the script location to find the repo root # Script is typically in tools\build, so go up two levels -while ($repoRoot -and -not (Test-Path (Join-Path $repoRoot "PowerToys.sln"))) { +while ($repoRoot -and -not (Test-Path (Join-Path $repoRoot "PowerToys.slnx"))) { $parentDir = Split-Path -Parent $repoRoot if ($parentDir -eq $repoRoot) { - # Reached the root of the drive, PowerToys.sln not found + # Reached the root of the drive, PowerToys.slnx not found Write-Error "Could not find PowerToys repository root. Make sure this script is in the PowerToys repository." exit 1 } $repoRoot = $parentDir } -if (-not $repoRoot -or -not (Test-Path (Join-Path $repoRoot "PowerToys.sln"))) { - Write-Error "Could not locate PowerToys.sln. Please ensure this script is run from within the PowerToys repository." +if (-not $repoRoot -or -not (Test-Path (Join-Path $repoRoot "PowerToys.slnx"))) { + Write-Error "Could not locate PowerToys.slnx. Please ensure this script is run from within the PowerToys repository." exit 1 } @@ -102,7 +102,7 @@ if (Test-Path $cmdpalOutputPath) { $commonArgs = '/p:CIBuild=true' # No local projects found (or continuing) - build full solution and tools -RestoreThenBuild 'PowerToys.sln' $commonArgs $Platform $Configuration +RestoreThenBuild 'PowerToys.slnx' $commonArgs $Platform $Configuration $msixSearchRoot = Join-Path $repoRoot "$Platform\$Configuration" $msixFiles = Get-ChildItem -Path $msixSearchRoot -Recurse -Filter *.msix | @@ -141,10 +141,10 @@ try { Pop-Location } -RunMSBuild 'installer\PowerToysSetup.sln' "$commonArgs /t:restore /p:RestorePackagesConfig=true" $Platform $Configuration +RunMSBuild 'installer\PowerToysSetup.slnx' "$commonArgs /t:restore /p:RestorePackagesConfig=true" $Platform $Configuration -RunMSBuild 'installer\PowerToysSetup.sln' "$commonArgs /m /t:PowerToysInstallerVNext /p:PerUser=$PerUser" $Platform $Configuration +RunMSBuild 'installer\PowerToysSetup.slnx' "$commonArgs /m /t:PowerToysInstallerVNext /p:PerUser=$PerUser" $Platform $Configuration -RunMSBuild 'installer\PowerToysSetup.sln' "$commonArgs /m /t:PowerToysBootstrapperVNext /p:PerUser=$PerUser" $Platform $Configuration +RunMSBuild 'installer\PowerToysSetup.slnx' "$commonArgs /m /t:PowerToysBootstrapperVNext /p:PerUser=$PerUser" $Platform $Configuration Write-Host '[PIPELINE] Completed' diff --git a/tools/project_template/README.md b/tools/project_template/README.md index 0efbd29c90..2f37ce20f3 100644 --- a/tools/project_template/README.md +++ b/tools/project_template/README.md @@ -6,7 +6,7 @@ - The template will be available in Visual Studio, when adding a new project, under the `Visual C++` tab. ## Contributing -If you'd like to work on a PowerToy template, make required modifications to `\tools\project_template\ModuleTemplate.vcxproj` and then use the dedicated solution `PowerToyTemplate.sln` to export it as a template. Note that `ModuleTemplate.vcxproj` is actually a project template, therefore uncompilable, so we also have a dedicated `ModuleTemplateCompileTest.vcxproj` project referenced from the `PowerToys.sln` to help keeping the template sources up to date and verify it compiles correctly. +If you'd like to work on a PowerToy template, make required modifications to `\tools\project_template\ModuleTemplate.vcxproj` and then use the dedicated solution `PowerToyTemplate.sln` to export it as a template. Note that `ModuleTemplate.vcxproj` is actually a project template, therefore uncompilable, so we also have a dedicated `ModuleTemplateCompileTest.vcxproj` project referenced from the `PowerToys.slnx` to help keeping the template sources up to date and verify it compiles correctly. ## Create a new PowerToy Module @@ -442,7 +442,7 @@ void ExamplePowertoy::save_settings() { ## Add a new PowerToy to the Installer -In the `installer` folder, open the `PowerToysSetup.sln` solution. +In the `installer` folder, open the `PowerToysSetup.slnx` solution. Under the `PowerToysSetup` project, edit `Product.wxs`. You will need to add a component for your module DLL. Search for `Module_ShortcutGuide` to see where to add the component declaration and where to reference that declaration so the DLL is added to the installer. Each component requires a newly generated GUID (you can use the Visual Studio integrated tool to generate one).
Event Name Description
Microsoft.PowerToys.NewPlus_ChangedTemplateLocationTriggered when the template folder location is changed.
Microsoft.PowerToys.NewPlus_EventCopyTemplate Triggered when an item from New+ is created (copied to the current directory).Microsoft.PowerToys.NewPlus_EventCopyTemplateResult Logs the success of item creation (copying).
Microsoft.PowerToys.NewPlus_EventOpenTemplatesTriggered when the templates folder is opened.
Microsoft.PowerToys.NewPlus_EventShowTemplateItems Triggered when the New+ context menu flyout is displayed.Description
Microsoft.PowerToys.ShortcutGuide_EnableGuideTriggered when Shortcut Guide is enabled.
Microsoft.PowerToys.ShortcutGuide_HideGuideOccurs when Shortcut Guide is hidden from view.Microsoft.PowerToys.ShortcutGuide_GuideSessionLogs a Shortcut Guide session including duration and how it was closed.
Microsoft.PowerToys.ShortcutGuide_Settings