Compare commits

...

10 Commits

Author SHA1 Message Date
Michael Jolley
696ad8ac34 Merging Core projects into Common and UI.ViewModels 2026-02-19 17:14:48 -06:00
Jiří Polášek
39bfa86335 CmdPal: Fixes and improve main window positioning (#45585)
## Summary of the Pull Request

This PR improves main window positioning:

- Fixes cases where an invalid window size or position was saved.  
- `UpdateWindowPositionInMemory` failed to capture correct values when
the window was minimized or maximized (for example, a minimized window
reports coordinates like `(-32000, -32000)`).
- Improves repositioning logic to use relative anchors (corners and
center). When switching displays, the window should reappear in the
expected position. This also reduces cases that trigger the failsafe
recentering.
- Fixes the dragging rectangle size after switching DPIs - the rectangle
was not adapting, so it when switching from 100 % to 200 % it covered
only left half of the window and had teeny-tiny height.
- Suppresses system DPI handling during summon to prevent double
scaling.
- Makes `WindowPosition` class immutable.
- Adds light-weight failsafe preventing overwriting position with
invalid data.
- Hotfixes a min/max state conflict with the WinUIEx window manager.

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

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

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-02-19 12:43:32 -06:00
Jiří Polášek
dcf4c4d16d CmdPal: Calm down sanitizer and adjust unit tests (#45613)
## Summary of the Pull Request

This PR chills down the report sanitizer, because it's overly active.

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

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

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-02-19 12:39:18 -06:00
Jiří Polášek
de25059de0 CmdPal: Fix starting new web URI for default browser that doesn't support exe arguments (#45614)
## Summary of the Pull Request

This PR changes the way the Web Search built-in extension handles full
URIs: it bypasses default browser discovery and asks the shell to open
the URI directly. The original execution path remains as a fallback and
for simple queries (when a custom search engine is not set).

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

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

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-02-19 12:33:28 -06:00
Jiří Polášek
3548d5c1a3 CmdPal: Add missing resources related to ShortcutControl (#45589)
## Summary of the Pull Request

This PR fixes crash when editing keyboard shortcut (missing string
resource) and adds another string resource to display a text for
un-assigned hotkey.

<img width="937" height="145" alt="image"
src="https://github.com/user-attachments/assets/1f423c3b-6f4f-4dd2-a3ba-e777b6e665ba"
/>


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

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

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-02-14 15:30:51 +01:00
Jeremy Sinclair
93e80265b8 [Build][Settings] Add CoreTargetFramework Property (#41366)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Adds CoreTargetFramework MSBuild property as a way to use the
TargetFramework property minus the OS and OS Version.


<!-- Please review the items on the PR checklist before submitting-->
## 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

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Updates `Common.Dotnet.CsWinRT.props` with a `CoreTargetFramework`
property. This is then used to form the actual `TargetFramework`
property. `Settings.UI.XamlIndexBuilder` was the original catalyst for
this PR since it doesn't need Windows SDK targeting, and it didn't make
sense to have one project by itself that would manually need its target
version updated.

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed

---------

Co-authored-by: vanzue <vanzue@outlook.com>
2026-02-14 15:53:04 +08:00
Youssef Victor
a403323530 Migrate to MTP (#37651)
Duplicating https://github.com/microsoft/PowerToys/pull/37001, but
opening from upstream instead of fork as CI doesn't play nicely with PRs
from forks (https://github.com/microsoft/PowerToys/pull/37617 is
improving that)

---------

Co-authored-by: Clint Rutkas <clint@rutkas.com>
Co-authored-by: vanzue <vanzue@outlook.com>
2026-02-14 15:47:56 +08:00
Kai Tao
8e264d37a1 CI: Sign new dll to get ci passed (#45582)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
<img width="1527" height="354" alt="image"
src="https://github.com/user-attachments/assets/28b14e69-f16a-4129-8757-3f7304e6a446"
/>

Release pipeline fail to check the dll signature, forgot to sign it.

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

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

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

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed

Should pass release pipeline
2026-02-13 22:26:37 +08:00
Dave Rayment
e8165fc947 [ZoomIt] Fix ampersand typing bug and debug assertion failure (#43679)
## Summary of the Pull Request
This PR fixes two typing-related issues in ZoomIt:
1. Ampersands could be typed even when Type Mode or Draw Mode were not
engaged
2. On Debug builds, typing a non-alphanumeric character in Type Mode
would crash ZoomIt with a CRT assertion failure

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

- [x] Closes: #43676 
- [x] Closes: #43677
- [ ] **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

### Assertion failure on Debug builds

**Root Cause**

This occurred because of a combination of a type-coercion issue and the
use of `isprint()` in `WM_KEYDOWN`, which operates on virtual key codes,
not characters.

This is the code with the fault:

```cpp
    if( (g_TypeMode != TypeModeOff) && g_HaveTyped && static_cast<char>(wParam) != VK_UP && static_cast<char>(wParam) != VK_DOWN &&
        (isprint( static_cast<char>(wParam)) ||
        wParam == VK_RETURN || wParam == VK_DELETE || wParam == VK_BACK )) {
```

There are a few issues here:

1. There is no need for the `VK_UP` / `VK_DOWN` check. The block only
executes if `VK_RETURN`, `VK_DELETE` or `VK_BACK` are pressed, which
cannot be `VK_UP` or `VK_DOWN` by definition. This should be removed.
2. Casting the `wParam` to `char` means casting an unsigned int value to
a signed char. This works for alphanumeric characters, as the VK_-codes
correspond to their char counterparts. But it fails for values with
their high bit set, e.g. a hyphen:

- The virtual key code for the hyphen key is `VK_OEM_MINUS`, or `0xBD`
- `0xBD` (10111101) becomes `-67` when cast to a char
- In Debug builds, a call to `isprint()` includes a range check to
ensure the value is in the range 1 to 255. A negative value trips this
assertion.

3. The casts are not needed.

**Fix**
Remove both the `isprint()` call (the WM_CHAR handler has an
`iswprint()` check) and remove the check against `VK_UP` and `VK_DOWN`.

### Ampersand issue

This is a simple operator precedence issue with this statement:

```cpp
if ((g_TypeMode != TypeModeOff) && iswprint(static_cast<TCHAR>(wParam)) || 
    (static_cast<TCHAR>(wParam) == L'&'))
```

The intention is to continue if one of the Type Modes is engaged (either
left-to-right or right-to-left) and either the typed character is
printable or (a special-case) the ampersand (presumably for legacy
issues when `DT_NOPREFIX` was not present on all draw text calls).

Unfortunately, the parentheses are placed incorrectly, resulting in the
expression actually being:

`if (Type Mode is active AND a printable character was pressed) OR
(Ampersand was pressed)`

(Meaning the code will always execute if ampersand is pressed regardless
of the mode.)

**Fix**
Correcting the placement of the parentheses fixes the issue.

Note: I think `DT_NOPREFIX` exists on all `DrawText()` calls which
render characters, so we could potentially remove the ampersand check
entirely in the future, assuming that was the original issue which
required the special casing.

## Validation Steps Performed
- Ensure ampersand does not result in the character appearing and/or
glitches occurring where the cursor is when Type Mode or Draw Mode are
not active.
- Ensure ampersands may still be typed as normal in Type Mode.
- Confirm that non-alphanumeric characters can be typed without issue in
Type Mode on both Debug and Release builds.
- Test draw operations in combination with text notes.
- Test backspace, return and delete keys in Type Mode.
- Test that Type Mode engages repeatedly and can be exited.
2026-02-13 19:29:38 +08:00
foxmsft
450d6db343 Add an option for mono mic capture in ZoomIt 2026-02-13 10:43:24 +01:00
365 changed files with 3433 additions and 1605 deletions

View File

@@ -143,3 +143,5 @@ ignore$
^src/modules/registrypreview/RegistryPreviewUILib/Controls/HexBox/.*$
^src/common/CalculatorEngineCommon/exprtk\.hpp$
src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleMarkdownImagesPage.cs
^src/modules/powerrename/unittests/testdata/avif_test\.avif$
^src/modules/powerrename/unittests/testdata/heif_test\.heic$

File diff suppressed because it is too large Load Diff

View File

@@ -18,6 +18,7 @@
"StylesReportTool\\PowerToys.StylesReportTool.exe",
"CalculatorEngineCommon.dll",
"PowerToys.Common.UI.Controls.dll",
"PowerToys.ManagedTelemetry.dll",
"PowerToys.ManagedCommon.dll",
"PowerToys.ManagedCsWin32.dll",

View File

@@ -108,9 +108,6 @@ jobs:
sdk: true
version: '9.0'
- task: VisualStudioTestPlatformInstaller@1
displayName: Ensure VSTest Platform
- pwsh: |-
& '$(build.sourcesdirectory)\.pipelines\InstallWinAppDriver.ps1'
displayName: Download and install WinAppDriver
@@ -152,46 +149,7 @@ jobs:
inputs:
displaySettings: 'optimal'
- ${{ if eq(length(parameters.uiTestModules), 0) }}:
- task: VSTest@3
displayName: Run UI Tests
inputs:
platform: '$(BuildPlatform)'
configuration: '$(BuildConfiguration)'
testSelector: 'testAssemblies'
searchFolder: '$(Pipeline.Workspace)\$(TestArtifactsName)'
vsTestVersion: 'toolsInstaller'
uiTests: true
rerunFailedTests: true
testRunTitle: 'UITests_${{ parameters.platform }}_${{ parameters.installMode }}'
# Since UITests-FancyZonesEditor.dll is generated in both UITests-FancyZonesEditor and UITests-FancyZones, removed one to avoid duplicate test runs
testAssemblyVer2: |
**\*UITest*.dll
!**\obj\**
!**\ref\**
!**\UITests-FancyZones\**\UITests-FancyZonesEditor.dll
env:
platform: '$(TestPlatform)'
useInstallerForTest: ${{ ne(parameters.buildSource, 'buildNow') }}
- ${{ if ne(length(parameters.uiTestModules), 0) }}:
- ${{ each module in parameters.uiTestModules }}:
- task: VSTest@3
displayName: Run UI Test - ${{ module }}
inputs:
platform: '$(BuildPlatform)'
configuration: '$(BuildConfiguration)'
testSelector: 'testAssemblies'
searchFolder: '$(Pipeline.Workspace)\$(TestArtifactsName)'
vsTestVersion: 'toolsInstaller'
uiTests: true
rerunFailedTests: true
testRunTitle: 'UITests_${{ parameters.platform }}_${{ parameters.installMode }}'
testAssemblyVer2: |
**\*${{ module }}*.dll
!**\obj\**
!**\ref\**
!**\UITests-FancyZones\**\UITests-FancyZonesEditor.dll
env:
platform: '$(TestPlatform)'
useInstallerForTest: ${{ ne(parameters.buildSource, 'buildNow') }}
- script: |
dotnet test $(Build.SourcesDirectory)\src\modules\fancyzones\FancyZones.UITests\FancyZones.UITests.csproj --no-build -c $(BuildConfiguration) -p:Platform=$(BuildPlatform)
dotnet test $(Build.SourcesDirectory)\src\modules\fancyzones\FancyZonesEditor.UITests\FancyZonesEditor.UITests.csproj --no-build -c $(BuildConfiguration) -p:Platform=$(BuildPlatform)
displayName: "Run UI Tests"

View File

@@ -93,7 +93,8 @@ if ($noticeMatch.Success) {
# Test-only packages that are allowed to be in NOTICE.md but not in the build
# (e.g., when BuildTests=false, these packages won't appear in the NuGet list)
$allowedExtraPackages = @(
"- Moq"
"- Moq",
"- MSTest"
)
if (!$noticeFile.Trim().EndsWith($returnList.Trim()))

View File

@@ -20,6 +20,23 @@
<NuGetAuditMode>direct</NuGetAuditMode>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion> <!-- Don't add source revision hash to the product version of binaries. -->
<PlatformTarget>$(Platform)</PlatformTarget>
<!-- Enable Microsoft.Testing.Platform -->
<EnableMSTestRunner>true</EnableMSTestRunner>
<TestingPlatformShowTestsFailure>true</TestingPlatformShowTestsFailure>
<TestingPlatformDotNetTestSupport>true</TestingPlatformDotNetTestSupport>
<TestingPlatformCommandLineArguments>$(TestingPlatformCommandLineArguments) --report-trx</TestingPlatformCommandLineArguments>
<!-- No arm64 agents to run the tests. -->
<TestingPlatformDisableCustomTestTarget Condition="'$(Platform)' == 'ARM64'">true</TestingPlatformDisableCustomTestTarget>
</PropertyGroup>
<!--
UI tests are run in dedicated UI test jobs/pipelines.
In CI, the main build uses `/t:Build;Test` across the full solution, so
prevent UI test projects from being executed in that pass.
-->
<PropertyGroup Condition="'$(TF_BUILD)' != '' and $(MSBuildProjectName.Contains('UITest'))">
<TestingPlatformDisableCustomTestTarget>true</TestingPlatformDisableCustomTestTarget>
</PropertyGroup>
<!--
@@ -82,7 +99,15 @@
</PackageReference>
</ItemGroup>
<!-- Add ability to run tests via "msbuild /t:Test" -->
<!-- In CI, we build and test with `/t:Build;Test` -->
<!-- So, for non-test projects, we want the target to be there and it's basically doing nothing -->
<!-- For C# test projects, Microsoft.Testing.Platform should inject Test target here: -->
<!-- https://github.com/microsoft/testfx/blob/5ad21909704db501f58f27d4a7ec241edd761af5/src/Platform/Microsoft.Testing.Platform.MSBuild/buildMultiTargeting/Microsoft.Testing.Platform.MSBuild.targets#L270-L273 -->
<!-- For C++ test projects, the RunVSTest SDK will do its job -->
<Target Name="Test" />
<!-- Add ability to run tests via "msbuild /t:Test" using the RunVSTest SDK -->
<!-- This is only needed for C++, as we use Microsoft.Testing.Platform for C# -->
<!--
Work around an MSBuild bug where Microsoft.Common.Test.targets is missing from the Arm64 installation.
See: https://github.com/dotnet/msbuild/pull/9984
@@ -92,11 +117,11 @@
Once the change referenced above is fixed, the ImportGroup below can be replaced with:
<Sdk Name="Microsoft.Build.RunVSTest" Version="1.0.319" />
-->
<ImportGroup Condition="'$(PROCESSOR_ARCHITECTURE)' != 'ARM64'">
<ImportGroup Condition="'$(PROCESSOR_ARCHITECTURE)' != 'ARM64' AND ('$(Language)' == 'C++' OR '$(MSBuildProjectExtension)' == '.vcxproj')">
<Import Project="Sdk.props" Sdk="Microsoft.Build.RunVSTest" Version="1.0.319" />
<Import Project="Sdk.targets" Sdk="Microsoft.Build.RunVSTest" Version="1.0.319" />
</ImportGroup>
<PropertyGroup>
<PropertyGroup Condition="'$(Language)' == 'C++' OR '$(MSBuildProjectExtension)' == '.vcxproj'">
<VSTestLogger>trx</VSTestLogger>
<!--
RunVSTest by default uses %VSINSTALLDIR%\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe,

View File

@@ -2,6 +2,7 @@
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
<MSTestVersion>3.8.3</MSTestVersion>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="AdaptiveCards.ObjectModel.WinUI3" Version="2.0.0-beta" />
@@ -86,7 +87,8 @@
<PackageVersion Include="ModernWpfUI" Version="0.9.4" />
<!-- Moq to stay below v4.20 due to behavior change. need to be sure fixed -->
<PackageVersion Include="Moq" Version="4.18.4" />
<PackageVersion Include="MSTest" Version="3.8.3" />
<PackageVersion Include="MSTest" Version="$(MSTestVersion)" />
<PackageVersion Include="MSTest.TestFramework" Version="$(MSTestVersion)" />
<PackageVersion Include="NJsonSchema" Version="11.4.0" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="NLog" Version="5.2.8" />

View File

@@ -1582,6 +1582,7 @@ SOFTWARE.
- ModernWpfUI
- Moq
- MSTest
- MSTest.TestFramework
- NJsonSchema
- NLog
- NLog.Extensions.Logging
@@ -1602,4 +1603,4 @@ SOFTWARE.
- WinUIEx
- WmiLight
- WPF-UI
- WyHash
- WyHash

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />

View File

@@ -4,8 +4,9 @@
<Import Project=".\Common.Dotnet.PrepareGeneratedFolder.targets" />
<PropertyGroup>
<CoreTargetFramework>net9.0</CoreTargetFramework>
<WindowsSdkPackageVersion>10.0.26100.68-preview</WindowsSdkPackageVersion>
<TargetFramework>net9.0-windows10.0.26100.0</TargetFramework>
<TargetFramework>$(CoreTargetFramework)-windows10.0.26100.0</TargetFramework>
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>

View File

@@ -7,4 +7,13 @@
<PropertyGroup>
<TargetFramework>net8.0-windows10.0.26100.0</TargetFramework>
</PropertyGroup>
<!--
In CI, the main build runs `/t:Build;Test` across the full solution.
Fuzz test projects are built for OneFuzz ingestion, but should not be
executed as regular MSTest tests in this pass.
-->
<PropertyGroup Condition="'$(TF_BUILD)' != ''">
<TestingPlatformDisableCustomTestTarget>true</TestingPlatformDisableCustomTestTarget>
</PropertyGroup>
</Project>

View File

@@ -8,7 +8,6 @@ using System.Runtime.CompilerServices;
using System.Xml.Linq;
using ABI.Windows.Foundation;
using Microsoft.PowerToys.UITest;
using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Appium;

View File

@@ -15,7 +15,8 @@
<ItemGroup>
<PackageReference Include="Appium.WebDriver" />
<PackageReference Include="MSTest" />
<!-- Test libraries/utilities should not use the metapackage. -->
<PackageReference Include="MSTest.TestFramework" />
<PackageReference Include="System.IO.Abstractions" />
<PackageReference Include="System.Text.RegularExpressions" />
<PackageReference Include="CoenM.ImageSharp.ImageHash" />

View File

@@ -4,7 +4,7 @@
<PropertyGroup>
<IsPackable>false</IsPackable>
<OutputType>Library</OutputType>
<OutputType>Exe</OutputType>
<RootNamespace>Microsoft.Interop.Tests</RootNamespace>
<AssemblyName>Microsoft.Interop.Tests</AssemblyName>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>

View File

@@ -3,6 +3,10 @@
<Import Project="$(RepoRoot)src\Common.Dotnet.CsWinRT.props" />
<PropertyGroup>
<SelfContained>true</SelfContained>
<RuntimeIdentifier Condition="'$(Platform)' == 'x64'">win-x64</RuntimeIdentifier>
<RuntimeIdentifier Condition="'$(Platform)' == 'ARM64'">win-arm64</RuntimeIdentifier>
<OutputType>Exe</OutputType>
<IsPackable>false</IsPackable>
<OutputPath>$(RepoRoot)$(Configuration)\$(Platform)\tests\PowerToys.DSC.Tests\</OutputPath>
</PropertyGroup>

View File

@@ -46,6 +46,7 @@
<Message Text="Generating DSC resource JSON files to DSCModules subfolder..." Importance="high" />
<MakeDir Directories="$(TargetDir)DSCModules" />
<Exec Command="dotnet &quot;$(TargetPath)&quot; manifest --resource settings --outputDir &quot;$(TargetDir)DSCModules&quot;" />
<Exec Command="&quot;$(TargetDir)$(AssemblyName).exe&quot; manifest --resource settings --outputDir &quot;$(TargetDir)DSCModules&quot;" Condition="'$(SelfContained)' == 'true'" />
<Exec Command="dotnet &quot;$(TargetPath)&quot; manifest --resource settings --outputDir &quot;$(TargetDir)DSCModules&quot;" Condition="'$(SelfContained)' != 'true'" />
</Target>
</Project>

View File

@@ -6,6 +6,12 @@
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<OutputType>Exe</OutputType>
<!-- exit code 8 means no tests ran. -->
<!-- Doc: https://learn.microsoft.com/dotnet/core/testing/unit-testing-platform-exit-codes -->
<!-- This test project doesn't seem to contain any tests. -->
<TestingPlatformCommandLineArguments>$(TestingPlatformCommandLineArguments) --ignore-exit-code 8</TestingPlatformCommandLineArguments>
</PropertyGroup>
<PropertyGroup>
<OutputPath>$(RepoRoot)$(Platform)\$(Configuration)\tests\AdvancedPaste.FuzzTests\</OutputPath>

View File

@@ -3,11 +3,14 @@
<Import Project="$(RepoRoot)src\Common.Dotnet.CsWinRT.props" />
<PropertyGroup>
<SelfContained>true</SelfContained>
<RuntimeIdentifier Condition="'$(Platform)' == 'x64'">win-x64</RuntimeIdentifier>
<RuntimeIdentifier Condition="'$(Platform)' == 'ARM64'">win-arm64</RuntimeIdentifier>
<IsPackable>false</IsPackable>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\tests\AdvancedPaste.UnitTests\</OutputPath>
<IsTestProject>true</IsTestProject>
<OutputType>Exe</OutputType>
</PropertyGroup>
<ItemGroup>

View File

@@ -7,6 +7,11 @@
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<DefineConstants>TESTONLY</DefineConstants>
<!-- exit code 8 means no tests ran. -->
<!-- Doc: https://learn.microsoft.com/dotnet/core/testing/unit-testing-platform-exit-codes -->
<!-- This test project doesn't seem to contain any tests. -->
<TestingPlatformCommandLineArguments>$(TestingPlatformCommandLineArguments) --ignore-exit-code 8</TestingPlatformCommandLineArguments>
</PropertyGroup>
<PropertyGroup>

View File

@@ -9,6 +9,7 @@
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\tests\Hosts.Tests\</OutputPath>
<RootNamespace>Hosts.Tests</RootNamespace>
<AssemblyName>PowerToys.Hosts.Tests</AssemblyName>
<OutputType>Exe</OutputType>
</PropertyGroup>
<ItemGroup>

View File

@@ -8,7 +8,7 @@
<AssemblyName>PowerToys.MouseJump.Common.UnitTests</AssemblyName>
<AssemblyTitle>PowerToys.MouseJump.Common.UnitTests</AssemblyTitle>
<AssemblyDescription>PowerToys MouseJump.Common.UnitTests</AssemblyDescription>
<OutputType>Library</OutputType>
<OutputType>Exe</OutputType>
<OutputPath>$(RepoRoot)$(Platform)\$(Configuration)\tests\MouseJump.Common.UnitTests\</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>

View File

@@ -6,7 +6,13 @@
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<OutputType>Library</OutputType>
<OutputType>Exe</OutputType>
<!-- exit code 8 means no tests ran. -->
<!-- Doc: https://learn.microsoft.com/dotnet/core/testing/unit-testing-platform-exit-codes -->
<!-- This test project contains a single test but it's ignored. -->
<!-- Remove this line if more tests are added or if the test is un-ignored -->
<TestingPlatformCommandLineArguments>$(TestingPlatformCommandLineArguments) --ignore-exit-code 8</TestingPlatformCommandLineArguments>
</PropertyGroup>
<ItemGroup>

View File

@@ -2,10 +2,13 @@
<Import Project="$(RepoRoot)src\Common.Dotnet.CsWinRT.props" />
<PropertyGroup>
<SelfContained>true</SelfContained>
<RuntimeIdentifier Condition="'$(Platform)' == 'x64'">win-x64</RuntimeIdentifier>
<RuntimeIdentifier Condition="'$(Platform)' == 'ARM64'">win-arm64</RuntimeIdentifier>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<OutputType>Library</OutputType>
<OutputType>Exe</OutputType>
<RunVSTest>false</RunVSTest>
<IsTestProject>true</IsTestProject>
<IsPackable>false</IsPackable>

View File

@@ -34,13 +34,15 @@ namespace winrt
using namespace Windows::Devices::Enumeration;
}
AudioSampleGenerator::AudioSampleGenerator(bool captureMicrophone, bool captureSystemAudio)
AudioSampleGenerator::AudioSampleGenerator(bool captureMicrophone, bool captureSystemAudio, bool micMonoMix)
: m_captureMicrophone(captureMicrophone)
, m_captureSystemAudio(captureSystemAudio)
, m_micMonoMix(micMonoMix)
{
OutputDebugStringA(("AudioSampleGenerator created, captureMicrophone=" +
std::string(captureMicrophone ? "true" : "false") +
", captureSystemAudio=" + std::string(captureSystemAudio ? "true" : "false") + "\n").c_str());
", captureSystemAudio=" + std::string(captureSystemAudio ? "true" : "false") +
", micMonoMix=" + std::string(micMonoMix ? "true" : "false") + "\n").c_str());
m_audioEvent.create(wil::EventOptions::ManualReset);
m_endEvent.create(wil::EventOptions::ManualReset);
m_startEvent.create(wil::EventOptions::ManualReset);
@@ -631,6 +633,30 @@ void AudioSampleGenerator::OnAudioQuantumStarted(winrt::AudioGraph const& sender
uint32_t expectedSamplesPerQuantum = (m_graphSampleRate / 100) * m_graphChannels;
uint32_t numMicSamples = audioBuffer.Length() / sizeof(float);
// Apply mono mixing to microphone audio if enabled
// This converts stereo mic input (with same signal on both channels) to true mono
// by averaging the channels and writing the result to both channels
if (m_micMonoMix && m_captureMicrophone && numMicSamples > 0 && m_graphChannels >= 2)
{
float* micData = reinterpret_cast<float*>(sampleBuffer.data());
uint32_t numFrames = numMicSamples / m_graphChannels;
for (uint32_t i = 0; i < numFrames; i++)
{
// Sum all channels for this frame
float sum = 0.0f;
for (uint32_t ch = 0; ch < m_graphChannels; ch++)
{
sum += micData[i * m_graphChannels + ch];
}
// Power-preserving mix: divide by sqrt(N) to maintain perceived loudness
float mono = sum / std::sqrt(static_cast<float>(m_graphChannels));
for (uint32_t ch = 0; ch < m_graphChannels; ch++)
{
micData[i * m_graphChannels + ch] = mono;
}
}
}
// Drain loopback samples regardless of whether we have mic audio
if (m_loopbackCapture)
{

View File

@@ -5,7 +5,7 @@
class AudioSampleGenerator
{
public:
AudioSampleGenerator(bool captureMicrophone = true, bool captureSystemAudio = true);
AudioSampleGenerator(bool captureMicrophone = true, bool captureSystemAudio = true, bool micMonoMix = false);
~AudioSampleGenerator();
winrt::Windows::Foundation::IAsyncAction InitializeAsync();
@@ -70,4 +70,5 @@ private:
std::atomic<bool> m_started = false;
bool m_captureMicrophone = true;
bool m_captureSystemAudio = true;
bool m_micMonoMix = false;
};

View File

@@ -861,6 +861,7 @@ VideoRecordingSession::VideoRecordingSession(
uint32_t frameRate,
bool captureAudio,
bool captureSystemAudio,
bool micMonoMix,
winrt::Streams::IRandomAccessStream const& stream)
{
m_device = device;
@@ -964,7 +965,7 @@ VideoRecordingSession::VideoRecordingSession(
winrt::check_hresult(m_d3dDevice->CreateRenderTargetView(backBuffer.get(), nullptr, m_renderTargetView.put()));
// Always create audio generator for loopback capture; captureAudio controls microphone
m_audioGenerator = std::make_unique<AudioSampleGenerator>(captureAudio, captureSystemAudio);
m_audioGenerator = std::make_unique<AudioSampleGenerator>(captureAudio, captureSystemAudio, micMonoMix);
}
@@ -1112,9 +1113,10 @@ std::shared_ptr<VideoRecordingSession> VideoRecordingSession::Create(
uint32_t frameRate,
bool captureAudio,
bool captureSystemAudio,
bool micMonoMix,
winrt::Streams::IRandomAccessStream const& stream)
{
return std::shared_ptr<VideoRecordingSession>(new VideoRecordingSession(device, item, crop, frameRate, captureAudio, captureSystemAudio, stream));
return std::shared_ptr<VideoRecordingSession>(new VideoRecordingSession(device, item, crop, frameRate, captureAudio, captureSystemAudio, micMonoMix, stream));
}
//----------------------------------------------------------------------------

View File

@@ -28,6 +28,7 @@ public:
uint32_t frameRate,
bool captureAudio,
bool captureSystemAudio,
bool micMonoMix,
winrt::Streams::IRandomAccessStream const& stream);
~VideoRecordingSession();
@@ -188,6 +189,7 @@ private:
uint32_t frameRate,
bool captureAudio,
bool captureSystemAudio,
bool micMonoMix,
winrt::Streams::IRandomAccessStream const& stream);
void CloseInternal();

View File

@@ -279,6 +279,7 @@ BEGIN
LTEXT "To record a specific window, enter the hotkey with the Alt key in the opposite mode.",IDC_STATIC,7,55,251,19
CONTROL "Capture &system audio",IDC_CAPTURE_SYSTEM_AUDIO,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | WS_TABSTOP,7,149,83,10
CONTROL "&Capture audio input:",IDC_CAPTURE_AUDIO,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | WS_TABSTOP,7,161,83,10
CONTROL "Mono",IDC_MIC_MONO_MIX,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | WS_TABSTOP,98,161,30,10
COMBOBOX IDC_MICROPHONE,81,176,152,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
LTEXT "Microphone:",IDC_MICROPHONE_LABEL,32,178,47,8
END

View File

@@ -51,6 +51,7 @@ DWORD g_RecordScalingMP4 = 100;
RecordingFormat g_RecordingFormat = RecordingFormat::MP4;
BOOLEAN g_CaptureSystemAudio = TRUE;
BOOLEAN g_CaptureAudio = FALSE;
BOOLEAN g_MicMonoMix = FALSE;
TCHAR g_MicrophoneDeviceId[MAX_PATH] = {0};
TCHAR g_RecordingSaveLocationBuffer[MAX_PATH] = {0};
TCHAR g_ScreenshotSaveLocationBuffer[MAX_PATH] = {0};
@@ -99,6 +100,7 @@ REG_SETTING RegSettings[] = {
{ L"RecordScalingMP4", SETTING_TYPE_DWORD, 0, &g_RecordScalingMP4, static_cast<DOUBLE>(g_RecordScalingMP4) },
{ L"CaptureAudio", SETTING_TYPE_BOOLEAN, 0, &g_CaptureAudio, static_cast<DOUBLE>(g_CaptureAudio) },
{ L"CaptureSystemAudio", SETTING_TYPE_BOOLEAN, 0, &g_CaptureSystemAudio, static_cast<DOUBLE>(g_CaptureSystemAudio) },
{ L"MicMonoMix", SETTING_TYPE_BOOLEAN, 0, &g_MicMonoMix, static_cast<DOUBLE>(g_MicMonoMix) },
{ L"MicrophoneDeviceId", SETTING_TYPE_STRING, sizeof(g_MicrophoneDeviceId), g_MicrophoneDeviceId, static_cast<DOUBLE>(0) },
{ L"RecordingSaveLocation", SETTING_TYPE_STRING, sizeof(g_RecordingSaveLocationBuffer), g_RecordingSaveLocationBuffer, static_cast<DOUBLE>(0) },
{ L"ScreenshotSaveLocation", SETTING_TYPE_STRING, sizeof(g_ScreenshotSaveLocationBuffer), g_ScreenshotSaveLocationBuffer, static_cast<DOUBLE>(0) },

View File

@@ -3840,6 +3840,9 @@ INT_PTR CALLBACK OptionsProc( HWND hDlg, UINT message,
CheckDlgButton( g_OptionsTabs[RECORD_PAGE].hPage, IDC_CAPTURE_AUDIO,
g_CaptureAudio ? BST_CHECKED: BST_UNCHECKED );
CheckDlgButton( g_OptionsTabs[RECORD_PAGE].hPage, IDC_MIC_MONO_MIX,
g_MicMonoMix ? BST_CHECKED: BST_UNCHECKED );
//
// The framerate drop down list is not used in the current version (might be added in the future)
//
@@ -4260,6 +4263,7 @@ INT_PTR CALLBACK OptionsProc( HWND hDlg, UINT message,
g_ShowExpiredTime = IsDlgButtonChecked( g_OptionsTabs[BREAK_PAGE].hPage, IDC_CHECK_SHOW_EXPIRED ) == BST_CHECKED;
g_CaptureSystemAudio = IsDlgButtonChecked(g_OptionsTabs[RECORD_PAGE].hPage, IDC_CAPTURE_SYSTEM_AUDIO) == BST_CHECKED;
g_CaptureAudio = IsDlgButtonChecked(g_OptionsTabs[RECORD_PAGE].hPage, IDC_CAPTURE_AUDIO) == BST_CHECKED;
g_MicMonoMix = IsDlgButtonChecked(g_OptionsTabs[RECORD_PAGE].hPage, IDC_MIC_MONO_MIX) == BST_CHECKED;
GetDlgItemText( g_OptionsTabs[BREAK_PAGE].hPage, IDC_TIMER, text, 3 );
text[2] = 0;
newTimeout = _tstoi( text );
@@ -5605,6 +5609,7 @@ winrt::fire_and_forget StartRecordingAsync( HWND hWnd, LPRECT rcCrop, HWND hWndR
g_RecordFrameRate,
g_CaptureAudio,
g_CaptureSystemAudio,
g_MicMonoMix,
stream );
recordingStarted = (g_RecordingSession != nullptr);
@@ -7291,7 +7296,8 @@ LRESULT APIENTRY MainWndProc(
case WM_IME_CHAR:
case WM_CHAR:
if( (g_TypeMode != TypeModeOff) && iswprint(static_cast<TCHAR>(wParam)) || (static_cast<TCHAR>(wParam) == L'&')) {
if( (g_TypeMode != TypeModeOff) &&
(iswprint(static_cast<TCHAR>(wParam)) || (static_cast<TCHAR>(wParam) == L'&')) ) {
g_HaveTyped = TRUE;
TCHAR vKey = static_cast<TCHAR>(wParam);
@@ -7399,9 +7405,8 @@ LRESULT APIENTRY MainWndProc(
case WM_KEYDOWN:
if( (g_TypeMode != TypeModeOff) && g_HaveTyped && static_cast<char>(wParam) != VK_UP && static_cast<char>(wParam) != VK_DOWN &&
(isprint( static_cast<char>(wParam)) ||
wParam == VK_RETURN || wParam == VK_DELETE || wParam == VK_BACK )) {
if( (g_TypeMode != TypeModeOff) && g_HaveTyped &&
(wParam == VK_RETURN || wParam == VK_DELETE || wParam == VK_BACK) ) {
if( wParam == VK_RETURN ) {

View File

@@ -111,6 +111,7 @@
#define IDC_SMOOTH_IMAGE 1107
#define IDC_CAPTURE_SYSTEM_AUDIO 1108
#define IDC_MICROPHONE_LABEL 1109
#define IDC_MIC_MONO_MIX 1110
#define IDC_SAVE 40002
#define IDC_COPY 40004
#define IDC_RECORD 40006

View File

@@ -1,26 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\CoreCommonProps.props" />
<PropertyGroup>
<RootNamespace>Microsoft.CmdPal.Core.Common</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@@ -1,83 +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.Text.RegularExpressions;
using Microsoft.CmdPal.Core.Common.Services.Sanitizer.Abstraction;
namespace Microsoft.CmdPal.Core.Common.Services.Sanitizer;
internal sealed partial class PiiRuleProvider : ISanitizationRuleProvider
{
public IEnumerable<SanitizationRule> GetRules()
{
yield return new(EmailRx(), "[EMAIL_REDACTED]", "Email addresses");
yield return new(SsnRx(), "[SSN_REDACTED]", "Social Security Numbers");
yield return new(CreditCardRx(), "[CARD_REDACTED]", "Credit card numbers");
// phone number regex is the most generic, so it goes last
// we can't make this too generic; otherwise we over-redact error codes, dates, etc.
yield return new(PhoneRx(), "[PHONE_REDACTED]", "Phone numbers");
}
[GeneratedRegex(@"\b[a-zA-Z0-9]([a-zA-Z0-9._%-]*[a-zA-Z0-9])?@[a-zA-Z0-9]([a-zA-Z0-9.-]*[a-zA-Z0-9])?\.[a-zA-Z]{2,}\b",
SanitizerDefaults.DefaultOptions, SanitizerDefaults.DefaultMatchTimeoutMs)]
private static partial Regex EmailRx();
[GeneratedRegex("""
(?xi)
# ---------- boundaries ----------
(?<!\w) # not after a letter/digit/underscore
(?<![A-Za-z0-9]-) # avoid starting inside hyphenated tokens (GUID middles, etc.)
# ---------- global do-not-match guards ----------
(?! # ISO date (yyyy-mm-dd / yyyy.mm.dd / yyyy/mm/dd)
(?:19|20)\d{2}[-./](?:0[1-9]|1[0-2])[-./](?:0[1-9]|[12]\d|3[01])\b
)
(?! # EU date (dd-mm-yyyy / dd.mm.yyyy / dd/mm/yyyy)
(?:0[1-9]|[12]\d|3[01])[-./](?:0[1-9]|1[0-2])[-./](?:19|20)\d{2}\b
)
(?! # ISO datetime like 2025-08-24T14:32[:ss][Z|±hh:mm]
(?:19|20)\d{2}-\d{2}-\d{2}[T\s]\d{2}:\d{2}(?::\d{2})?(?:Z|[+-]\d{2}:\d{2})?\b
)
(?!\b(?:\d{1,3}\.){3}\d{1,3}(?::\d{1,5})?\b) # IPv4 with optional :port
(?!\b[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}\b) # GUID, lowercase
(?!\b[0-9A-F]{8}-(?:[0-9A-F]{4}-){3}[0-9A-F]{12}\b) # GUID, uppercase
(?!\bv?\d+(?:\.\d+){2,}\b) # semantic/file versions like 1.2.3 or 10.0.22631.3448
(?!\b(?:[0-9A-F]{2}[:-]){5}[0-9A-F]{2}\b) # MAC address
# ---------- digit budget ----------
(?=(?:\D*\d){7,15}) # 715 digits in total
# ---------- number body ----------
(?:
# A with explicit country code, allow compact digits (E.164-ish) or grouped
(?:\+|00)[1-9]\d{0,2}
(?:
[\p{Zs}.\-\/]*\d{6,14}
|
[\p{Zs}.\-\/]* (?:\(\d{1,4}\)|\d{1,4})
(?:[\p{Zs}.\-\/]+(?:\(\d{2,4}\)|\d{2,4})){1,6}
)
|
# B no country code => require separators between blocks (avoid plain big ints)
(?:\(\d{1,4}\)|\d{1,4})
(?:[\p{Zs}.\-\/]+(?:\(\d{2,4}\)|\d{2,4})){1,6}
)
# ---------- optional extension ----------
(?:[\p{Zs}.\-,:;]* (?:ext\.?|x) [\p{Zs}]* (?<ext>\d{1,6}))?
(?!-\w) # don't end just before '-letter'/'-digit'
""",
SanitizerDefaults.DefaultOptions | RegexOptions.IgnorePatternWhitespace, SanitizerDefaults.DefaultMatchTimeoutMs)]
private static partial Regex PhoneRx();
[GeneratedRegex(@"\b\d{3}-\d{2}-\d{4}\b",
SanitizerDefaults.DefaultOptions, SanitizerDefaults.DefaultMatchTimeoutMs)]
private static partial Regex SsnRx();
[GeneratedRegex(@"\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b",
SanitizerDefaults.DefaultOptions, SanitizerDefaults.DefaultMatchTimeoutMs)]
private static partial Regex CreditCardRx();
}

View File

@@ -1,12 +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 Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
public record HideDetailsMessage()
{
}

View File

@@ -1,12 +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 Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
public record LaunchUriMessage(Uri Uri)
{
}

View File

@@ -1,12 +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 Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
public record ShowDetailsMessage(DetailsViewModel Details)
{
}

View File

@@ -1,25 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\CoreCommonProps.props" />
<PropertyGroup>
<EnableCoreMrtTooling>false</EnableCoreMrtTooling>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Common" />
<PackageReference Include="CommunityToolkit.Mvvm" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.CmdPal.Core.Common\Microsoft.CmdPal.Core.Common.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
</Project>

View File

@@ -1,4 +0,0 @@
{
"$schema": "https://aka.ms/CsWin32.schema.json",
"allowMarshaling": false
}

View File

@@ -1,19 +0,0 @@
GetPhysicallyInstalledSystemMemory
GlobalMemoryStatusEx
GetSystemInfo
CoCreateInstance
SetForegroundWindow
IsIconic
RegisterHotKey
SetWindowLongPtr
CallWindowProc
ShowWindow
SetForegroundWindow
SetFocus
SetActiveWindow
MonitorFromWindow
GetMonitorInfo
SHCreateStreamOnFileEx
CoAllowSetForegroundWindow
SHCreateStreamOnFileEx
SHLoadIndirectString

View File

@@ -1,72 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Microsoft.CmdPal.Core.ViewModels.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// 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.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.CmdPal.Core.ViewModels.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Show details.
/// </summary>
public static string ShowDetailsCommand {
get {
return ResourceManager.GetString("ShowDetailsCommand", resourceCulture);
}
}
}
}

View File

@@ -1,124 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ShowDetailsCommand" xml:space="preserve">
<value>Show details</value>
<comment>Name for the command that shows details of an item</comment>
</data>
</root>

View File

@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CmdPal.Core.Common;
namespace Microsoft.CmdPal.Common;
/// <summary>
/// Represents the packaging flavor of the application.

View File

@@ -4,7 +4,7 @@
using System;
namespace Microsoft.CmdPal.Core.Common;
namespace Microsoft.CmdPal.Common;
public static class CoreLogger
{

View File

@@ -2,10 +2,9 @@
// 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.Runtime.InteropServices;
namespace Microsoft.CmdPal.Core.Common.Helpers;
namespace Microsoft.CmdPal.Common.Helpers;
/// <summary>
/// Provides utility methods for building diagnostic and error messages.

View File

@@ -2,12 +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;
using System.Threading.Tasks;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Core.Common;
namespace Microsoft.CmdPal.Common;
public partial class ExtensionHostInstance
{

View File

@@ -2,9 +2,9 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.CmdPal.Core.Common.Text;
using Microsoft.CmdPal.Common.Text;
namespace Microsoft.CmdPal.Core.Common.Helpers;
namespace Microsoft.CmdPal.Common.Helpers;
/// <summary>
/// Represents an item that can provide precomputed fuzzy matching targets for its title and subtitle.

View File

@@ -2,9 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Threading;
namespace Microsoft.CmdPal.Core.Common.Helpers;
namespace Microsoft.CmdPal.Common.Helpers;
/// <summary>
/// Thread-safe boolean implementation using atomic operations

View File

@@ -4,9 +4,9 @@
using System.Buffers;
using System.Diagnostics;
using Microsoft.CmdPal.Core.Common.Text;
using Microsoft.CmdPal.Common.Text;
namespace Microsoft.CmdPal.Core.Common.Helpers;
namespace Microsoft.CmdPal.Common.Helpers;
public static partial class InternalListHelpers
{

View File

@@ -2,12 +2,9 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Threading;
using Microsoft.UI.Dispatching;
namespace Microsoft.CmdPal.Core.Common.Helpers;
namespace Microsoft.CmdPal.Common.Helpers;
public static partial class NativeEventWaiter
{

View File

@@ -6,7 +6,7 @@ using System.Runtime.CompilerServices;
using Windows.Win32;
using Windows.Win32.Storage.FileSystem;
namespace Microsoft.CmdPal.Core.Common.Helpers;
namespace Microsoft.CmdPal.Common.Helpers;
public static class PathHelper
{

View File

@@ -2,11 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.CmdPal.Core.Common.Helpers;
namespace Microsoft.CmdPal.Common.Helpers;
/// <summary>
/// An async gate that ensures only one operation runs at a time.

View File

@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CmdPal.Core.Common.Helpers;
namespace Microsoft.CmdPal.Common.Helpers;
/// <summary>
/// An async gate that ensures only one value computation runs at a time.

View File

@@ -5,7 +5,7 @@
using System.Diagnostics;
using Windows.ApplicationModel;
namespace Microsoft.CmdPal.Core.Common.Helpers;
namespace Microsoft.CmdPal.Common.Helpers;
/// <summary>
/// Helper class for retrieving application version information safely.

View File

@@ -4,10 +4,9 @@
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Windows.System;
namespace Microsoft.CmdPal.Core.Common.Helpers;
namespace Microsoft.CmdPal.Common.Helpers;
/// <summary>
/// Well-known key chords used in the Command Palette and extensions.

View File

@@ -1,7 +1,9 @@
<Project>
<Import Project="..\..\Common.Dotnet.CsWinRT.props" />
<Import Project="..\..\Common.Dotnet.AotCompatibility.props" />
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\Common.Dotnet.CsWinRT.props" />
<Import Project="..\..\..\Common.Dotnet.AotCompatibility.props" />
<PropertyGroup>
<RootNamespace>Microsoft.CmdPal.Core.Common</RootNamespace>
<Nullable>enable</Nullable>
<!-- For MVVM Toolkit Partial Properties/AOT support -->
<LangVersion>preview</LangVersion>
@@ -18,11 +20,19 @@
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<PropertyGroup>
<CsWinRTAotOptimizerEnabled>true</CsWinRTAotOptimizerEnabled>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" />
<PackageReference Include="Microsoft.Windows.CsWin32">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
@@ -32,21 +42,14 @@
<!-- This line forces the WebView2 version used by Windows App SDK to be the one we expect from Directory.Packages.props . -->
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(MSBuildThisFileDirectory)\extensionsdk\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
<_Parameter1>$(AssemblyName).UnitTests</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\extensionsdk\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
</ItemGroup>
</Project>

View File

@@ -8,7 +8,7 @@
// </auto-generated>
//------------------------------------------------------------------------------
namespace Microsoft.CmdPal.Core.Common.Properties {
namespace Microsoft.CmdPal.Common.Properties {
using System;

View File

@@ -5,11 +5,11 @@
using System.Globalization;
using System.Runtime.InteropServices;
using System.Security.Principal;
using Microsoft.CmdPal.Core.Common.Helpers;
using Microsoft.CmdPal.Common.Helpers;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Windows.ApplicationModel;
namespace Microsoft.CmdPal.Core.Common.Services;
namespace Microsoft.CmdPal.Common.Services;
/// <summary>
/// Implementation of IApplicationInfoService providing application-wide information.

View File

@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CmdPal.Core.Common.Services;
namespace Microsoft.CmdPal.Common.Services;
/// <summary>
/// Provides access to application-wide information such as version, packaging flavor, and directory paths.

View File

@@ -2,11 +2,9 @@
// 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.Threading.Tasks;
using Windows.Foundation;
namespace Microsoft.CmdPal.Core.Common.Services;
namespace Microsoft.CmdPal.Common.Services;
public interface IExtensionService
{

View File

@@ -2,13 +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;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.CommandPalette.Extensions;
using Windows.ApplicationModel;
namespace Microsoft.CmdPal.Core.Common.Services;
namespace Microsoft.CmdPal.Common.Services;
public interface IExtensionWrapper
{

View File

@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CmdPal.Core.Common.Services;
namespace Microsoft.CmdPal.Common.Services;
public interface IRunHistoryService
{

View File

@@ -3,9 +3,9 @@
// See the LICENSE file in the project root for more information.
using System.Runtime.InteropServices;
using Microsoft.CmdPal.Core.Common.Services.Sanitizer;
using Microsoft.CmdPal.Common.Services.Sanitizer;
namespace Microsoft.CmdPal.Core.Common.Services.Reports;
namespace Microsoft.CmdPal.Common.Services.Reports;
public sealed class ErrorReportBuilder : IErrorReportBuilder
{

View File

@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CmdPal.Core.Common.Services.Reports;
namespace Microsoft.CmdPal.Common.Services.Reports;
/// <summary>
/// Defines a contract for creating human-readable error reports from exceptions,

View File

@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CmdPal.Core.Common.Services.Sanitizer.Abstraction;
namespace Microsoft.CmdPal.Common.Services.Sanitizer.Abstraction;
/// <summary>
/// Defines a service that sanitizes text by applying a set of configurable, regex-based rules.

View File

@@ -4,7 +4,7 @@
using System.Text.RegularExpressions;
namespace Microsoft.CmdPal.Core.Common.Services.Sanitizer.Abstraction;
namespace Microsoft.CmdPal.Common.Services.Sanitizer.Abstraction;
public readonly record struct SanitizationRule
{

View File

@@ -3,9 +3,9 @@
// See the LICENSE file in the project root for more information.
using System.Text.RegularExpressions;
using Microsoft.CmdPal.Core.Common.Services.Sanitizer.Abstraction;
using Microsoft.CmdPal.Common.Services.Sanitizer.Abstraction;
namespace Microsoft.CmdPal.Core.Common.Services.Sanitizer;
namespace Microsoft.CmdPal.Common.Services.Sanitizer;
internal sealed partial class ConnectionStringRuleProvider : ISanitizationRuleProvider
{

View File

@@ -3,9 +3,9 @@
// See the LICENSE file in the project root for more information.
using System.Text.RegularExpressions;
using Microsoft.CmdPal.Core.Common.Services.Sanitizer.Abstraction;
using Microsoft.CmdPal.Common.Services.Sanitizer.Abstraction;
namespace Microsoft.CmdPal.Core.Common.Services.Sanitizer;
namespace Microsoft.CmdPal.Common.Services.Sanitizer;
internal sealed class EnvironmentPropertiesRuleProvider : ISanitizationRuleProvider
{

View File

@@ -2,9 +2,9 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.CmdPal.Core.Common.Services.Sanitizer.Abstraction;
using Microsoft.CmdPal.Common.Services.Sanitizer.Abstraction;
namespace Microsoft.CmdPal.Core.Common.Services.Sanitizer;
namespace Microsoft.CmdPal.Common.Services.Sanitizer;
/// <summary>
/// Specific sanitizer used for error report content. Builds on top of the generic TextSanitizer.

View File

@@ -4,9 +4,9 @@
using System.Collections.Frozen;
using System.Text.RegularExpressions;
using Microsoft.CmdPal.Core.Common.Services.Sanitizer.Abstraction;
using Microsoft.CmdPal.Common.Services.Sanitizer.Abstraction;
namespace Microsoft.CmdPal.Core.Common.Services.Sanitizer;
namespace Microsoft.CmdPal.Common.Services.Sanitizer;
internal sealed class FilenameMaskRuleProvider : ISanitizationRuleProvider
{
@@ -25,6 +25,7 @@ internal sealed class FilenameMaskRuleProvider : ISanitizationRuleProvider
"env",
"environment",
"manifest",
"log",
}.ToFrozenSet(StringComparer.OrdinalIgnoreCase);
public IEnumerable<SanitizationRule> GetRules()
@@ -61,6 +62,11 @@ internal sealed class FilenameMaskRuleProvider : ISanitizationRuleProvider
return full;
}
if (IsVersionSegment(file))
{
return full;
}
string stem, ext;
if (dot > 0 && dot < file.Length - 1)
{
@@ -106,4 +112,30 @@ internal sealed class FilenameMaskRuleProvider : ISanitizationRuleProvider
var maskedCount = Math.Max(1, stem.Length - keep);
return stem[..keep] + new string('*', maskedCount);
}
private static bool IsVersionSegment(string file)
{
var dotIndex = file.IndexOf('.');
if (dotIndex <= 0 || dotIndex == file.Length - 1)
{
return false;
}
var hasDot = false;
foreach (var ch in file)
{
if (ch == '.')
{
hasDot = true;
continue;
}
if (!char.IsDigit(ch))
{
return false;
}
}
return hasDot;
}
}

View File

@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CmdPal.Core.Common.Services.Sanitizer;
namespace Microsoft.CmdPal.Common.Services.Sanitizer;
public record GuardrailEventArgs(
string RuleDescription,

View File

@@ -2,9 +2,9 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.CmdPal.Core.Common.Services.Sanitizer.Abstraction;
using Microsoft.CmdPal.Common.Services.Sanitizer.Abstraction;
namespace Microsoft.CmdPal.Core.Common.Services.Sanitizer;
namespace Microsoft.CmdPal.Common.Services.Sanitizer;
internal interface ISanitizationRuleProvider
{

View File

@@ -3,15 +3,17 @@
// See the LICENSE file in the project root for more information.
using System.Text.RegularExpressions;
using Microsoft.CmdPal.Core.Common.Services.Sanitizer.Abstraction;
using Microsoft.CmdPal.Common.Services.Sanitizer.Abstraction;
namespace Microsoft.CmdPal.Core.Common.Services.Sanitizer;
namespace Microsoft.CmdPal.Common.Services.Sanitizer;
internal sealed partial class NetworkRuleProvider : ISanitizationRuleProvider
{
public IEnumerable<SanitizationRule> GetRules()
{
yield return new(Ipv4Rx(), "[IP4_REDACTED]", "IP addresses");
// Disabled for now as these rules can be too aggressive and cause over-sanitization, especially in scenarios like
// error report sanitization where we want to preserve as much useful information as possible while still protecting sensitive data.
// yield return new(Ipv4Rx(), "[IP4_REDACTED]", "IP addresses");
yield return new(Ipv6BracketedRx(), "[IP6_REDACTED]", "IPv6 addresses (bracketed/with port)");
yield return new(Ipv6Rx(), "[IP6_REDACTED]", "IPv6 addresses");
yield return new(MacAddressRx(), "[MAC_ADDRESS_REDACTED]", "MAC addresses");

View File

@@ -0,0 +1,87 @@
// 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.RegularExpressions;
using Microsoft.CmdPal.Common.Services.Sanitizer.Abstraction;
namespace Microsoft.CmdPal.Common.Services.Sanitizer;
internal sealed partial class PiiRuleProvider : ISanitizationRuleProvider
{
public IEnumerable<SanitizationRule> GetRules()
{
yield return new(EmailRx(), "[EMAIL_REDACTED]", "Email addresses");
yield return new(SsnRx(), "[SSN_REDACTED]", "Social Security Numbers");
yield return new(CreditCardRx(), "[CARD_REDACTED]", "Credit card numbers");
// phone number regex is the most generic, so it goes last
// we can't make this too generic; otherwise we over-redact error codes, dates, etc.
yield return new(PhoneRx(), "[PHONE_REDACTED]", "Phone numbers");
}
[GeneratedRegex(@"\b[a-zA-Z0-9]([a-zA-Z0-9._%-]*[a-zA-Z0-9])?@[a-zA-Z0-9]([a-zA-Z0-9.-]*[a-zA-Z0-9])?\.[a-zA-Z]{2,}\b",
SanitizerDefaults.DefaultOptions, SanitizerDefaults.DefaultMatchTimeoutMs)]
private static partial Regex EmailRx();
[GeneratedRegex("""
(?xi)
# ---------- boundaries ----------
(?<!\w) # not after a letter/digit/underscore
(?<![A-Za-z0-9]-) # avoid starting inside hyphenated tokens (GUID middles, etc.)
# ---------- global do-not-match guards ----------
(?! # ISO date (yyyy-mm-dd / yyyy.mm.dd / yyyy/mm/dd)
(?:19|20)\d{2}[-./](?:0[1-9]|1[0-2])[-./](?:0[1-9]|[12]\d|3[01])\b
)
(?! # EU date (dd-mm-yyyy / dd.mm.yyyy / dd/mm/yyyy)
(?:0[1-9]|[12]\d|3[01])[-./](?:0[1-9]|1[0-2])[-./](?:19|20)\d{2}\b
)
(?! # ISO datetime like 2025-08-24T14:32[:ss][Z|±hh:mm]
(?:19|20)\d{2}-\d{2}-\d{2}[T\s]\d{2}:\d{2}(?::\d{2})?(?:Z|[+-]\d{2}:\d{2})?\b
)
(?!\b(?:\d{1,3}\.){3}\d{1,3}(?::\d{1,5})?\b) # IPv4 with optional :port
(?!\b[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}\b) # GUID, lowercase
(?!\b[0-9A-F]{8}-(?:[0-9A-F]{4}-){3}[0-9A-F]{12}\b) # GUID, uppercase
(?!\bv?\d+(?:\.\d+){2,}\b) # semantic/file versions like 1.2.3 or 10.0.22631.3448
(?!\b(?:[0-9A-F]{2}[:-]){5}[0-9A-F]{2}\b) # MAC address
# ---------- digit budget ----------
(?=(?:[^\r\n]*\d){7,15}[^\r\n]*(?:\r\n|$))
(?=(?:\D*\d){7,15}) # 715 digits in total
# ---------- number body ----------
(?:
# A with explicit country code, allow compact digits (E.164-ish) or grouped
(?:\+|00)[1-9]\d{0,2}
(?:
[\p{Zs}.\-\/]*\d{6,14}
|
[\p{Zs}.\-\/]* (?:\(\d{1,4}\)|\d{1,4})
(?:[\p{Zs}.\-\/]+(?:\(\d{2,4}\)|\d{2,4})){1,6}
)
|
# B no country code => require separators between blocks (avoid plain big ints)
(?:\(\d{1,4}\)|\d{1,4})
(?:[\p{Zs}.\-\/]+(?:\(\d{2,4}\)|\d{2,4})){1,6}
)
# ---------- optional extension ----------
(?:[\p{Zs}.\-,:;]* (?:ext\.?|x) [\p{Zs}]* (?<ext>\d{1,6}))?
# ---------- end boundary (allow whitespace/newlines at edges) ----------
(?!-\w) # don't end just before '-letter'/'-digit'
(?!\w) # don't be immediately followed by a word char
""",
SanitizerDefaults.DefaultOptions | RegexOptions.IgnorePatternWhitespace,
SanitizerDefaults.DefaultMatchTimeoutMs)]
private static partial Regex PhoneRx();
[GeneratedRegex(@"\b\d{3}-\d{2}-\d{4}\b",
SanitizerDefaults.DefaultOptions, SanitizerDefaults.DefaultMatchTimeoutMs)]
private static partial Regex SsnRx();
[GeneratedRegex(@"\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b",
SanitizerDefaults.DefaultOptions, SanitizerDefaults.DefaultMatchTimeoutMs)]
private static partial Regex CreditCardRx();
}

View File

@@ -4,9 +4,9 @@
using System.Collections.Frozen;
using System.Text.RegularExpressions;
using Microsoft.CmdPal.Core.Common.Services.Sanitizer.Abstraction;
using Microsoft.CmdPal.Common.Services.Sanitizer.Abstraction;
namespace Microsoft.CmdPal.Core.Common.Services.Sanitizer;
namespace Microsoft.CmdPal.Common.Services.Sanitizer;
internal sealed class ProfilePathAndUsernameRuleProvider : ISanitizationRuleProvider
{

View File

@@ -4,7 +4,7 @@
using System.Text.RegularExpressions;
namespace Microsoft.CmdPal.Core.Common.Services.Sanitizer;
namespace Microsoft.CmdPal.Common.Services.Sanitizer;
internal static class SanitizerDefaults
{

View File

@@ -4,9 +4,9 @@
using System.Collections.Frozen;
using System.Text.RegularExpressions;
using Microsoft.CmdPal.Core.Common.Services.Sanitizer.Abstraction;
using Microsoft.CmdPal.Common.Services.Sanitizer.Abstraction;
namespace Microsoft.CmdPal.Core.Common.Services.Sanitizer;
namespace Microsoft.CmdPal.Common.Services.Sanitizer;
internal sealed class SecretKeyValueRulesProvider : ISanitizationRuleProvider
{

View File

@@ -3,9 +3,9 @@
// See the LICENSE file in the project root for more information.
using System.Text.RegularExpressions;
using Microsoft.CmdPal.Core.Common.Services.Sanitizer.Abstraction;
using Microsoft.CmdPal.Common.Services.Sanitizer.Abstraction;
namespace Microsoft.CmdPal.Core.Common.Services.Sanitizer;
namespace Microsoft.CmdPal.Common.Services.Sanitizer;
/// <summary>
/// Generic text sanitizer that applies a sequence of regex-based rules over input text.

View File

@@ -3,9 +3,9 @@
// See the LICENSE file in the project root for more information.
using System.Text.RegularExpressions;
using Microsoft.CmdPal.Core.Common.Services.Sanitizer.Abstraction;
using Microsoft.CmdPal.Common.Services.Sanitizer.Abstraction;
namespace Microsoft.CmdPal.Core.Common.Services.Sanitizer;
namespace Microsoft.CmdPal.Common.Services.Sanitizer;
internal sealed partial class TokenRuleProvider : ISanitizationRuleProvider
{

View File

@@ -3,9 +3,9 @@
// See the LICENSE file in the project root for more information.
using System.Text.RegularExpressions;
using Microsoft.CmdPal.Core.Common.Services.Sanitizer.Abstraction;
using Microsoft.CmdPal.Common.Services.Sanitizer.Abstraction;
namespace Microsoft.CmdPal.Core.Common.Services.Sanitizer;
namespace Microsoft.CmdPal.Common.Services.Sanitizer;
internal sealed partial class UrlRuleProvider : ISanitizationRuleProvider
{

View File

@@ -4,7 +4,7 @@
using System.Runtime.CompilerServices;
namespace Microsoft.CmdPal.Core.Common.Text;
namespace Microsoft.CmdPal.Common.Text;
public sealed class BloomFilter : IBloomFilter
{

View File

@@ -4,7 +4,7 @@
using System.Globalization;
namespace Microsoft.CmdPal.Core.Common.Text;
namespace Microsoft.CmdPal.Common.Text;
public sealed class FuzzyMatcherProvider : IFuzzyMatcherProvider
{

View File

@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CmdPal.Core.Common.Text;
namespace Microsoft.CmdPal.Common.Text;
public readonly struct FuzzyQuery
{

View File

@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CmdPal.Core.Common.Text;
namespace Microsoft.CmdPal.Common.Text;
public readonly struct FuzzyTarget
{

View File

@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CmdPal.Core.Common.Text;
namespace Microsoft.CmdPal.Common.Text;
public struct FuzzyTargetCache
{

View File

@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CmdPal.Core.Common.Text;
namespace Microsoft.CmdPal.Common.Text;
public interface IBloomFilter
{

View File

@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CmdPal.Core.Common.Text;
namespace Microsoft.CmdPal.Common.Text;
public interface IFuzzyMatcherProvider
{

View File

@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CmdPal.Core.Common.Text;
namespace Microsoft.CmdPal.Common.Text;
public interface IPrecomputedFuzzyMatcher
{

View File

@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CmdPal.Core.Common.Text;
namespace Microsoft.CmdPal.Common.Text;
public interface IStringFolder
{

View File

@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CmdPal.Core.Common.Text;
namespace Microsoft.CmdPal.Common.Text;
public sealed class PinyinFuzzyMatcherOptions
{

View File

@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CmdPal.Core.Common.Text;
namespace Microsoft.CmdPal.Common.Text;
public enum PinyinMode
{

View File

@@ -7,7 +7,7 @@ using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Microsoft.CmdPal.Core.Common.Text;
namespace Microsoft.CmdPal.Common.Text;
public sealed class PrecomputedFuzzyMatcher : IPrecomputedFuzzyMatcher
{

View File

@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CmdPal.Core.Common.Text;
namespace Microsoft.CmdPal.Common.Text;
public sealed class PrecomputedFuzzyMatcherOptions
{

View File

@@ -6,7 +6,7 @@ using System.Globalization;
using System.Runtime.CompilerServices;
using ToolGood.Words.Pinyin;
namespace Microsoft.CmdPal.Core.Common.Text;
namespace Microsoft.CmdPal.Common.Text;
public sealed class PrecomputedFuzzyMatcherWithPinyin : IPrecomputedFuzzyMatcher
{

View File

@@ -6,7 +6,7 @@ using System.Globalization;
using System.Runtime.CompilerServices;
using System.Text;
namespace Microsoft.CmdPal.Core.Common.Text;
namespace Microsoft.CmdPal.Common.Text;
public sealed class StringFolder : IStringFolder
{

View File

@@ -4,7 +4,7 @@
using System.Runtime.CompilerServices;
namespace Microsoft.CmdPal.Core.Common.Text;
namespace Microsoft.CmdPal.Common.Text;
internal static class SymbolClassifier
{

View File

@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CmdPal.Core.Common.Text;
namespace Microsoft.CmdPal.Common.Text;
internal enum SymbolKind : byte
{

View File

@@ -4,7 +4,7 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CmdPal.ViewModels.Messages;
namespace Microsoft.CmdPal.UI.ViewModels;

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