mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-01-01 18:06:25 +01:00
Compare commits
84 Commits
dev/FHL/ch
...
yuleng/cmd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53eb4b8592 | ||
|
|
721c84d3a6 | ||
|
|
96ba445cfa | ||
|
|
16157231d4 | ||
|
|
a641b46f57 | ||
|
|
51e9e9d46a | ||
|
|
5157ffc895 | ||
|
|
60bbf070e1 | ||
|
|
d597bd267d | ||
|
|
2623eb10f3 | ||
|
|
8e27940b77 | ||
|
|
c6750d3a62 | ||
|
|
37836c656d | ||
|
|
39e8231831 | ||
|
|
2cb63f5fbe | ||
|
|
e931135d50 | ||
|
|
5b39d1551d | ||
|
|
5e88d47f3d | ||
|
|
aeec3a967f | ||
|
|
be1968aaa5 | ||
|
|
33cc612e40 | ||
|
|
a9a41ca1a2 | ||
|
|
4e7bd34c4d | ||
|
|
43783d2cff | ||
|
|
79bd825f91 | ||
|
|
69c2e9c568 | ||
|
|
df3e3414d2 | ||
|
|
7368458a72 | ||
|
|
4d7691a56f | ||
|
|
2f9fea2287 | ||
|
|
29551898ca | ||
|
|
048b07c1ce | ||
|
|
7575c040f8 | ||
|
|
e52dd68fe4 | ||
|
|
3e9a6a1e64 | ||
|
|
14919dff10 | ||
|
|
57cbcc2c3e | ||
|
|
5d03667bcf | ||
|
|
2b4d13ccb9 | ||
|
|
665e957cde | ||
|
|
dadd306555 | ||
|
|
68f76409ab | ||
|
|
bf877c4e40 | ||
|
|
53003b9969 | ||
|
|
394583fca9 | ||
|
|
20cd0ec7f4 | ||
|
|
dfb727f9a3 | ||
|
|
a13abc3803 | ||
|
|
f68f408be3 | ||
|
|
a62acf7a71 | ||
|
|
648c3eb0bf | ||
|
|
f6b53d1088 | ||
|
|
8862b22c45 | ||
|
|
4377de260f | ||
|
|
1f81d14000 | ||
|
|
1d358af600 | ||
|
|
18a1107ec4 | ||
|
|
8e90d8e4c5 | ||
|
|
abd6314b2e | ||
|
|
a298f67b81 | ||
|
|
c89280cd9e | ||
|
|
0e62e2ddd4 | ||
|
|
7bdd6c660a | ||
|
|
53f8499434 | ||
|
|
39073f0467 | ||
|
|
924898ae94 | ||
|
|
a00f56e317 | ||
|
|
2b7307d32e | ||
|
|
92fb931e1e | ||
|
|
82bc3b7c85 | ||
|
|
ccb77ff601 | ||
|
|
bbc8beb006 | ||
|
|
3b05cf127a | ||
|
|
8494858314 | ||
|
|
04c80c40a2 | ||
|
|
42edf9da97 | ||
|
|
c38faa959a | ||
|
|
fc94cd758e | ||
|
|
61a00aa669 | ||
|
|
cca3f442e2 | ||
|
|
22e29d1253 | ||
|
|
8a2d4745fa | ||
|
|
bf2685757a | ||
|
|
b8cef42776 |
@@ -3,13 +3,13 @@
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"dotnet-consolidate": {
|
||||
"version": "2.0.0",
|
||||
"version": "4.2.0",
|
||||
"commands": [
|
||||
"dotnet-consolidate"
|
||||
]
|
||||
},
|
||||
"xamlstyler.console": {
|
||||
"version": "3.2404.2",
|
||||
"version": "3.2501.8",
|
||||
"commands": [
|
||||
"xstyler"
|
||||
]
|
||||
|
||||
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -53,6 +53,7 @@ body:
|
||||
- Awake
|
||||
- ColorPicker
|
||||
- Command not found
|
||||
- Command Palette
|
||||
- Crop and Lock
|
||||
- Environment Variables
|
||||
- FancyZones
|
||||
|
||||
4
.github/actions/spell-check/allow/code.txt
vendored
4
.github/actions/spell-check/allow/code.txt
vendored
@@ -89,6 +89,7 @@ onefuzzingestionpreparationtool
|
||||
OTP
|
||||
Yubi
|
||||
Yubico
|
||||
svgl
|
||||
|
||||
# KEYS
|
||||
|
||||
@@ -232,6 +233,9 @@ SWAPBUTTON
|
||||
SYSTEMDOCKED
|
||||
TABLETPC
|
||||
|
||||
# Units
|
||||
nmi
|
||||
|
||||
# MATH
|
||||
|
||||
artanh
|
||||
|
||||
7
.github/actions/spell-check/allow/names.txt
vendored
7
.github/actions/spell-check/allow/names.txt
vendored
@@ -79,6 +79,7 @@ Gershaft
|
||||
Giordani
|
||||
Gokce
|
||||
gordon
|
||||
Griese
|
||||
grzhan
|
||||
Guo
|
||||
hanselman
|
||||
@@ -153,6 +154,7 @@ Santossio
|
||||
Schoen
|
||||
Sekan
|
||||
Seraphima
|
||||
Shmuelie
|
||||
skttl
|
||||
somil
|
||||
Soref
|
||||
@@ -184,6 +186,7 @@ zhaopy
|
||||
zhaoqpcn
|
||||
Zoltan
|
||||
Zykova
|
||||
Sameerjs
|
||||
|
||||
# OTHERS
|
||||
|
||||
@@ -196,6 +199,7 @@ cortana
|
||||
dlnilsson
|
||||
fancymouse
|
||||
firefox
|
||||
fudan
|
||||
gpt
|
||||
Inkscape
|
||||
Markdig
|
||||
@@ -211,6 +215,7 @@ regedit
|
||||
roslyn
|
||||
Spotify
|
||||
Vanara
|
||||
wangyi
|
||||
WEX
|
||||
windowwalker
|
||||
winui
|
||||
@@ -218,7 +223,9 @@ winuiex
|
||||
wix
|
||||
wordpad
|
||||
WWL
|
||||
wyhash
|
||||
xamlstyler
|
||||
Xavalon
|
||||
Xbox
|
||||
Youdao
|
||||
zadjii
|
||||
|
||||
3
.github/actions/spell-check/excludes.txt
vendored
3
.github/actions/spell-check/excludes.txt
vendored
@@ -96,10 +96,11 @@
|
||||
^\Qdoc/devdocs/localization.md\E$
|
||||
^\Qsrc/common/ManagedCommon/ColorFormatHelper.cs\E$
|
||||
^\Qsrc/common/notifications/BackgroundActivatorDLL/cpp.hint\E$
|
||||
^\Qsrc/modules/cmdpal/doc/initial-sdk-spec/list-elements-mock-002.pdn\E$
|
||||
^\Qsrc/modules/colorPicker/ColorPickerUI/Assets/ColorPicker/colorPicker.cur\E$
|
||||
^\Qsrc/modules/colorPicker/ColorPickerUI/Shaders/GridShader.cso\E$
|
||||
^\Qsrc/modules/MouseUtils/MouseJumpUI/MainForm.resx\E$
|
||||
^\Qsrc/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.SYSTEM_METRICS_INDEX.cs\E$
|
||||
^\Qsrc/modules/MouseUtils/MouseJumpUI/MainForm.resx\E$
|
||||
^\Qsrc/modules/MouseWithoutBorders/App/Form/frmAbout.cs\E$
|
||||
^\Qsrc/modules/MouseWithoutBorders/App/Form/frmInputCallback.resx\E$
|
||||
^\Qsrc/modules/MouseWithoutBorders/App/Form/frmLogon.resx\E$
|
||||
|
||||
243
.github/actions/spell-check/expect.txt
vendored
243
.github/actions/spell-check/expect.txt
vendored
File diff suppressed because it is too large
Load Diff
11
.github/actions/spell-check/patterns.txt
vendored
11
.github/actions/spell-check/patterns.txt
vendored
@@ -232,6 +232,15 @@ _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING
|
||||
# ignore long runs of a single character:
|
||||
\b([A-Za-z])\g{-1}{3,}\b
|
||||
|
||||
# Amazon
|
||||
\bamazon\.com/[-\w]+/(?:dp/[0-9A-Z]+|)
|
||||
|
||||
# imgur
|
||||
\bimgur\.com/[^.]+
|
||||
|
||||
# Process Process (typename varname)
|
||||
Process Process
|
||||
|
||||
# ZoomIt menu items with accelerator keys
|
||||
E&xit
|
||||
St&yle
|
||||
St&yle
|
||||
5
.github/workflows/msstore-submissions.yml
vendored
5
.github/workflows/msstore-submissions.yml
vendored
@@ -39,6 +39,11 @@ jobs:
|
||||
echo powerToysInstallerX64Url=$(jq -n "$powerToysSetup" | jq -r '[.[]|select(.name | contains("x64"))][0].browser_download_url') >> $GITHUB_OUTPUT
|
||||
echo powerToysInstallerArm64Url=$(jq -n "$powerToysSetup" | jq -r '[.[]|select(.name | contains("arm64"))][0].browser_download_url') >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Setup .NET 9.0
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '9.0.x'
|
||||
|
||||
- uses: microsoft/setup-msstore-cli@v1
|
||||
|
||||
- name: Fetch Store Credential
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -224,7 +224,7 @@ ClientBin/
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
@@ -322,7 +322,7 @@ ImageResizer/tools/**
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
@@ -331,7 +331,7 @@ ASALocalRun/
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Temp build files
|
||||
|
||||
51
.pipelines/ESRPSigning_cmdpal_msix_content.json
Normal file
51
.pipelines/ESRPSigning_cmdpal_msix_content.json
Normal file
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"Version": "1.0.0",
|
||||
"UseMinimatch": false,
|
||||
"SignBatches": [
|
||||
{
|
||||
"MatchedPath": [
|
||||
"*.dll",
|
||||
"*.exe"
|
||||
],
|
||||
"SigningInfo": {
|
||||
"Operations": [
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationSetCode": "SigntoolSign",
|
||||
"Parameters": [
|
||||
{
|
||||
"parameterName": "OpusName",
|
||||
"parameterValue": "Microsoft"
|
||||
},
|
||||
{
|
||||
"parameterName": "OpusInfo",
|
||||
"parameterValue": "http://www.microsoft.com"
|
||||
},
|
||||
{
|
||||
"parameterName": "FileDigest",
|
||||
"parameterValue": "/fd \"SHA256\""
|
||||
},
|
||||
{
|
||||
"parameterName": "PageHash",
|
||||
"parameterValue": "/NPH"
|
||||
},
|
||||
{
|
||||
"parameterName": "TimeStamp",
|
||||
"parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
|
||||
}
|
||||
],
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationSetCode": "SigntoolVerify",
|
||||
"Parameters": [],
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -217,7 +217,10 @@
|
||||
"PowerToys.ZoomItSettingsInterop.dll",
|
||||
|
||||
"WinUI3Apps\\PowerToys.Settings.dll",
|
||||
"WinUI3Apps\\PowerToys.Settings.exe"
|
||||
"WinUI3Apps\\PowerToys.Settings.exe",
|
||||
|
||||
"PowerToys.CmdPalModuleInterface.dll",
|
||||
"*Microsoft.CmdPal.UI_*.msix"
|
||||
],
|
||||
"SigningInfo": {
|
||||
"Operations": [
|
||||
|
||||
51
.pipelines/ESRPSigning_sdk.json
Normal file
51
.pipelines/ESRPSigning_sdk.json
Normal file
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"Version": "1.0.0",
|
||||
"UseMinimatch": false,
|
||||
"SignBatches": [
|
||||
{
|
||||
"MatchedPath": [
|
||||
"Microsoft.CommandPalette.Extensions.dll",
|
||||
"Microsoft.CommandPalette.Extensions.Toolkit.dll"
|
||||
],
|
||||
"SigningInfo": {
|
||||
"Operations": [
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationSetCode": "SigntoolSign",
|
||||
"Parameters": [
|
||||
{
|
||||
"parameterName": "OpusName",
|
||||
"parameterValue": "Microsoft"
|
||||
},
|
||||
{
|
||||
"parameterName": "OpusInfo",
|
||||
"parameterValue": "http://www.microsoft.com"
|
||||
},
|
||||
{
|
||||
"parameterName": "FileDigest",
|
||||
"parameterValue": "/fd \"SHA256\""
|
||||
},
|
||||
{
|
||||
"parameterName": "PageHash",
|
||||
"parameterValue": "/NPH"
|
||||
},
|
||||
{
|
||||
"parameterName": "TimeStamp",
|
||||
"parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
|
||||
}
|
||||
],
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationSetCode": "SigntoolVerify",
|
||||
"Parameters": [],
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -20,6 +20,16 @@ parameters:
|
||||
type: string
|
||||
default: '0.0.1'
|
||||
|
||||
- name: cmdPalVersionNumber
|
||||
displayName: "Command Palette Version Number"
|
||||
type: string
|
||||
default: '0.0.1'
|
||||
|
||||
- name: cmdPalSdkVersionNumber
|
||||
displayName: "Command Palette SDK Version Number"
|
||||
type: string
|
||||
default: '0.0.1'
|
||||
|
||||
- name: buildConfigurations
|
||||
displayName: "Build Configurations"
|
||||
type: object
|
||||
@@ -78,6 +88,7 @@ extends:
|
||||
buildPlatforms: ${{ parameters.buildPlatforms }}
|
||||
buildConfigurations: ${{ parameters.buildConfigurations }}
|
||||
versionNumber: ${{ parameters.versionNumber }}
|
||||
cmdPalVersionNumber: ${{ parameters.cmdPalVersionNumber }}
|
||||
publishArtifacts: false # 1ES PT handles publication for us.
|
||||
codeSign: true
|
||||
runTests: false
|
||||
@@ -95,7 +106,7 @@ extends:
|
||||
beforeBuildSteps:
|
||||
# Sets versions for all PowerToy created DLLs
|
||||
- pwsh: |-
|
||||
.pipelines/versionSetting.ps1 -versionNumber '${{ parameters.versionNumber }}' -DevEnvironment ''
|
||||
.pipelines/versionSetting.ps1 -versionNumber '${{ parameters.versionNumber }}' -DevEnvironment '' -cmdPalVersionNumber '${{ parameters.cmdPalVersionNumber }}'
|
||||
displayName: Prepare versioning
|
||||
|
||||
# Prepare the localizations and telemetry config before the release build
|
||||
@@ -107,6 +118,28 @@ extends:
|
||||
move /Y "Microsoft.PowerToys.Telemetry.2.0.2\build\include\TelemetryBase.cs" "src\common\Telemetry\TelemetryBase.cs" || exit /b 1
|
||||
displayName: Emplace telemetry files
|
||||
|
||||
- stage: Build_SDK
|
||||
displayName: Build SDK
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: .pipelines/v2/templates/job-build-sdk.yml@self
|
||||
parameters:
|
||||
pool:
|
||||
name: SHINE-INT-L
|
||||
image: SHINE-VS17-Latest
|
||||
os: windows
|
||||
codeSign: true
|
||||
sdkVersionNumber: ${{ parameters.cmdPalSdkVersionNumber }}
|
||||
signingIdentity:
|
||||
serviceName: $(SigningServiceName)
|
||||
appId: $(SigningAppId)
|
||||
tenantId: $(SigningTenantId)
|
||||
akvName: $(SigningAKVName)
|
||||
authCertName: $(SigningAuthCertName)
|
||||
signCertName: $(SigningSignCertName)
|
||||
useManagedIdentity: $(SigningUseManagedIdentity)
|
||||
clientId: $(SigningOriginalClientId)
|
||||
|
||||
- stage: Publish
|
||||
displayName: Publish
|
||||
dependsOn: [Build]
|
||||
|
||||
@@ -56,6 +56,9 @@ parameters:
|
||||
- name: versionNumber
|
||||
type: string
|
||||
default: '0.0.1'
|
||||
- name: cmdPalVersionNumber
|
||||
type: string
|
||||
default: '0.0.1'
|
||||
- name: useLatestWinAppSDK
|
||||
type: boolean
|
||||
default: false
|
||||
@@ -96,6 +99,7 @@ jobs:
|
||||
${{ else }}:
|
||||
OutputBuildPlatform: ${{ platform }}
|
||||
variables:
|
||||
MakeAppxPath: 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x86\MakeAppx.exe'
|
||||
# Azure DevOps abhors a vacuum
|
||||
# If these are blank, expansion will fail later on... which will result in direct substitution of the variable *names*
|
||||
# later on. We'll just... set them to a single space and if we need to, check IsNullOrWhiteSpace.
|
||||
@@ -145,7 +149,7 @@ jobs:
|
||||
- template: steps-ensure-dotnet-version.yml
|
||||
parameters:
|
||||
sdk: true
|
||||
version: '6.0'
|
||||
version: '6.0' # .NET 6.0 is required in CI for ESRP code signing tasks. Please do not remove.
|
||||
|
||||
- template: steps-ensure-dotnet-version.yml
|
||||
parameters:
|
||||
@@ -242,6 +246,32 @@ jobs:
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: Stage SDK/build
|
||||
inputs:
|
||||
contents: |-
|
||||
"**/cmdpal/extensionsdk/nuget/Microsoft.CommandPalette.Extensions.SDK.props"
|
||||
"**/cmdpal/extensionsdk/nuget/Microsoft.CommandPalette.Extensions.SDK.targets"
|
||||
flattenFolders: True
|
||||
targetFolder: $(JobOutputDirectory)/sdk/build
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: Stage SDK/lib
|
||||
inputs:
|
||||
contents: |-
|
||||
"**/Microsoft.CommandPalette.Extensions.Toolkit/$(BuildPlatform)/release/WinUI3Apps/CmdPal/Microsoft.CommandPalette.Extensions.Toolkit.dll"
|
||||
"**/Microsoft.CommandPalette.Extensions.Toolkit/$(BuildPlatform)/release/WinUI3Apps/CmdPal/Microsoft.CommandPalette.Extensions.Toolkit.deps.json"
|
||||
flattenFolders: True
|
||||
targetFolder: $(JobOutputDirectory)/sdk/lib/net8.0-windows10.0.19041.0
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: Stage SDK/winmd
|
||||
inputs:
|
||||
contents: |-
|
||||
"**/Microsoft.CommandPalette.Extensions/$(BuildPlatform)/release/Microsoft.CommandPalette.Extensions/Microsoft.CommandPalette.Extensions.winmd"
|
||||
flattenFolders: True
|
||||
targetFolder: $(JobOutputDirectory)/sdk/winmd
|
||||
|
||||
- task: VSBuild@1
|
||||
displayName: Build BugReportTool
|
||||
inputs:
|
||||
@@ -309,7 +339,7 @@ jobs:
|
||||
displayName: HACK Copy core WebView2 ARM64 dll to output directory
|
||||
condition: eq(variables['BuildPlatform'],'arm64')
|
||||
inputs:
|
||||
contents: packages/Microsoft.Web.WebView2.1.0.2739.15/runtimes/win-ARM64/native_uap/Microsoft.Web.WebView2.Core.dll
|
||||
contents: packages/Microsoft.Web.WebView2.1.0.2903.40/runtimes/win-ARM64/native_uap/Microsoft.Web.WebView2.Core.dll
|
||||
targetFolder: $(Build.SourcesDirectory)/ARM64/Release/WinUI3Apps/
|
||||
flattenFolders: True
|
||||
OverWrite: True
|
||||
@@ -360,6 +390,33 @@ jobs:
|
||||
!**\obj\**
|
||||
|
||||
- ${{ if eq(parameters.codeSign, true) }}:
|
||||
- pwsh: |-
|
||||
$Package = (Get-ChildItem -Recurse -Filter "Microsoft.CmdPal.UI_*.msix" | Select -First 1)
|
||||
$PackageFilename = $Package.FullName
|
||||
Write-Host "##vso[task.setvariable variable=CmdPalPackagePath]${PackageFilename}"
|
||||
displayName: Locate the MSIX
|
||||
|
||||
- pwsh: |-
|
||||
& "$(MakeAppxPath)" unpack /p "$(CmdPalPackagePath)" /d "$(JobOutputDirectory)/CmdPalPackageContents"
|
||||
displayName: Unpack the MSIX for signing
|
||||
|
||||
- template: steps-esrp-signing.yml
|
||||
parameters:
|
||||
displayName: Sign CmdPal MSIX content
|
||||
signingIdentity: ${{ parameters.signingIdentity }}
|
||||
inputs:
|
||||
FolderPath: '$(JobOutputDirectory)/CmdPalPackageContents'
|
||||
signType: batchSigning
|
||||
batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_cmdpal_msix_content.json'
|
||||
ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml'
|
||||
|
||||
- pwsh: |-
|
||||
$outDir = New-Item -Type Directory "$(JobOutputDirectory)/_appx" -ErrorAction:Ignore
|
||||
$PackageFilename = Join-Path $outDir.FullName (Split-Path -Leaf "$(CmdPalPackagePath)")
|
||||
& "$(MakeAppxPath)" pack /h SHA256 /o /p $PackageFilename /d "$(JobOutputDirectory)/CmdPalPackageContents"
|
||||
Copy-Item -Force $PackageFilename "$(CmdPalPackagePath)"
|
||||
displayName: Re-pack the new CmdPal package after signing
|
||||
|
||||
- template: steps-esrp-signing.yml
|
||||
parameters:
|
||||
displayName: Sign Core PowerToys
|
||||
@@ -435,7 +492,7 @@ jobs:
|
||||
$machinePlat = "hash_machine_$(BuildPlatform).txt";
|
||||
$combinedUserPath = $p + $userPlat;
|
||||
$combinedMachinePath = $p + $machinePlat;
|
||||
|
||||
|
||||
echo $p
|
||||
|
||||
echo $userPlat
|
||||
@@ -445,7 +502,7 @@ jobs:
|
||||
echo $machinePlat
|
||||
echo $machineHash
|
||||
echo $combinedMachinePath
|
||||
|
||||
|
||||
$userHash | out-file -filepath $combinedUserPath
|
||||
$machineHash | out-file -filepath $combinedMachinePath
|
||||
displayName: Calculate file hashes
|
||||
|
||||
91
.pipelines/v2/templates/job-build-sdk.yml
Normal file
91
.pipelines/v2/templates/job-build-sdk.yml
Normal file
@@ -0,0 +1,91 @@
|
||||
parameters:
|
||||
- name: buildConfigurations
|
||||
type: object
|
||||
default:
|
||||
- Release
|
||||
- name: codeSign
|
||||
type: boolean
|
||||
default: false
|
||||
- name: pool
|
||||
type: object
|
||||
default: []
|
||||
- name: signingIdentity
|
||||
type: object
|
||||
default: {}
|
||||
- name: sdkVersionNumber
|
||||
type: string
|
||||
default: '0.0.1'
|
||||
|
||||
jobs:
|
||||
- job: "BuildSDK"
|
||||
${{ if ne(length(parameters.pool), 0) }}:
|
||||
pool: ${{ parameters.pool }}
|
||||
displayName: Build SDK
|
||||
timeoutInMinutes: 240
|
||||
cancelTimeoutInMinutes: 1
|
||||
templateContext: # Required when this template is hosted in 1ES PT
|
||||
outputs:
|
||||
- output: pipelineArtifact
|
||||
artifactName: SDK
|
||||
targetPath: $(Build.ArtifactStagingDirectory)
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
submodules: true
|
||||
persistCredentials: True
|
||||
fetchTags: false
|
||||
fetchDepth: 1
|
||||
|
||||
- pwsh: |-
|
||||
& "$(build.sourcesdirectory)\src\modules\cmdpal\extensionsdk\nuget\BuildSDKHelper.ps1" -Configuration "Release" -VersionOfSDK ${{ parameters.sdkVersionNumber }} -BuildStep "build" -IsAzurePipelineBuild
|
||||
displayName: Build SDK
|
||||
|
||||
- ${{ if eq(parameters.codeSign, true) }}:
|
||||
- template: steps-esrp-signing.yml
|
||||
parameters:
|
||||
displayName: Sign SDK
|
||||
signingIdentity: ${{ parameters.signingIdentity }}
|
||||
inputs:
|
||||
FolderPath: 'src/modules'
|
||||
signType: batchSigning
|
||||
batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_sdk.json'
|
||||
ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml'
|
||||
|
||||
- pwsh: |-
|
||||
& "$(build.sourcesdirectory)\src\modules\cmdpal\extensionsdk\nuget\BuildSDKHelper.ps1" -Configuration "Release" -VersionOfSDK ${{ parameters.sdkVersionNumber }} -BuildStep "pack" -IsAzurePipelineBuild
|
||||
displayName: Pack SDK
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: Copy Nuget to Artifact Staging
|
||||
inputs:
|
||||
sourceFolder: "$(build.sourcesdirectory)/src/modules/cmdpal/extensionsdk/_build"
|
||||
contents: '*.nupkg'
|
||||
targetFolder: '$(Build.ArtifactStagingDirectory)'
|
||||
|
||||
- ${{ if eq(parameters.codeSign, true) }}:
|
||||
- template: steps-esrp-signing.yml
|
||||
parameters:
|
||||
displayName: Sign NuGet packages
|
||||
signingIdentity: ${{ parameters.signingIdentity }}
|
||||
inputs:
|
||||
FolderPath: $(Build.ArtifactStagingDirectory)
|
||||
Pattern: '*.nupkg'
|
||||
UseMinimatch: true
|
||||
signConfigType: inlineSignParams
|
||||
inlineOperation: >-
|
||||
[
|
||||
{
|
||||
"KeyCode": "CP-401405",
|
||||
"OperationCode": "NuGetSign",
|
||||
"Parameters": {},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "CP-401405",
|
||||
"OperationCode": "NuGetVerify",
|
||||
"Parameters": {},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
@@ -1,30 +0,0 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/microsoft/azure-pipelines-vscode/master/service-schema.json
|
||||
jobs:
|
||||
- job: Precheck
|
||||
pool:
|
||||
vmImage: windows-2022
|
||||
steps:
|
||||
- checkout: none
|
||||
|
||||
- pwsh: |-
|
||||
try {
|
||||
# Try based on pull request first
|
||||
$pullRequestNumber = "$(system.pullRequest.pullRequestNumber)";
|
||||
$gitHubPullRequest = Invoke-RestMethod -Method Get "https://api.github.com/repos/microsoft/PowerToys/pulls/$pullRequestNumber/files"
|
||||
# If there are no files updated in the commit that are .md, set skipBuild variable
|
||||
if(([array]($gitHubPullRequest.filename) -notmatch ".md|.txt").Length -eq 0) {
|
||||
Write-Host '##vso[task.setvariable variable=skipBuild;isOutput=true]Yes'
|
||||
Write-Host 'Skipping Build'
|
||||
}
|
||||
}
|
||||
catch {
|
||||
# Fall back to the latest commit otherwise.
|
||||
$commit = "$(build.sourceVersion)";
|
||||
$gitHubCommit = Invoke-RestMethod -Method Get "https://api.github.com/repos/microsoft/PowerToys/commits/$commit"
|
||||
if(([array]($githubCommit.files.filename) -notmatch ".md|.txt").Length -eq 0) {
|
||||
Write-Host '##vso[task.setvariable variable=skipBuild;isOutput=true]Yes'
|
||||
Write-Host 'Skipping Build'
|
||||
}
|
||||
}
|
||||
displayName: Verify whether we need to build at all
|
||||
name: verifyBuildRequest
|
||||
@@ -61,9 +61,18 @@ jobs:
|
||||
reg add "HKLM\Software\Policies\Microsoft\Edge\WebView2\ReleaseChannels" /v PowerToys.exe /t REG_SZ /d "3"
|
||||
displayName: "Enable WebView2 Canary Channel"
|
||||
|
||||
- template: steps-download-artifacts-with-azure-cli.yml
|
||||
parameters:
|
||||
artifactName: $(TestArtifactsName)
|
||||
- ${{ if ne(parameters.platform, 'arm64') }}:
|
||||
- download: current
|
||||
displayName: Download artifacts
|
||||
artifact: $(TestArtifactsName)
|
||||
patterns: |-
|
||||
**
|
||||
!**\*.pdb
|
||||
!**\*.lib
|
||||
- ${{ else }}:
|
||||
- template: steps-download-artifacts-with-azure-cli.yml
|
||||
parameters:
|
||||
artifactName: $(TestArtifactsName)
|
||||
|
||||
- template: steps-ensure-dotnet-version.yml
|
||||
parameters:
|
||||
@@ -96,4 +105,4 @@ jobs:
|
||||
**\UITests-FancyZones.dll
|
||||
**\UITests-FancyZonesEditor.dll
|
||||
!**\obj\**
|
||||
!**\ref\**
|
||||
!**\ref\**
|
||||
@@ -36,20 +36,10 @@ parameters:
|
||||
default: false
|
||||
|
||||
stages:
|
||||
# Allow manual builds to skip pre-check
|
||||
- ${{ if ne(variables['Build.Reason'], 'Manual') }}:
|
||||
- stage: Precheck
|
||||
jobs:
|
||||
- template: job-ci-precheck.yml
|
||||
|
||||
- ${{ each platform in parameters.buildPlatforms }}:
|
||||
- stage: Build_${{ platform }}
|
||||
displayName: Build ${{ platform }}
|
||||
${{ if ne(variables['Build.Reason'], 'Manual') }}:
|
||||
dependsOn: [Precheck]
|
||||
condition: and(succeeded(), ne(dependencies.Precheck.outputs['Precheck.verifyBuildRequest.skipBuild'], 'Yes'))
|
||||
${{ else }}:
|
||||
dependsOn: []
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: job-build-project.yml
|
||||
parameters:
|
||||
@@ -72,7 +62,7 @@ stages:
|
||||
winAppSDKVersionNumber: ${{ parameters.winAppSDKVersionNumber }}
|
||||
useExperimentalVersion: ${{ parameters.useExperimentalVersion }}
|
||||
|
||||
- ${{ if eq(parameters.runTests, true) }}:
|
||||
- ${{ if and(eq(parameters.runTests, true), not(and(eq(platform, 'arm64'), eq(variables['System.PullRequest.IsFork'], true)))) }}:
|
||||
- stage: Test_${{ platform }}
|
||||
displayName: Test ${{ platform }}
|
||||
dependsOn:
|
||||
|
||||
@@ -87,6 +87,30 @@ steps:
|
||||
dir $(build.sourcesdirectory)\extractedMsi
|
||||
displayName: "${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Extract and verify MSI"
|
||||
|
||||
# Extract CmdPal msix package to check if its content is signed
|
||||
- pwsh: |-
|
||||
Write-Host "Extracting CmdPal MSIX package"
|
||||
|
||||
# Define the directory to search
|
||||
$searchDir = "extractedMsi\File"
|
||||
|
||||
# Define the regex pattern for MSIX files
|
||||
$pattern = '^Microsoft.CmdPal.UI.*\.msix$'
|
||||
|
||||
# Get all files in the directory and subdirectories
|
||||
$msixFile = Get-ChildItem -Path $searchDir -Recurse -File | Where-Object {
|
||||
$_.Name -match $pattern
|
||||
}
|
||||
|
||||
Write-Host "MSIX file found: " $msixFile
|
||||
|
||||
$destinationDir = "$(build.sourcesdirectory)\extractedMsi\File\extractedCmdPalMsix"
|
||||
|
||||
Expand-Archive -Path $msixFile -DestinationPath $destinationDir
|
||||
Get-ChildItem -Path $destinationDir -Recurse -File
|
||||
|
||||
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Extract CmdPal MSIX package
|
||||
|
||||
# Check if deps.json files don't reference different dll versions.
|
||||
- pwsh: |-
|
||||
& '.pipelines/verifyDepsJsonLibraryVersions.ps1' -targetDir '$(build.sourcesdirectory)\extractedMsi\File'
|
||||
|
||||
@@ -18,6 +18,11 @@ $totalFailures = 0
|
||||
Get-ChildItem $targetDir -Recurse -Filter *.deps.json -Exclude *UITest*,MouseJump.Common.UnitTests*,*.FuzzTests* | ForEach-Object {
|
||||
# Temporarily exclude All UI-Test, Fuzzer-Test projects because of Appium.WebDriver dependencies
|
||||
$depsJsonFullFileName = $_.FullName
|
||||
|
||||
if ($depsJsonFullFileName -like "*CmdPal*") {
|
||||
return
|
||||
}
|
||||
|
||||
$depsJsonFileName = $_.Name
|
||||
$depsJson = Get-Content $depsJsonFullFileName | ConvertFrom-Json
|
||||
|
||||
|
||||
@@ -22,7 +22,11 @@ $versionExceptions = @(
|
||||
"TraceReloggerLib.dll",
|
||||
"Microsoft.WindowsAppRuntime.Release.Net.dll",
|
||||
"Microsoft.Windows.Widgets.Projection.dll",
|
||||
"WinRT.Host.Shim.dll") -join '|';
|
||||
"WinRT.Host.Shim.dll",
|
||||
"WyHash.dll",
|
||||
"Microsoft.Recognizers.Text.DataTypes.TimexExpression.dll",
|
||||
"ObjectModelCsProjection.dll",
|
||||
"RendererCsProjection.dll") -join '|';
|
||||
$nullVersionExceptions = @(
|
||||
"codicon.ttf",
|
||||
"e_sqlite3.dll",
|
||||
@@ -43,12 +47,14 @@ $nullVersionExceptions = @(
|
||||
"PushNotificationsLongRunningTask.ProxyStub.dll",
|
||||
"WindowsAppSdk.AppxDeploymentExtensions.Desktop.dll",
|
||||
"System.Diagnostics.EventLog.Messages.dll",
|
||||
"Microsoft.Windows.Widgets.dll") -join '|';
|
||||
"Microsoft.Windows.Widgets.dll",
|
||||
"AdaptiveCards.ObjectModel.WinUI3.dll",
|
||||
"AdaptiveCards.Rendering.WinUI3.dll") -join '|';
|
||||
$totalFailure = 0;
|
||||
|
||||
Write-Host $DirPath;
|
||||
|
||||
if (-not (Test-Path $DirPath)) {
|
||||
if (-not (Test-Path $DirPath)) {
|
||||
Write-Error "Folder does not exist!"
|
||||
}
|
||||
|
||||
@@ -70,7 +76,7 @@ $items | ForEach-Object {
|
||||
Write-Host "Version set to 1.0.0.0: " + $_.FullName
|
||||
$totalFailure++;
|
||||
}
|
||||
elseif ($_.VersionInfo.FileVersion -eq $null -and $_.Name -notmatch $nullVersionExceptions) {
|
||||
elseif ($_.VersionInfo.FileVersion -eq $null -and $_.Name -notmatch $nullVersionExceptions) {
|
||||
# These items are exceptions that actually a version not set.
|
||||
Write-Host "Version not set: " + $_.FullName
|
||||
$totalFailure++;
|
||||
|
||||
@@ -5,7 +5,10 @@ Param(
|
||||
|
||||
[Parameter(Mandatory=$True,Position=2)]
|
||||
[AllowEmptyString()]
|
||||
[string]$DevEnvironment = "Local"
|
||||
[string]$DevEnvironment = "Local",
|
||||
|
||||
[Parameter(Mandatory=$True,Position=3)]
|
||||
[string]$cmdPalVersionNumber = "0.0.1"
|
||||
)
|
||||
|
||||
Write-Host $PSScriptRoot
|
||||
@@ -38,9 +41,20 @@ $verPropReadFileLocation = $verPropWriteFileLocation;
|
||||
$verProps.Project.PropertyGroup.Version = $versionNumber;
|
||||
$verProps.Project.PropertyGroup.DevEnvironment = $DevEnvironment;
|
||||
|
||||
Write-Host "xml" $verProps.Project.PropertyGroup.Version
|
||||
Write-Host "xml" $verProps.Project.PropertyGroup.Version
|
||||
$verProps.Save($verPropWriteFileLocation);
|
||||
|
||||
|
||||
#### The same thing as above, but for the CmdPal version
|
||||
$verPropWriteFileLocation = $PSScriptRoot + '/../src/CmdPalVersion.props';
|
||||
$verPropReadFileLocation = $verPropWriteFileLocation;
|
||||
[XML]$verProps = Get-Content $verPropReadFileLocation
|
||||
$verProps.Project.PropertyGroup.CmdPalVersion = $cmdPalVersionNumber;
|
||||
$verProps.Project.PropertyGroup.DevEnvironment = $DevEnvironment;
|
||||
Write-Host "xml" $verProps.Project.PropertyGroup.Version
|
||||
$verProps.Save($verPropWriteFileLocation);
|
||||
#######
|
||||
|
||||
# Set PowerRenameContextMenu package version in AppManifest.xml
|
||||
$powerRenameContextMenuAppManifestWriteFileLocation = $PSScriptRoot + '/../src/modules/powerrename/PowerRenameContextMenu/AppxManifest.xml';
|
||||
$powerRenameContextMenuAppManifestReadFileLocation = $powerRenameContextMenuAppManifestWriteFileLocation;
|
||||
@@ -76,3 +90,12 @@ $newPlusContextMenuAppManifestReadFileLocation = $newPlusContextMenuAppManifestW
|
||||
$newPlusContextMenuAppManifest.Package.Identity.Version = $versionNumber + '.0'
|
||||
Write-Host "NewPlusContextMenu version" $newPlusContextMenuAppManifest.Package.Identity.Version
|
||||
$newPlusContextMenuAppManifest.Save($newPlusContextMenuAppManifestWriteFileLocation);
|
||||
|
||||
# Set package version in Package.appxmanifest
|
||||
$cmdPalAppManifestWriteFileLocation = $PSScriptRoot + '/../src/modules/cmdpal/Microsoft.CmdPal.UI/Package.appxmanifest';
|
||||
$cmdPalAppManifestReadFileLocation = $cmdPalAppManifestWriteFileLocation;
|
||||
|
||||
[XML]$cmdPalAppManifest = Get-Content $cmdPalAppManifestReadFileLocation
|
||||
$cmdPalAppManifest.Package.Identity.Version = $cmdPalVersionNumber + '.0'
|
||||
Write-Host "CmdPal Package version: " $cmdPalAppManifest.Package.Identity.Version
|
||||
$cmdPalAppManifest.Save($cmdPalAppManifestWriteFileLocation);
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
{
|
||||
"version": "1.0",
|
||||
"components": [
|
||||
"components": [
|
||||
"Microsoft.VisualStudio.Component.CoreEditor",
|
||||
"Microsoft.VisualStudio.Workload.CoreEditor",
|
||||
"Microsoft.VisualStudio.Workload.NativeDesktop",
|
||||
"Microsoft.VisualStudio.Workload.ManagedDesktop",
|
||||
"Microsoft.VisualStudio.Workload.Universal",
|
||||
"Microsoft.VisualStudio.Component.Windows10SDK.19041",
|
||||
"Microsoft.VisualStudio.Component.Windows10SDK.20348",
|
||||
"Microsoft.VisualStudio.Component.Windows10SDK.22621",
|
||||
"Microsoft.VisualStudio.ComponentGroup.UWP.VC",
|
||||
"Microsoft.VisualStudio.Component.UWP.VC.ARM64",
|
||||
@@ -18,4 +19,4 @@
|
||||
"Microsoft.VisualStudio.Component.VC.ATL.Spectre",
|
||||
"Microsoft.VisualStudio.ComponentGroup.WindowsAppSDK.Cs"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -3,17 +3,21 @@
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="AdaptiveCards.ObjectModel.WinUI3" Version="2.0.0-beta" />
|
||||
<PackageVersion Include="AdaptiveCards.Rendering.WinUI3" Version="2.1.0-beta" />
|
||||
<PackageVersion Include="AdaptiveCards.Templating" Version="2.0.2" />
|
||||
<PackageVersion Include="Appium.WebDriver" Version="4.4.5" />
|
||||
<PackageVersion Include="Azure.AI.OpenAI" Version="1.0.0-beta.17" />
|
||||
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.2.2" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Animations" Version="8.0.240109" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Collections" Version="8.0.240109" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Primitives" Version="8.0.240109" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.0.240109" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Segmented" Version="8.0.240109" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Sizers" Version="8.0.240109" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Converters" Version="8.0.240109" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Extensions" Version="8.0.240109" />
|
||||
<PackageVersion Include="CommunityToolkit.Common" Version="8.4.0" />
|
||||
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Animations" Version="8.2.250129-preview2" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Collections" Version="8.2.250129-preview2" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Primitives" Version="8.2.250129-preview2" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.2.250129-preview2" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Segmented" Version="8.2.250129-preview2" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Sizers" Version="8.2.250129-preview2" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Converters" Version="8.2.250129-preview2" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Extensions" Version="8.2.250129-preview2" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.UI.Controls.DataGrid" Version="7.1.2" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.UI.Controls.Markdown" Version="7.1.2" />
|
||||
<PackageVersion Include="ControlzEx" Version="6.0.0" />
|
||||
@@ -27,30 +31,31 @@
|
||||
<!-- Including MessagePack to force version, since it's used by StreamJsonRpc but contains vulnerabilities. After StreamJsonRpc updates the version of MessagePack, we can upgrade StreamJsonRpc instead. -->
|
||||
<PackageVersion Include="MessagePack" Version="2.5.187" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="9.0.0" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.2" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.3" />
|
||||
<!-- Including Microsoft.Bcl.AsyncInterfaces to force version, since it's used by Microsoft.SemanticKernel. -->
|
||||
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.2" />
|
||||
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.3" />
|
||||
<PackageVersion Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="3.1.16" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.3" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.3" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.3" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.3" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.3" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel" Version="1.15.0" />
|
||||
<PackageVersion Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.2" />
|
||||
<PackageVersion Include="Microsoft.Web.WebView2" Version="1.0.2739.15" />
|
||||
<PackageVersion Include="Microsoft.Web.WebView2" Version="1.0.2903.40" />
|
||||
<!-- Package Microsoft.Win32.SystemEvents added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Drawing.Common but the 8.0.1 version wasn't published to nuget. -->
|
||||
<PackageVersion Include="Microsoft.Win32.SystemEvents" Version="9.0.2" />
|
||||
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="9.0.2" />
|
||||
<PackageVersion Include="Microsoft.Win32.SystemEvents" Version="9.0.3" />
|
||||
<PackageVersion Include="Microsoft.WindowsPackageManager.ComInterop" Version="1.10.120-preview" />
|
||||
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="9.0.3" />
|
||||
<PackageVersion Include="Microsoft.Windows.CsWin32" Version="0.2.46-beta" />
|
||||
<!-- CsWinRT version needs to be set to have a WinRT.Runtime.dll at the same version contained inside the NET SDK we're currently building on CI. -->
|
||||
<!--
|
||||
TODO: in Common.Dotnet.CsWinRT.props, on upgrade, verify RemoveCsWinRTPackageAnalyzer is no longer needed.
|
||||
This is present due to a bug in CsWinRT where WPF projects cause the analyzer to fail.
|
||||
-->
|
||||
<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="2.1.5" />
|
||||
<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />
|
||||
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.2428" />
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.6.241114003" />
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.6.250205002" />
|
||||
<PackageVersion Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.9" />
|
||||
<PackageVersion Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.39" />
|
||||
<PackageVersion Include="ModernWpfUI" Version="0.9.4" />
|
||||
@@ -67,35 +72,36 @@
|
||||
<PackageVersion Include="StreamJsonRpc" Version="2.19.27" />
|
||||
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
|
||||
<!-- Package System.CodeDom added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Management but the 8.0.1 version wasn't published to nuget. -->
|
||||
<PackageVersion Include="System.CodeDom" Version="9.0.2" />
|
||||
<PackageVersion Include="System.CodeDom" Version="9.0.3" />
|
||||
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
|
||||
<PackageVersion Include="System.ComponentModel.Composition" Version="9.0.2" />
|
||||
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="9.0.2" />
|
||||
<PackageVersion Include="System.Data.OleDb" Version="9.0.2" />
|
||||
<PackageVersion Include="System.ComponentModel.Composition" Version="9.0.3" />
|
||||
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="9.0.3" />
|
||||
<PackageVersion Include="System.Data.OleDb" Version="9.0.3" />
|
||||
<!-- Package System.Data.SqlClient added to force it as a dependency of Microsoft.Windows.Compatibility to the latest version available at this time. -->
|
||||
<PackageVersion Include="System.Data.SqlClient" Version="4.8.6" />
|
||||
<!-- Package System.Diagnostics.EventLog added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Data.OleDb but the 8.0.1 version wasn't published to nuget. -->
|
||||
<PackageVersion Include="System.Diagnostics.EventLog" Version="9.0.2" />
|
||||
<PackageVersion Include="System.Diagnostics.EventLog" Version="9.0.3" />
|
||||
<!-- Package System.Diagnostics.PerformanceCounter added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.11. -->
|
||||
<PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="9.0.2" />
|
||||
<PackageVersion Include="System.Drawing.Common" Version="9.0.2" />
|
||||
<PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="9.0.3" />
|
||||
<PackageVersion Include="System.Drawing.Common" Version="9.0.3" />
|
||||
<PackageVersion Include="System.IO.Abstractions" Version="21.0.29" />
|
||||
<PackageVersion Include="System.IO.Abstractions.TestingHelpers" Version="21.0.29" />
|
||||
<PackageVersion Include="System.Management" Version="9.0.2" />
|
||||
<PackageVersion Include="System.Management" Version="9.0.3" />
|
||||
<PackageVersion Include="System.Reactive" Version="6.0.1" />
|
||||
<PackageVersion Include="System.Runtime.Caching" Version="9.0.2" />
|
||||
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="9.0.2" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.2" />
|
||||
<PackageVersion Include="System.Text.Json" Version="9.0.2" />
|
||||
<PackageVersion Include="System.Runtime.Caching" Version="9.0.3" />
|
||||
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="9.0.3" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.3" />
|
||||
<PackageVersion Include="System.Text.Json" Version="9.0.3" />
|
||||
<PackageVersion Include="UnicodeInformation" Version="2.6.0" />
|
||||
<PackageVersion Include="UnitsNet" Version="5.56.0" />
|
||||
<PackageVersion Include="UTF.Unknown" Version="2.5.1" />
|
||||
<PackageVersion Include="WinUIEx" Version="2.2.0" />
|
||||
<PackageVersion Include="WPF-UI" Version="3.0.5" />
|
||||
<PackageVersion Include="WyHash" Version="1.0.5" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(IsExperimentationLive)'!=''">
|
||||
<!-- Additional dependencies used by experimentation -->
|
||||
<PackageVersion Include="Microsoft.VariantAssignment.Client" Version="2.4.17140001" />
|
||||
<PackageVersion Include="Microsoft.VariantAssignment.Contract" Version="3.0.16990001" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
170
NOTICE.md
170
NOTICE.md
@@ -3,12 +3,14 @@
|
||||
This software incorporates material from third parties.
|
||||
|
||||
- Color Picker
|
||||
- Command Palette
|
||||
- File Explorer Add-ins
|
||||
- ImageResizer
|
||||
- PowerToys Run
|
||||
- Installer/Runner
|
||||
- Measure tool
|
||||
- Peek
|
||||
- Registry Preview
|
||||
|
||||
## Utility: Color Picker
|
||||
|
||||
@@ -38,6 +40,41 @@ 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
|
||||
|
||||
### wyhash
|
||||
|
||||
We use the WyHash NuGet package for calculating stable hashes for strings.
|
||||
|
||||
**Source**: [https://github.com/wangyi-fudan/wyhash](https://github.com/wangyi-fudan/wyhash)
|
||||
|
||||
```
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
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 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.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
```
|
||||
|
||||
## Utility: File Explorer Add-ins
|
||||
|
||||
### Monaco Editor
|
||||
@@ -788,6 +825,34 @@ SOFTWARE.
|
||||
|
||||
## Utility: Peek
|
||||
|
||||
### Monaco Editor
|
||||
|
||||
**Source**: https://github.com/Microsoft/monaco-editor
|
||||
|
||||
**Additional third party notifications:** https://github.com/microsoft/monaco-editor/blob/main/ThirdPartyNotices.txt
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 - present Microsoft Corporation
|
||||
|
||||
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.
|
||||
|
||||
### The Quite OK Image Format reference decoder
|
||||
|
||||
**Source**: https://github.com/phoboslab/qoi
|
||||
@@ -1294,19 +1359,56 @@ EXHIBIT A -Mozilla Public License.
|
||||
Original Code Source Code for Your Modifications.]
|
||||
```
|
||||
|
||||
## Utility: Registry Preview
|
||||
|
||||
### Monaco Editor
|
||||
|
||||
**Source**: https://github.com/Microsoft/monaco-editor
|
||||
|
||||
**Additional third party notifications:** https://github.com/microsoft/monaco-editor/blob/main/ThirdPartyNotices.txt
|
||||
|
||||
```
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 - present Microsoft Corporation
|
||||
|
||||
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.
|
||||
```
|
||||
|
||||
## NuGet Packages used by PowerToys
|
||||
|
||||
|
||||
- AdaptiveCards.ObjectModel.WinUI3 2.0.0-beta
|
||||
- AdaptiveCards.Rendering.WinUI3 2.1.0-beta
|
||||
- AdaptiveCards.Templating 2.0.2
|
||||
- Appium.WebDriver 4.4.5
|
||||
- Azure.AI.OpenAI 1.0.0-beta.17
|
||||
- CommunityToolkit.Mvvm 8.2.2
|
||||
- CommunityToolkit.WinUI.Animations 8.0.240109
|
||||
- CommunityToolkit.WinUI.Collections 8.0.240109
|
||||
- CommunityToolkit.WinUI.Controls.Primitives 8.0.240109
|
||||
- CommunityToolkit.WinUI.Controls.Segmented 8.0.240109
|
||||
- CommunityToolkit.WinUI.Controls.SettingsControls 8.0.240109
|
||||
- CommunityToolkit.WinUI.Controls.Sizers 8.0.240109
|
||||
- CommunityToolkit.WinUI.Converters 8.0.240109
|
||||
- CommunityToolkit.WinUI.Extensions 8.0.240109
|
||||
- CommunityToolkit.Common 8.4.0
|
||||
- CommunityToolkit.Mvvm 8.4.0
|
||||
- CommunityToolkit.WinUI.Animations 8.2.250129-preview2
|
||||
- CommunityToolkit.WinUI.Collections 8.2.250129-preview2
|
||||
- CommunityToolkit.WinUI.Controls.Primitives 8.2.250129-preview2
|
||||
- CommunityToolkit.WinUI.Controls.Segmented 8.2.250129-preview2
|
||||
- CommunityToolkit.WinUI.Controls.SettingsControls 8.2.250129-preview2
|
||||
- CommunityToolkit.WinUI.Controls.Sizers 8.2.250129-preview2
|
||||
- CommunityToolkit.WinUI.Converters 8.2.250129-preview2
|
||||
- CommunityToolkit.WinUI.Extensions 8.2.250129-preview2
|
||||
- CommunityToolkit.WinUI.UI.Controls.DataGrid 7.1.2
|
||||
- CommunityToolkit.WinUI.UI.Controls.Markdown 7.1.2
|
||||
- ControlzEx 6.0.0
|
||||
@@ -1318,26 +1420,27 @@ EXHIBIT A -Mozilla Public License.
|
||||
- Mages 3.0.0
|
||||
- Markdig.Signed 0.34.0
|
||||
- MessagePack 2.5.187
|
||||
- Microsoft.Bcl.AsyncInterfaces 9.0.2
|
||||
- Microsoft.Bcl.AsyncInterfaces 9.0.3
|
||||
- Microsoft.CodeAnalysis.NetAnalyzers 9.0.0
|
||||
- Microsoft.Data.Sqlite 9.0.2
|
||||
- Microsoft.Data.Sqlite 9.0.3
|
||||
- Microsoft.Diagnostics.Tracing.TraceEvent 3.1.16
|
||||
- Microsoft.DotNet.ILCompiler (A)
|
||||
- Microsoft.Extensions.DependencyInjection 9.0.2
|
||||
- Microsoft.Extensions.Hosting 9.0.2
|
||||
- Microsoft.Extensions.Hosting.WindowsServices 9.0.2
|
||||
- Microsoft.Extensions.Logging 9.0.2
|
||||
- Microsoft.Extensions.Logging.Abstractions 9.0.2
|
||||
- Microsoft.Extensions.DependencyInjection 9.0.3
|
||||
- Microsoft.Extensions.Hosting 9.0.3
|
||||
- Microsoft.Extensions.Hosting.WindowsServices 9.0.3
|
||||
- Microsoft.Extensions.Logging 9.0.3
|
||||
- Microsoft.Extensions.Logging.Abstractions 9.0.3
|
||||
- Microsoft.NET.ILLink.Tasks (A)
|
||||
- Microsoft.SemanticKernel 1.15.0
|
||||
- Microsoft.Toolkit.Uwp.Notifications 7.1.2
|
||||
- Microsoft.Web.WebView2 1.0.2739.15
|
||||
- Microsoft.Win32.SystemEvents 9.0.2
|
||||
- Microsoft.Windows.Compatibility 9.0.2
|
||||
- Microsoft.Web.WebView2 1.0.2903.40
|
||||
- Microsoft.Win32.SystemEvents 9.0.3
|
||||
- Microsoft.Windows.Compatibility 9.0.3
|
||||
- Microsoft.Windows.CsWin32 0.2.46-beta
|
||||
- Microsoft.Windows.CsWinRT 2.1.5
|
||||
- Microsoft.Windows.CsWinRT 2.2.0
|
||||
- Microsoft.Windows.SDK.BuildTools 10.0.22621.2428
|
||||
- Microsoft.WindowsAppSDK 1.6.241114003
|
||||
- Microsoft.WindowsAppSDK 1.6.250205002
|
||||
- Microsoft.WindowsPackageManager.ComInterop 1.10.120-preview
|
||||
- Microsoft.Xaml.Behaviors.WinUI.Managed 2.0.9
|
||||
- Microsoft.Xaml.Behaviors.Wpf 1.1.39
|
||||
- ModernWpfUI 0.9.4
|
||||
@@ -1351,25 +1454,26 @@ EXHIBIT A -Mozilla Public License.
|
||||
- SharpCompress 0.37.2
|
||||
- StreamJsonRpc 2.19.27
|
||||
- StyleCop.Analyzers 1.2.0-beta.556
|
||||
- System.CodeDom 9.0.2
|
||||
- System.CodeDom 9.0.3
|
||||
- System.CommandLine 2.0.0-beta4.22272.1
|
||||
- System.ComponentModel.Composition 9.0.2
|
||||
- System.Configuration.ConfigurationManager 9.0.2
|
||||
- System.Data.OleDb 9.0.2
|
||||
- System.ComponentModel.Composition 9.0.3
|
||||
- System.Configuration.ConfigurationManager 9.0.3
|
||||
- System.Data.OleDb 9.0.3
|
||||
- System.Data.SqlClient 4.8.6
|
||||
- System.Diagnostics.EventLog 9.0.2
|
||||
- System.Diagnostics.PerformanceCounter 9.0.2
|
||||
- System.Drawing.Common 9.0.2
|
||||
- System.Diagnostics.EventLog 9.0.3
|
||||
- System.Diagnostics.PerformanceCounter 9.0.3
|
||||
- System.Drawing.Common 9.0.3
|
||||
- System.IO.Abstractions 21.0.29
|
||||
- System.IO.Abstractions.TestingHelpers 21.0.29
|
||||
- System.Management 9.0.2
|
||||
- System.Management 9.0.3
|
||||
- System.Reactive 6.0.1
|
||||
- System.Runtime.Caching 9.0.2
|
||||
- System.ServiceProcess.ServiceController 9.0.2
|
||||
- System.Text.Encoding.CodePages 9.0.2
|
||||
- System.Text.Json 9.0.2
|
||||
- System.Runtime.Caching 9.0.3
|
||||
- System.ServiceProcess.ServiceController 9.0.3
|
||||
- System.Text.Encoding.CodePages 9.0.3
|
||||
- System.Text.Json 9.0.3
|
||||
- UnicodeInformation 2.6.0
|
||||
- UnitsNet 5.56.0
|
||||
- UTF.Unknown 2.5.1
|
||||
- WinUIEx 2.2.0
|
||||
- WPF-UI 3.0.5
|
||||
- WyHash 1.0.5
|
||||
|
||||
318
PowerToys.sln
318
PowerToys.sln
@@ -620,10 +620,64 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EtwTrace", "src\common\Tele
|
||||
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\Exts\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\Exts\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\Exts\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\Exts\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\Exts\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\Exts\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\Exts\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.Common", "src\modules\cmdpal\Microsoft.CmdPal.Common\Microsoft.CmdPal.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\Exts\ProcessMonitorExtension\ProcessMonitorExtension.csproj", "{C846F7A7-792A-47D9-B0CB-417C900EE03D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SamplePagesExtension", "src\modules\cmdpal\Exts\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\Exts\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\Exts\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\Exts\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\Exts\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\Exts\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\Exts\Microsoft.CmdPal.Ext.WinGet\Microsoft.CmdPal.Ext.WinGet.csproj", "{E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvancedPaste.UnitTests", "src\modules\AdvancedPaste\AdvancedPaste.UnitTests\AdvancedPaste.UnitTests.csproj", "{D5E5F5EA-1B6C-4A73-88BE-304F36C9E4EE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvancedPaste.FuzzTests", "src\modules\AdvancedPaste\AdvancedPaste.FuzzTests\AdvancedPaste.FuzzTests.csproj", "{7F5B9557-5878-4438-A721-3E28296BA193}"
|
||||
@@ -636,6 +690,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZoomItModuleInterface", "sr
|
||||
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\Exts\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}"
|
||||
@@ -646,6 +702,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hosts.FuzzTests", "src\modu
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hosts.UITests", "src\modules\Hosts\Hosts.UITests\Hosts.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\Exts\Microsoft.CmdPal.Ext.System\Microsoft.CmdPal.Ext.System.csproj", "{64B88F02-CD88-4ED8-9624-989A800230F9}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
@@ -2198,6 +2258,154 @@ Global
|
||||
{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
|
||||
@@ -2214,6 +2422,54 @@ Global
|
||||
{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
|
||||
{D5E5F5EA-1B6C-4A73-88BE-304F36C9E4EE}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{D5E5F5EA-1B6C-4A73-88BE-304F36C9E4EE}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{D5E5F5EA-1B6C-4A73-88BE-304F36C9E4EE}.Debug|x64.ActiveCfg = Debug|x64
|
||||
@@ -2254,6 +2510,18 @@ Global
|
||||
{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
|
||||
@@ -2294,6 +2562,26 @@ Global
|
||||
{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}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{64B88F02-CD88-4ED8-9624-989A800230F9}.Debug|x86.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
|
||||
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|x86.ActiveCfg = Release|x64
|
||||
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|x86.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -2521,19 +2809,49 @@ Global
|
||||
{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} = {B6C42F16-73EB-477E-8B0D-4E6CF6C20AAC}
|
||||
{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} = {7520A2FE-00A2-49B8-83ED-DB216E874C04}
|
||||
{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}
|
||||
{D5E5F5EA-1B6C-4A73-88BE-304F36C9E4EE} = {9873BA05-4C41-4819-9283-CF45D795431B}
|
||||
{7F5B9557-5878-4438-A721-3E28296BA193} = {9873BA05-4C41-4819-9283-CF45D795431B}
|
||||
{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} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA}
|
||||
{4E0AE3A4-2EE0-44D7-A2D0-8769977254A0} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA}
|
||||
{5702B3CC-8575-48D5-83D8-15BB42269CD3} = {929C1324-22E8-4412-A9A8-80E85F3985A5}
|
||||
{64B88F02-CD88-4ED8-9624-989A800230F9} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}
|
||||
|
||||
184
README.md
184
README.md
@@ -11,14 +11,15 @@ Microsoft PowerToys is a set of utilities for power users to tune and streamline
|
||||
| | Current utilities: | |
|
||||
|--------------|--------------------|--------------|
|
||||
| [Advanced Paste](https://aka.ms/PowerToysOverview_AdvancedPaste) | [Always on Top](https://aka.ms/PowerToysOverview_AoT) | [PowerToys Awake](https://aka.ms/PowerToysOverview_Awake) |
|
||||
| [Command Not Found](https://aka.ms/PowerToysOverview_CmdNotFound) | [Color Picker](https://aka.ms/PowerToysOverview_ColorPicker) | [Crop And Lock](https://aka.ms/PowerToysOverview_CropAndLock) |
|
||||
| [Environment Variables](https://aka.ms/PowerToysOverview_EnvironmentVariables) | [FancyZones](https://aka.ms/PowerToysOverview_FancyZones) | [File Explorer Add-ons](https://aka.ms/PowerToysOverview_FileExplorerAddOns) |
|
||||
| [File Locksmith](https://aka.ms/PowerToysOverview_FileLocksmith) | [Hosts File Editor](https://aka.ms/PowerToysOverview_HostsFileEditor) | [Image Resizer](https://aka.ms/PowerToysOverview_ImageResizer) |
|
||||
| [Keyboard Manager](https://aka.ms/PowerToysOverview_KeyboardManager) | [Mouse utilities](https://aka.ms/PowerToysOverview_MouseUtilities) | [Mouse Without Borders](https://aka.ms/PowerToysOverview_MouseWithoutBorders) |
|
||||
| [New+](https://aka.ms/PowerToysOverview_NewPlus) | [Peek](https://aka.ms/PowerToysOverview_Peek) | [Paste as Plain Text](https://aka.ms/PowerToysOverview_PastePlain) |
|
||||
| [PowerRename](https://aka.ms/PowerToysOverview_PowerRename) | [PowerToys Run](https://aka.ms/PowerToysOverview_PowerToysRun) | [Quick Accent](https://aka.ms/PowerToysOverview_QuickAccent) |
|
||||
| [Registry Preview](https://aka.ms/PowerToysOverview_RegistryPreview) | [Screen Ruler](https://aka.ms/PowerToysOverview_ScreenRuler) | [Shortcut Guide](https://aka.ms/PowerToysOverview_ShortcutGuide) |
|
||||
| [Text Extractor](https://aka.ms/PowerToysOverview_TextExtractor) | [Workspaces](https://aka.ms/PowerToysOverview_Workspaces) | [ZoomIt](https://aka.ms/PowerToysOverview_ZoomIt) |
|
||||
| [Color Picker](https://aka.ms/PowerToysOverview_ColorPicker) | [Command Not Found](https://aka.ms/PowerToysOverview_CmdNotFound) | [Command Palette](https://aka.ms/PowerToysOverview_CmdPal) |
|
||||
| [Crop And Lock](https://aka.ms/PowerToysOverview_CropAndLock) | [Environment Variables](https://aka.ms/PowerToysOverview_EnvironmentVariables) | [FancyZones](https://aka.ms/PowerToysOverview_FancyZones) |
|
||||
| [File Explorer Add-ons](https://aka.ms/PowerToysOverview_FileExplorerAddOns) | [File Locksmith](https://aka.ms/PowerToysOverview_FileLocksmith) | [Hosts File Editor](https://aka.ms/PowerToysOverview_HostsFileEditor) |
|
||||
| [Image Resizer](https://aka.ms/PowerToysOverview_ImageResizer) | [Keyboard Manager](https://aka.ms/PowerToysOverview_KeyboardManager) | [Mouse utilities](https://aka.ms/PowerToysOverview_MouseUtilities) |
|
||||
| [Mouse Without Borders](https://aka.ms/PowerToysOverview_MouseWithoutBorders) | [New+](https://aka.ms/PowerToysOverview_NewPlus) | [Paste as Plain Text](https://aka.ms/PowerToysOverview_PastePlain) |
|
||||
| [Peek](https://aka.ms/PowerToysOverview_Peek) | [PowerRename](https://aka.ms/PowerToysOverview_PowerRename) | [PowerToys Run](https://aka.ms/PowerToysOverview_PowerToysRun) |
|
||||
| [Quick Accent](https://aka.ms/PowerToysOverview_QuickAccent) | [Registry Preview](https://aka.ms/PowerToysOverview_RegistryPreview) | [Screen Ruler](https://aka.ms/PowerToysOverview_ScreenRuler) |
|
||||
| [Shortcut Guide](https://aka.ms/PowerToysOverview_ShortcutGuide) | [Text Extractor](https://aka.ms/PowerToysOverview_TextExtractor) | [Workspaces](https://aka.ms/PowerToysOverview_Workspaces) |
|
||||
| [ZoomIt](https://aka.ms/PowerToysOverview_ZoomIt) |
|
||||
|
||||
## Installing and running Microsoft PowerToys
|
||||
|
||||
@@ -34,19 +35,19 @@ Microsoft PowerToys is a set of utilities for power users to tune and streamline
|
||||
Go to the [Microsoft PowerToys GitHub releases page][github-release-link] and click on `Assets` at the bottom to show the files available in the release. Please use the appropriate PowerToys installer that matches your machine's architecture and install scope. For most, it is `x64` and per-user.
|
||||
|
||||
<!-- items that need to be updated release to release -->
|
||||
[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.89%22
|
||||
[github-current-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.88%22
|
||||
[ptUserX64]: https://github.com/microsoft/PowerToys/releases/download/v0.88.0/PowerToysUserSetup-0.88.0-x64.exe
|
||||
[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.88.0/PowerToysUserSetup-0.88.0-arm64.exe
|
||||
[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.88.0/PowerToysSetup-0.88.0-x64.exe
|
||||
[ptMachineArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.88.0/PowerToysSetup-0.88.0-arm64.exe
|
||||
[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.91%22
|
||||
[github-current-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.90%22
|
||||
[ptUserX64]: https://github.com/microsoft/PowerToys/releases/download/v0.90.0/PowerToysUserSetup-0.90.0-x64.exe
|
||||
[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.90.0/PowerToysUserSetup-0.90.0-arm64.exe
|
||||
[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.90.0/PowerToysSetup-0.90.0-x64.exe
|
||||
[ptMachineArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.90.0/PowerToysSetup-0.90.0-arm64.exe
|
||||
|
||||
| Description | Filename | sha256 hash |
|
||||
|----------------|----------|-------------|
|
||||
| Per user - x64 | [PowerToysUserSetup-0.88.0-x64.exe][ptUserX64] | 5BBA2E06603CAAE0269DFBC991095C6664FD934130335197C1BA3120E19B7CA3 |
|
||||
| Per user - ARM64 | [PowerToysUserSetup-0.88.0-arm64.exe][ptUserArm64] | E79723F9F94068C699E01334C8CC0C85F37818EB4664FC772D2B545A1C37C3FA |
|
||||
| Machine wide - x64 | [PowerToysSetup-0.88.0-x64.exe][ptMachineX64] | C43742DB7AA3F8B01FE7AE1DA591F0342767AFE5BBACB72F2968CE5E8EE1E3AC |
|
||||
| Machine wide - ARM64 | [PowerToysSetup-0.88.0-arm64.exe][ptMachineArm64] | AEE4A67643C886336F31F86C4117BA5F01BCA5E0E99FF34524217DC91AFA7132 |
|
||||
| Per user - x64 | [PowerToysUserSetup-0.90.0-x64.exe][ptUserX64] | 2A6036F5B2D454084E55816C306E1E57EF1D14C916691CBDA42B469797605CE0 |
|
||||
| Per user - ARM64 | [PowerToysUserSetup-0.90.0-arm64.exe][ptUserArm64] | AB2E4DC87A9D764BE897C5170E2890E174C89CA912A1916FA3AE1E427536EA4A |
|
||||
| Machine wide - x64 | [PowerToysSetup-0.90.0-x64.exe][ptMachineX64] | 12801C44F43D0CC61E90DF1EFDC40E4F3C88341E0199D5B20791042D9B173DCF |
|
||||
| Machine wide - ARM64 | [PowerToysSetup-0.90.0-arm64.exe][ptMachineArm64] | 2998007C8FCD7BD2770767C6502AAA2CC75B85EC30DE62986EC7005EB0014EDB |
|
||||
|
||||
This is our preferred method.
|
||||
|
||||
@@ -92,141 +93,96 @@ For guidance on developing for PowerToys, please read the [developer docs](/doc/
|
||||
|
||||
Our [prioritized roadmap][roadmap] of features and utilities that the core team is focusing on.
|
||||
|
||||
### 0.88 - January 2025 Update
|
||||
### 0.90 - March 2025 Update
|
||||
|
||||
In this release, we focused on new features, stability, and improvements.
|
||||
In this release, we focused on new features, stability, and automation.
|
||||
|
||||
**Highlights**
|
||||
**✨Highlights**
|
||||
|
||||
- New utility: ZoomIt - a screen zoom, annotation, and recording tool for technical presentations and demos. This utility from Sysinternals has had its source code released and included in PowerToys. ZoomIt will still continue to be updated and shipped by Sysinternals for users who prefer to have it as a standalone utility outside of PowerToys. Thanks [@markrussinovich](https://github.com/markrussinovich), [@foxmsft](https://github.com/foxmsft) and [@johnstep](https://github.com/johnstep) for contributing the original code and reviewing the PowerToys integration!
|
||||
- Video Conference Mute has been deprecated and was removed from PowerToys.
|
||||
- .Net 9.0.1 fixed many issue in WPF, improving stability for PowerToys Run.
|
||||

|
||||
|
||||
### General
|
||||
- Applied a workaround for the Windows App SDK applications title bar override that was causing accent color to not be shown on the top bar of applications on Windows 10. Thanks [@pingzing](https://github.com/pingzing)!
|
||||
- Improved the "admin application running" notification checking logic to be less demanding on resources. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Fixed an issue causing many utilities to crash when the GPO to disable data diagnostics was applied.
|
||||
- New module: Command Palette ("CmdPal") - Created as the evolution of PowerToys Run with extensibility at the forefront, Command Palette is a quick launcher with a richer display and additional capabilities without sacrificing performance, allowing you to start anything with the shortcut **Win+Alt+Space**! Thanks [@zadjii-msft](https://github.com/zadjii-msft), [@niels9001](https://github.com/niels9001), [@joadoumie](https://github.com/joadoumie), [@plante-msft](https://github.com/plante-msft), [@ethanfangg](https://github.com/ethanfangg) and [@krschau](https://github.com/krschau)!
|
||||
- Enhanced the Color Picker by switching from WPF UI to .NET WPF, resulting in improved themes and visual consistency across different modes. Thanks [@mantaionut](https://github.com/mantaionut)! Thanks [@Jay-o-Way](https://github.com/Jay-o-Way) and [@niels9001](https://github.com/niels9001) for helping with the review!
|
||||
- Added the ability to delete files directly from Peek, enhancing file management efficiency. Thanks [@daverayment](https://github.com/daverayment) and thanks [@htcfreek](https://github.com/htcfreek) for the review!
|
||||
- Added support for variables in template filenames, enabling dynamic elements like date components and environment variables for enhanced customization in New+. Thanks [@cgaarden](https://github.com/cgaarden)!
|
||||
|
||||
### Advanced Paste
|
||||
### Color Picker
|
||||
|
||||
- Fixed a crash when the application was exiting. (This was a hotfix for 0.87)
|
||||
- Added a Json format validation step to verify if a conversion to Json should be applied.
|
||||
- Fixed accessibility issues when using a screen reader.
|
||||
- Added support for all BitmapDecoder supported image file types to the Image to Text functionality. Thanks [@daverayment](https://github.com/daverayment)!
|
||||
- Fixed an issue causing Advanced Paste initialization errors to hang the PowerToys main process.
|
||||
- Replaced WPF UI with .NET WPF for the Color Picker, enhancing compatibility and improving theme support. Thanks [@mantaionut](https://github.com/mantaionut)! Thanks [@Jay-o-Way](https://github.com/Jay-o-Way) and [@niels9001](https://github.com/niels9001) for helping with the review!
|
||||
|
||||
### Command Palette
|
||||
|
||||
- Introduced the Windows Command Palette ("CmdPal"), the next iteration of PowerToys Run, designed with extensibility at its core. CmdPal includes features such as searching for installed apps, shell commands, files and WinGet package installation. This module aims to provide a more powerful and flexible launcher experience. Thanks [@zadjii-msft](https://github.com/zadjii-msft), [@niels9001](https://github.com/niels9001), [@joadoumie](https://github.com/joadoumie), [@plante-msft](https://github.com/plante-msft), and the whole team!
|
||||
|
||||
### FancyZones
|
||||
|
||||
- Removed Workspaces Editor from the exclusions list so it can be snapped by FancyZones.
|
||||
- Fixed a bug where deleting a layout resulted in incorrect data being written to the JSON file.
|
||||
- Fixed a bug where layout hotkeys were displayed incorrectly, ensuring the hotkey list does not include invalid entries.
|
||||
- Fixed an issue where the "None" option was missing in the editor layout.
|
||||
|
||||
### Keyboard Manager
|
||||
### Image Resizer
|
||||
|
||||
- Added an option to make a shortcut remapping only trigger with exact modifiers.
|
||||
|
||||
### Monaco Preview
|
||||
|
||||
- Added support for .resx and .resw files in Peek and File Explorer add-ons. Thanks [@asif4318](https://github.com/asif4318)!
|
||||
- Added a setting to make the code minimap toggle-able in Peek and File Explorer add-ons. Thanks [@PesBandi](https://github.com/PesBandi)!
|
||||
- Fixed an issue causing Json format preview setting to not be applied correctly.
|
||||
- Fixed an issue causing the wrong Monaco assets to be used at runtime.
|
||||
- Fixed warnings in ImageResizer regarding the use of variables "shellItem" and "itemName" without being initialized.
|
||||
|
||||
### Mouse Without Borders
|
||||
|
||||
- Fixed an issue causing clipboard to stop working after going through a UAC screen when using the Service mode. Thanks [@YDKK](https://github.com/YDKK)!
|
||||
- Enhanced the logger to properly track the file path for easier debugging.
|
||||
- Refactored the "Common" class into distinct individual classes to enhance maintainability, and updated all references and unit tests to reflect these changes. Thanks [@mikeclayton](https://github.com/mikeclayton) for this!
|
||||
|
||||
### New+
|
||||
|
||||
- Fixed an issue causing New+ to override the New file or folder creation from the File Explorer Ribbon buttons or keyboard shortcuts on Windows 10.
|
||||
- When creating file or folders through a template, they should now have the current time as the last modified date. Thanks [@cgaarden](https://github.com/cgaarden)!
|
||||
- Added support for variables in template filenames, including date/time components, parent folder name, and environment variables. Thanks [@cgaarden](https://github.com/cgaarden)!
|
||||
|
||||
### Peek
|
||||
|
||||
- Fixed an issue causing Peek to not appear if it was previously minimized. Thanks [@asif4318](https://github.com/asif4318)!
|
||||
- Added the ability to delete the file currently being previewed in Peek, including navigation updates and handling for deleted items. Thanks [@daverayment](https://github.com/daverayment) and thanks [@htcfreek](https://github.com/htcfreek) for your help reviewing this!
|
||||
|
||||
### PowerToys Run
|
||||
|
||||
- Fixed a transparent border issue on Windows 10. (This was a hotfix for 0.87)
|
||||
- Fixed a crash in the OneNote plugin after the .Net 9 update. (This was a hotfix for 0.87)
|
||||
- Fixed an issue causing the Calculator plugin to return division by zero errors when dividing by hexadecimal numbers. Thanks [@plante-msft](https://github.com/plante-msft)!
|
||||
- Updated the Calculator plugin Mages library to 3.0.0 and added support for the random integer function. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Improved handling of non-base 10 numbers to add support for binary and octal numbers in the Calculator plugin. Thanks [@PesBandi](https://github.com/PesBandi)!
|
||||
- Added a setting to enable selection of which units to use for trigonometric functions. Thanks [@OldUser101](https://github.com/OldUser101)!
|
||||
- Fixed a .NET 9 regression causing the PowerToys Run dialog to not be draggable. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Added context menu buttons for the VS Code Workspaces plugin, for copying the path, opening in File Explorer or in Console. Thanks [@programming-with-ia](https://github.com/programming-with-ia)!
|
||||
- Added some telemetry to gather data on which hotkey is used to trigger PowerToys Run.
|
||||
- Removed the workarounds that were in place to fix some WPF issues that were fixed in .NET 9.0.1.
|
||||
- Fixed a typo in the Value Generator plugin messages. Thanks [@OldUser101](https://github.com/OldUser101)!
|
||||
|
||||
### Quick Accent
|
||||
|
||||
- Added the ć character to the Slovenian character set. Thanks [@dsoklic](https://github.com/dsoklic)!
|
||||
- Added the Proto-Indo-European character set.
|
||||
|
||||
### Registry Preview
|
||||
|
||||
- Fixed an issue causing line breaks to not be parsed correctly for REG_MULTI_SZ values. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Added a tooltip to values to show multiple lines of data. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Added a context menu to enable copying type, value and key paths. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Fixed an issue where duplicated applications were shown by ensuring the shell link helper opens .ink files non-exclusively and correctly retrieves the "FullPath". Thanks [@htcfreek](https://github.com/htcfreek) and [@davidegiacometti](https://github.com/davidegiacometti) for review!
|
||||
- Fixed an issue where applying round corners on Windows 11 build 22000 caused crashes.
|
||||
- Async the OnRename method to unblock the thread. Thanks [@davidegiacometti](https://github.com/davidegiacometti) for review!
|
||||
- Added support for using `sq` instead of `^2` in the Unit Converter. Thanks [@PesBandi](https://github.com/PesBandi)!
|
||||
|
||||
### Settings
|
||||
|
||||
- Made the Advanced Paste paste OpenAI configuration modal scrollable.
|
||||
- Fixed the text on the Quick Accent page to refer to "character sets" instead of "character set". Thanks [@PesBandi](https://github.com/PesBandi)!
|
||||
- Added the plugin's dll file version and website to the PowerToys Run plugin settings. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Added the Workspaces file to the list of files that gets backed up by the Back up / Restore functionality.
|
||||
- Fixed an issue causing some of the selected character sets to be unselected when opening the character set expander in the Quick Accent page.
|
||||
- Improved GPO logic, icons, info bar layout and enabled state of all modules settings pages. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Fixed some accessibility issues and refactored and improved quality of the code related to image sizes in the Image Resizer page. Thanks [@daverayment](https://github.com/daverayment)!
|
||||
- Fixed mentions of "Backup" to "Back up" when it should be used as a verb. Thanks [@JackStuart](https://github.com/JackStuart)!
|
||||
- Added a "New" label to Settings to better highlight new utilities that get released. Thanks [@niels9001](https://github.com/niels9001) for the UI tweaks!
|
||||
|
||||
### Text Extractor
|
||||
|
||||
- Fixed many accessibility and UI issues on the overlay UI. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Disabled the spell check feature in the text boxes of plugin settings for PowerToys Run. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Fixed an issue where InfoBars for release notes errors were not displayed properly, and added a retry button. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
|
||||
### Workspaces
|
||||
|
||||
- Fixed an issue causing the Workspaces Editor to start outside of visible desktop area.
|
||||
- Fixed an issue to maintain command line arguments for applications when trying using the "Launch and Edit" feature.
|
||||
|
||||
### Video Conference Mute
|
||||
|
||||
- The module has been deprecated in 0.88.0, being removed from PowerToys.
|
||||
|
||||
### ZoomIt
|
||||
|
||||
- New utility: Zoom It - a screen zoom, annotation, and recording tool for technical presentations and demos. This utility from Sysinternals has had its source code released and included in PowerToys. ZoomIt will still continue to be updated and shipped by Sysinternals for users who prefer to have it as a standalone utility outside of PowerToys. Thanks [@markrussinovich](https://github.com/markrussinovich), [@foxmsft](https://github.com/foxmsft) and [@johnstep](https://github.com/johnstep) for contributing the original code and reviewing the PowerToys integration!
|
||||
- Fixed an issue where some minimized packaged apps (e.g., Microsoft ToDo, Settings) were not snapshotted.
|
||||
|
||||
### Documentation
|
||||
|
||||
- Updated the PowerToys Run documentation to reflect documentation pages for new plugins.
|
||||
- Added YubicoOauthOTP plugin mention to thirdPartyRunPlugins.md. Thanks [@dlnilsson](https://github.com/dlnilsson)!
|
||||
- Added the FirefoxBookmark plugin to the list of Third-Party plugins for PowerToys Run. Thanks [@8LWXpg](https://github.com/8LWXpg)!
|
||||
- Added the SVGL third-party plugin to PowerToys Run, enabling users to search, browse, and copy SVG logos. Thanks [@SameerJS6](https://github.com/SameerJS6)!
|
||||
- Added Monaco usage for the Registry Preview.
|
||||
|
||||
### Development
|
||||
|
||||
- Added fuzz testing for AdvancedPaste, with a new pipeline for OneFuzz.
|
||||
- Added a new CI pipeline to build with the latest WindowsAppSDK.
|
||||
- Added a new CI pipeline to build with the latest webview2 from Edge Canary.
|
||||
- Made the HostsUILib project AOT compatible. Thanks [@snickler](https://github.com/snickler) for your help reviewing this!
|
||||
- Made FilePreviewCommon and MarkdownPreviewHandler AOT compatible. Thanks [@snickler](https://github.com/snickler) for your help reviewing this!
|
||||
- Made the PowerAccent.Core project AOT compatible. Thanks [@snickler](https://github.com/snickler) for your help reviewing this!
|
||||
- Cleaned up some code for AOT compatibility in the Advanced Paste module. Thanks [@snickler](https://github.com/snickler) for your help reviewing this!
|
||||
- Removed the prerelease flag from the PowerToys development DSC configurations. Thanks [@denelon](https://github.com/denelon)!
|
||||
- Improved Dart CI reliability by improving error messages and retrying to the step that installs the correct dotnet version.
|
||||
- Improved Dart CI reliability by fixing retries when downloading the localization files.
|
||||
- Improved Dart CI build times by removing the steps to build the no longer needed abstracted utility nuget packages.
|
||||
- Removed the solution.props file from the solution root.
|
||||
- Fixed PowerToys Run Calculator plugin tests when running in systems with different number formats. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Updated many .NET packages from .NET 9.0.0 to 9.0.1 for security fixes. Thanks [@snickler](https://github.com/snickler)!
|
||||
- Refactored the Mouse Without Borders Common.Log.cs and Common.Receiver.cs files. Thanks [@mikeclayton](https://github.com/mikeclayton)!
|
||||
- Updated WinGet configuration file location and extension. Thanks [@mdanish-kh](https://github.com/mdanish-kh)!
|
||||
- Removed the Markdown file bypass to ensure CI runs for commits that only update Markdown files.
|
||||
- Fixed an issue where the default generated file path exceeded the length limit of 260 characters for EnvironmentVariablesUILib.csproj, causing build failures.
|
||||
- Upgraded WindowsAppSDK to 1.6.250205002 and CsWinRT to 2.2.0. Thanks [@htcfreek](https://github.com/htcfreek) for review!
|
||||
- Upgraded XamlStyler to 3.2501.8 and dotnet-consolidate to 4.2.0. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Updated .NET Packages from 9.0.2 to 9.0.3.
|
||||
- Optimized the UI Test Automation Framework and added UI test cases for the Hosts File Editor module.
|
||||
- Added fuzz testing for RegistryPreview.
|
||||
- Added new UI tests for the FancyZones editor, including tests for creating, duplicating, editing, and deleting layouts.
|
||||
- Added telemetry code to measure the module editor open time and evaluate the benefits of applying AOT.
|
||||
|
||||
#### What is being planned for version 0.89
|
||||
|
||||
For [v0.89][github-next-release-work], we'll work on the items below:
|
||||
|
||||
### What is being planned for version 0.91
|
||||
|
||||
For [v0.91][github-next-release-work], we'll work on the items below:
|
||||
|
||||
- Stability / bug fixes
|
||||
- New module: File Actions Menu
|
||||
- PowerToys Run v2 development work
|
||||
- New UI Automation tests
|
||||
- Working on installer upgrades
|
||||
- Upgrading Keyboard Manager's editor UI
|
||||
- Stability / bug fixes
|
||||
|
||||
## PowerToys Community
|
||||
|
||||
|
||||
@@ -94,5 +94,5 @@ Note that we've supplied `Debug` option, so a `%TEMP\PowerToys.DSC.TestConfigure
|
||||
Finally, you can test it with winget by invoking it as such:
|
||||
|
||||
```ps
|
||||
winget configure .\configuration.dsc.yaml --accept-configuration-agreements --disable-interactivity
|
||||
winget configure .\configuration.winget --accept-configuration-agreements --disable-interactivity
|
||||
```
|
||||
BIN
doc/images/overview/CmdPal_Hero.gif
Normal file
BIN
doc/images/overview/CmdPal_Hero.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.5 MiB |
@@ -42,6 +42,7 @@ Contact the developers of a plugin directly for assistance with a specific plugi
|
||||
| [CanIUse](https://github.com/skttl/ptrun-caniuse) | [skttl](https://github.com/skttl) | Look up browser feature support with caniuse.com |
|
||||
| [TailwindCSS](https://github.com/skttl/ptrun-tailwindcss) | [skttl](https://github.com/skttl) | Search the documentation of TailwindCSS |
|
||||
| [HttpStatusCodes](https://github.com/grzhan/HttpStatusCodePowerToys) | [grzhan](https://github.com/grzhan) | Search for http status codes |
|
||||
| [SVGL](https://github.com/Sameerjs6/powertoys-svgl) | [SameerJS6](https://github.com/SameerJS6) | Search, Browse and copy SVG logos from SVGL. |
|
||||
|
||||
## Extending software plugins
|
||||
|
||||
@@ -63,3 +64,4 @@ Below are community created plugins that target a website or software. They are
|
||||
| [SSH](https://github.com/8LWXpg/PowerToysRun-SSH) | [8LWXpg](https://github.com/8LWXpg) | Connect to ssh clients |
|
||||
| [Bilibili](https://github.com/Whuihuan/PowerToysRun-Bilibili) | [Whuihuan](https://github.com/Whuihuan) | Use AVID or BVID to parse and jump to Bilibili |
|
||||
| [YubicoOauthOTP](https://github.com/dlnilsson/Community.PowerToys.Run.Plugin.YubicoOauthOTP) | [dlnilsson](https://github.com/dlnilsson) | Display generated codes from OATH accounts stored on the YubiKey in powerToys Run |
|
||||
| [Firefox Bookmark](https://github.com/8LWXpg/PowerToysRun-FirefoxBookmark) | [8LWXpg](https://github.com/8LWXpg) | Open bookmarks in Firefox based browser |
|
||||
|
||||
76
installer/PowerToysSetup/CmdPal.wxs
Normal file
76
installer/PowerToysSetup/CmdPal.wxs
Normal file
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
|
||||
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
|
||||
|
||||
<?include $(sys.CURRENTDIR)\Common.wxi?>
|
||||
|
||||
<?define CmdPalBuildDir="$(var.BinDir)\WinUI3Apps\CmdPal\"?>
|
||||
|
||||
<Fragment>
|
||||
<DirectoryRef Id="WinUI3AppsInstallFolder">
|
||||
<Directory Id="CmdPalInstallFolder" Name="CmdPal">
|
||||
<Directory Id="CmdPalDepsInstallFolder" Name="Dependencies">
|
||||
<?if $(sys.BUILDARCH) = x64 ?>
|
||||
<Directory Id="CmdPalDepsX64InstallFolder" Name="x64" />
|
||||
<?else ?>
|
||||
<Directory Id="CmdPalDepsArm64InstallFolder" Name="arm64" />
|
||||
<?endif ?>
|
||||
</Directory>
|
||||
</Directory>
|
||||
</DirectoryRef>
|
||||
|
||||
<DirectoryRef Id="CmdPalInstallFolder" FileSource="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion).0_Test">
|
||||
<Component Id="Module_CmdPal" Win64="yes" Guid="3A4942B2-1A86-4182-B3B4-65157365A980">
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="Module_CmdPal" Value="" KeyPath="yes"/>
|
||||
</RegistryKey>
|
||||
<?if $(sys.BUILDARCH) = x64 ?>
|
||||
<File Source="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion).0_Test\Microsoft.CmdPal.UI_$(var.CmdPalVersion).0_x64.msix" />
|
||||
<?else ?>
|
||||
<File Source="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion).0_Test\Microsoft.CmdPal.UI_$(var.CmdPalVersion).0_arm64.msix" />
|
||||
<?endif ?>
|
||||
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<?if $(sys.BUILDARCH) = x64 ?>
|
||||
<DirectoryRef Id="CmdPalDepsX64InstallFolder" FileSource="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion).0_Test\Dependencies\x64">
|
||||
<Component Id="Module_CmdPal_Deps" Win64="yes" Guid="C2790FC4-0665-4462-947A-D942A2AABFF0">
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="Module_CmdPal_Deps" Value="" KeyPath="yes"/>
|
||||
</RegistryKey>
|
||||
<File Source="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion).0_Test\Dependencies\x64\Microsoft.VCLibs.x64.14.00.Desktop.appx" />
|
||||
<File Source="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion).0_Test\Dependencies\x64\Microsoft.WindowsAppRuntime.1.6.msix" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
<?else ?>
|
||||
<DirectoryRef Id="CmdPalDepsArm64InstallFolder" FileSource="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion).0_Test\Dependencies\arm64">
|
||||
<Component Id="Module_CmdPal_Deps" Win64="yes" Guid="C2790FC4-0665-4462-947A-D942A2AABFF0">
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="Module_CmdPal_Deps" Value="" KeyPath="yes"/>
|
||||
</RegistryKey>
|
||||
<File Source="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion).0_Test\Dependencies\arm64\Microsoft.VCLibs.ARM64.14.00.Desktop.appx" />
|
||||
<File Source="$(var.CmdPalBuildDir)AppPackages\Microsoft.CmdPal.UI_$(var.CmdPalVersion).0_Test\Dependencies\arm64\Microsoft.WindowsAppRuntime.1.6.msix" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
<?endif ?>
|
||||
|
||||
<ComponentGroup Id="CmdPalComponentGroup">
|
||||
<Component Id="RemoveCmdPalFolder" Guid="2DF90C08-CC75-4245-A14E-B82904636C53" Directory="INSTALLFOLDER">
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="RemoveCmdPalFolder" Value="" KeyPath="yes"/>
|
||||
</RegistryKey>
|
||||
<RemoveFolder Id="RemoveCmdPalInstallDirFolder" Directory="CmdPalInstallFolder" On="uninstall"/>
|
||||
<RemoveFolder Id="RemoveCmdPalDepsInstallDirFolder" Directory="CmdPalDepsInstallFolder" On="uninstall"/>
|
||||
<?if $(sys.BUILDARCH) = x64 ?>
|
||||
<RemoveFolder Id="RemoveCmdPalDepsX64InstallDirFolder" Directory="CmdPalDepsX64InstallFolder" On="uninstall"/>
|
||||
<?else ?>
|
||||
<RemoveFolder Id="RemoveCmdPalDepsArm64InstallDirFolder" Directory="CmdPalDepsArm64InstallFolder" On="uninstall"/>
|
||||
<?endif ?>
|
||||
</Component>
|
||||
<ComponentRef Id="Module_CmdPal" />
|
||||
<ComponentRef Id="Module_CmdPal_Deps" />
|
||||
</ComponentGroup>
|
||||
|
||||
</Fragment>
|
||||
</Wix>
|
||||
@@ -17,6 +17,12 @@
|
||||
<PropertyGroup Label="UserMacros" Condition=" '$(PerUser)' != 'true' ">
|
||||
<DefineConstants>$(DefineConstants);PerUser=false</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="UserMacros" Condition=" '$(CIBuild)' == 'true' ">
|
||||
<DefineConstants>$(DefineConstants);CIBuild=true</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="UserMacros" Condition=" '$(CIBuild)' != 'true' ">
|
||||
<DefineConstants>$(DefineConstants);CIBuild=false</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform Condition="'$(Platform)'=='x64'">x64</Platform>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" InitialTargets="EnsureNuGetPackageBuildImports" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" InitialTargets="EnsureNuGetPackageBuildImports"
|
||||
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\src\Version.props" Condition="Exists('..\..\src\Version.props')" />
|
||||
<Import Project="..\..\src\CmdPalVersion.props" Condition="Exists('..\..\src\CmdPalVersion.props')" />
|
||||
<Import Project="..\wix.props" Condition="Exists('..\wix.props')" />
|
||||
<PropertyGroup Condition="'$(Platform)' == 'x64'">
|
||||
<DefineConstants>Version=$(Version);MonacoSRCHarvestPath=$(ProjectDir)..\..\x64\$(Configuration)\Assets\Monaco\monacoSRC</DefineConstants>
|
||||
<DefineConstants>Version=$(Version);MonacoSRCHarvestPath=$(ProjectDir)..\..\x64\$(Configuration)\Assets\Monaco\monacoSRC;CmdPalVersion=$(CmdPalVersion)</DefineConstants>
|
||||
<!-- THIS IS AN INNER LOOP OPTIMIZATION
|
||||
The build pipeline builds the Settings and Launcher projects for Publication
|
||||
using a specific profile. If you're doing local installer builds, this will
|
||||
@@ -17,7 +19,7 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
|
||||
</PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)' != 'x64'">
|
||||
<DefineConstants>Version=$(Version);MonacoSRCHarvestPath=$(ProjectDir)..\..\ARM64\$(Configuration)\Assets\Monaco\monacoSRC</DefineConstants>
|
||||
<DefineConstants>Version=$(Version);MonacoSRCHarvestPath=$(ProjectDir)..\..\ARM64\$(Configuration)\Assets\Monaco\monacoSRC;CmdPalVersion=$(CmdPalVersion);</DefineConstants>
|
||||
<PreBuildEvent>IF NOT DEFINED IsPipeline (
|
||||
call "$([MSBuild]::GetVsInstallRoot())\Common7\Tools\VsDevCmd.bat" -arch=arm64 -host_arch=amd64 -winsdk=10.0.19041.0 -vcvars_ver=$(VCToolsVersion)
|
||||
SET PTRoot=$(SolutionDir)\..
|
||||
@@ -32,6 +34,7 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
|
||||
call move /Y ..\..\..\AdvancedPaste.wxs.bk ..\..\..\AdvancedPaste.wxs
|
||||
call move /Y ..\..\..\Awake.wxs.bk ..\..\..\Awake.wxs
|
||||
call move /Y ..\..\..\BaseApplications.wxs.bk ..\..\..\BaseApplications.wxs
|
||||
call move /Y ..\..\..\CmdPal.wxs.bk ..\..\..\CmdPal.wxs
|
||||
call move /Y ..\..\..\ColorPicker.wxs.bk ..\..\..\ColorPicker.wxs
|
||||
call move /Y ..\..\..\Core.wxs.bk ..\..\..\Core.wxs
|
||||
call move /Y ..\..\..\EnvironmentVariables.wxs.bk ..\..\..\EnvironmentVariables.wxs
|
||||
@@ -54,7 +57,7 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
|
||||
call move /Y ..\..\..\WinAppSDK.wxs.bk ..\..\..\WinAppSDK.wxs
|
||||
call move /Y ..\..\..\WinUI3Applications.wxs.bk ..\..\..\WinUI3Applications.wxs
|
||||
call move /Y ..\..\..\Workspaces.wxs.bk ..\..\..\Workspaces.wxs
|
||||
</PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<Name>PowerToysInstaller</Name>
|
||||
@@ -65,6 +68,12 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
|
||||
<PropertyGroup Label="UserMacros" Condition=" '$(PerUser)' != 'true' ">
|
||||
<DefineConstants>$(DefineConstants);PerUser=false</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="UserMacros" Condition=" '$(CIBuild)' == 'true' ">
|
||||
<DefineConstants>$(DefineConstants);CIBuild=true</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="UserMacros" Condition=" '$(CIBuild)' != 'true' ">
|
||||
<DefineConstants>$(DefineConstants);CIBuild=false</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<!-- We do not support debug installer builds -->
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
|
||||
@@ -104,6 +113,7 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
|
||||
<Compile Include="AdvancedPaste.wxs" />
|
||||
<Compile Include="Awake.wxs" />
|
||||
<Compile Include="BaseApplications.wxs" />
|
||||
<Compile Include="CmdPal.wxs" />
|
||||
<Compile Include="ColorPicker.wxs" />
|
||||
<Compile Include="EnvironmentVariables.wxs" />
|
||||
<Compile Include="FileExplorerPreview.wxs" />
|
||||
@@ -188,4 +198,4 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
<Target Name="Restore" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -79,6 +79,10 @@
|
||||
<ComponentGroupRef Id="ToolComponentGroup" />
|
||||
<ComponentGroupRef Id="MonacoSRCHeatGenerated" />
|
||||
<ComponentGroupRef Id="WorkspacesComponentGroup" />
|
||||
|
||||
<?if $(var.CIBuild) = "true" ?>
|
||||
<ComponentGroupRef Id="CmdPalComponentGroup" />
|
||||
<?endif?>
|
||||
</Feature>
|
||||
|
||||
<SetProperty Id="ARPINSTALLLOCATION" Value="[INSTALLFOLDER]" After="CostFinalize" />
|
||||
@@ -135,6 +139,7 @@
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action="DetectPrevInstallPath" After="AppSearch" />
|
||||
<Custom Action="SetLaunchPowerToysParam" Before="LaunchPowerToys" />
|
||||
<Custom Action="SetInstallCmdPalPackageParam" Before="InstallCmdPalPackage" />
|
||||
<Custom Action="SetUninstallCommandNotFoundParam" Before="UninstallCommandNotFound" />
|
||||
<Custom Action="SetUpgradeCommandNotFoundParam" Before="UpgradeCommandNotFound" />
|
||||
<Custom Action="SetApplyModulesRegistryChangeSetsParam" Before="ApplyModulesRegistryChangeSets" />
|
||||
@@ -150,6 +155,9 @@
|
||||
<Custom Action="ApplyModulesRegistryChangeSets" After="InstallFiles">
|
||||
NOT Installed
|
||||
</Custom>
|
||||
<Custom Action="InstallCmdPalPackage" After="InstallFiles">
|
||||
NOT Installed
|
||||
</Custom>
|
||||
<Custom Action="WixCloseApplications" Before="RemoveFiles" />
|
||||
<Custom Action="RemovePowerToysSchTasks" After="RemoveFiles" />
|
||||
<!-- TODO: Use to activate embedded MSIX -->
|
||||
@@ -171,6 +179,9 @@
|
||||
<Custom Action="UnRegisterContextMenuPackages" Before="RemoveFiles">
|
||||
Installed AND (REMOVE="ALL")
|
||||
</Custom>
|
||||
<Custom Action="UnRegisterCmdPalPackage" Before="RemoveFiles">
|
||||
Installed AND (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")
|
||||
</Custom>
|
||||
<Custom Action="UnsetAdvancedPasteAPIKey" Before="RemoveFiles">
|
||||
Installed AND (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")
|
||||
</Custom>
|
||||
@@ -204,6 +215,10 @@
|
||||
Property="LaunchPowerToys"
|
||||
Value="[INSTALLFOLDER]" />
|
||||
|
||||
<CustomAction Id="SetInstallCmdPalPackageParam"
|
||||
Property="InstallCmdPalPackage"
|
||||
Value="[INSTALLFOLDER]" />
|
||||
|
||||
<CustomAction
|
||||
Id="LaunchPowerToys"
|
||||
Return="ignore"
|
||||
@@ -427,6 +442,14 @@
|
||||
DllEntry="UnRegisterContextMenuPackagesCA"
|
||||
/>
|
||||
|
||||
<CustomAction Id="UnRegisterCmdPalPackage"
|
||||
Return="ignore"
|
||||
Impersonate="yes"
|
||||
Execute="deferred"
|
||||
BinaryKey="PTCustomActions"
|
||||
DllEntry="UnRegisterCmdPalPackageCA"
|
||||
/>
|
||||
|
||||
<CustomAction Id="CheckGPO"
|
||||
Return="check"
|
||||
Impersonate="yes"
|
||||
@@ -434,6 +457,14 @@
|
||||
DllEntry="CheckGPOCA"
|
||||
/>
|
||||
|
||||
<CustomAction Id="InstallCmdPalPackage"
|
||||
Return="ignore"
|
||||
Impersonate="yes"
|
||||
Execute="deferred"
|
||||
BinaryKey="PTCustomActions"
|
||||
DllEntry="InstallCmdPalPackageCA"
|
||||
/>
|
||||
|
||||
<!-- Close 'PowerToys.exe' before uninstall-->
|
||||
<Property Id="MSIRESTARTMANAGERCONTROL" Value="DisableShutdown" />
|
||||
<Property Id="MSIFASTINSTALL" Value="DisableShutdown" />
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "../../src/common/updating/installer.h"
|
||||
#include "../../src/common/version/version.h"
|
||||
#include "../../src/common/Telemetry/EtwTrace/EtwTrace.h"
|
||||
#include "../../src/common/utils/package.h"
|
||||
#include "../../src/common/utils/clean_video_conference.h"
|
||||
|
||||
#include <winrt/Windows.ApplicationModel.h>
|
||||
@@ -35,13 +36,13 @@ TRACELOGGING_DEFINE_PROVIDER(
|
||||
TraceLoggingOptionProjectTelemetry());
|
||||
|
||||
const DWORD USERNAME_DOMAIN_LEN = DNLEN + UNLEN + 2; // Domain Name + '\' + User Name + '\0'
|
||||
const DWORD USERNAME_LEN = UNLEN + 1; // User Name + '\0'
|
||||
const DWORD USERNAME_LEN = UNLEN + 1; // User Name + '\0'
|
||||
|
||||
static const wchar_t* POWERTOYS_EXE_COMPONENT = L"{A2C66D91-3485-4D00-B04D-91844E6B345B}";
|
||||
static const wchar_t* POWERTOYS_UPGRADE_CODE = L"{42B84BF7-5FBF-473B-9C8B-049DC16F7708}";
|
||||
static const wchar_t *POWERTOYS_EXE_COMPONENT = L"{A2C66D91-3485-4D00-B04D-91844E6B345B}";
|
||||
static const wchar_t *POWERTOYS_UPGRADE_CODE = L"{42B84BF7-5FBF-473B-9C8B-049DC16F7708}";
|
||||
|
||||
constexpr inline const wchar_t* DataDiagnosticsRegKey = L"Software\\Classes\\PowerToys";
|
||||
constexpr inline const wchar_t* DataDiagnosticsRegValueName = L"AllowDataDiagnostics";
|
||||
constexpr inline const wchar_t *DataDiagnosticsRegKey = L"Software\\Classes\\PowerToys";
|
||||
constexpr inline const wchar_t *DataDiagnosticsRegValueName = L"AllowDataDiagnostics";
|
||||
|
||||
#define TraceLoggingWriteWrapper(provider, eventName, ...) \
|
||||
if (isDataDiagnosticEnabled()) \
|
||||
@@ -52,16 +53,16 @@ constexpr inline const wchar_t* DataDiagnosticsRegValueName = L"AllowDataDiagnos
|
||||
trace.UpdateState(false); \
|
||||
}
|
||||
|
||||
static Shared::Trace::ETWTrace trace{ L"PowerToys_Installer" };
|
||||
static Shared::Trace::ETWTrace trace{L"PowerToys_Installer"};
|
||||
|
||||
inline bool isDataDiagnosticEnabled()
|
||||
{
|
||||
HKEY key{};
|
||||
if (RegOpenKeyExW(HKEY_CURRENT_USER,
|
||||
DataDiagnosticsRegKey,
|
||||
0,
|
||||
KEY_READ,
|
||||
&key) != ERROR_SUCCESS)
|
||||
DataDiagnosticsRegKey,
|
||||
0,
|
||||
KEY_READ,
|
||||
&key) != ERROR_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -86,8 +87,7 @@ inline bool isDataDiagnosticEnabled()
|
||||
return isDataDiagnosticsEnabled == 1;
|
||||
}
|
||||
|
||||
|
||||
HRESULT getInstallFolder(MSIHANDLE hInstall, std::wstring& installationDir)
|
||||
HRESULT getInstallFolder(MSIHANDLE hInstall, std::wstring &installationDir)
|
||||
{
|
||||
DWORD len = 0;
|
||||
wchar_t _[1];
|
||||
@@ -116,13 +116,13 @@ BOOL IsLocalSystem()
|
||||
|
||||
// open process token
|
||||
if (!OpenProcessToken(GetCurrentProcess(),
|
||||
TOKEN_QUERY,
|
||||
&hToken))
|
||||
TOKEN_QUERY,
|
||||
&hToken))
|
||||
return FALSE;
|
||||
|
||||
// retrieve user SID
|
||||
if (!GetTokenInformation(hToken, TokenUser, pTokenUser,
|
||||
sizeof(bTokenUser), &cbTokenUser))
|
||||
sizeof(bTokenUser), &cbTokenUser))
|
||||
{
|
||||
CloseHandle(hToken);
|
||||
return FALSE;
|
||||
@@ -132,7 +132,7 @@ BOOL IsLocalSystem()
|
||||
|
||||
// allocate LocalSystem well-known SID
|
||||
if (!AllocateAndInitializeSid(&siaNT, 1, SECURITY_LOCAL_SYSTEM_RID,
|
||||
0, 0, 0, 0, 0, 0, 0, &pSystemSid))
|
||||
0, 0, 0, 0, 0, 0, 0, &pSystemSid))
|
||||
return FALSE;
|
||||
|
||||
// compare the user SID from the token with the LocalSystem SID
|
||||
@@ -194,7 +194,7 @@ static std::filesystem::path GetUserPowerShellModulesPath()
|
||||
|
||||
if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &myDocumentsBlockPtr)))
|
||||
{
|
||||
const std::wstring myDocuments{ myDocumentsBlockPtr };
|
||||
const std::wstring myDocuments{myDocumentsBlockPtr};
|
||||
CoTaskMemFree(myDocumentsBlockPtr);
|
||||
return std::filesystem::path(myDocuments) / "PowerShell" / "Modules";
|
||||
}
|
||||
@@ -227,10 +227,12 @@ UINT __stdcall LaunchPowerToysCA(MSIHANDLE hInstall)
|
||||
|
||||
BOOL isSystemUser = IsLocalSystem();
|
||||
|
||||
if (isSystemUser) {
|
||||
if (isSystemUser)
|
||||
{
|
||||
|
||||
auto action = [&commandLine](HANDLE userToken) {
|
||||
STARTUPINFO startupInfo{ .cb = sizeof(STARTUPINFO), .wShowWindow = SW_SHOWNORMAL };
|
||||
auto action = [&commandLine](HANDLE userToken)
|
||||
{
|
||||
STARTUPINFO startupInfo{.cb = sizeof(STARTUPINFO), .wShowWindow = SW_SHOWNORMAL};
|
||||
PROCESS_INFORMATION processInformation;
|
||||
|
||||
PVOID lpEnvironment = NULL;
|
||||
@@ -269,7 +271,7 @@ UINT __stdcall LaunchPowerToysCA(MSIHANDLE hInstall)
|
||||
}
|
||||
else
|
||||
{
|
||||
STARTUPINFO startupInfo{ .cb = sizeof(STARTUPINFO), .wShowWindow = SW_SHOWNORMAL };
|
||||
STARTUPINFO startupInfo{.cb = sizeof(STARTUPINFO), .wShowWindow = SW_SHOWNORMAL};
|
||||
|
||||
PROCESS_INFORMATION processInformation;
|
||||
|
||||
@@ -313,7 +315,7 @@ UINT __stdcall CheckGPOCA(MSIHANDLE hInstall)
|
||||
LPWSTR currentScope = nullptr;
|
||||
hr = WcaGetProperty(L"InstallScope", ¤tScope);
|
||||
|
||||
if (std::wstring{ currentScope } == L"perUser")
|
||||
if (std::wstring{currentScope} == L"perUser")
|
||||
{
|
||||
if (powertoys_gpo::getDisablePerUserInstallationValue() == powertoys_gpo::gpo_rule_configured_enabled)
|
||||
{
|
||||
@@ -354,7 +356,7 @@ UINT __stdcall ApplyModulesRegistryChangeSetsCA(MSIHANDLE hInstall)
|
||||
hr = getInstallFolder(hInstall, installationFolder);
|
||||
ExitOnFailure(hr, "Failed to get installFolder.");
|
||||
|
||||
for (const auto& changeSet : getAllOnByDefaultModulesChangeSets(installationFolder))
|
||||
for (const auto &changeSet : getAllOnByDefaultModulesChangeSets(installationFolder))
|
||||
{
|
||||
if (!changeSet.apply())
|
||||
{
|
||||
@@ -382,7 +384,7 @@ UINT __stdcall UnApplyModulesRegistryChangeSetsCA(MSIHANDLE hInstall)
|
||||
ExitOnFailure(hr, "Failed to initialize");
|
||||
hr = getInstallFolder(hInstall, installationFolder);
|
||||
ExitOnFailure(hr, "Failed to get installFolder.");
|
||||
for (const auto& changeSet : getAllModulesChangeSets(installationFolder))
|
||||
for (const auto &changeSet : getAllModulesChangeSets(installationFolder))
|
||||
{
|
||||
changeSet.unApply();
|
||||
}
|
||||
@@ -396,8 +398,8 @@ LExit:
|
||||
return WcaFinalize(er);
|
||||
}
|
||||
|
||||
const wchar_t* DSC_CONFIGURE_PSD1_NAME = L"Microsoft.PowerToys.Configure.psd1";
|
||||
const wchar_t* DSC_CONFIGURE_PSM1_NAME = L"Microsoft.PowerToys.Configure.psm1";
|
||||
const wchar_t *DSC_CONFIGURE_PSD1_NAME = L"Microsoft.PowerToys.Configure.psd1";
|
||||
const wchar_t *DSC_CONFIGURE_PSM1_NAME = L"Microsoft.PowerToys.Configure.psm1";
|
||||
|
||||
UINT __stdcall InstallDSCModuleCA(MSIHANDLE hInstall)
|
||||
{
|
||||
@@ -429,7 +431,7 @@ UINT __stdcall InstallDSCModuleCA(MSIHANDLE hInstall)
|
||||
ExitOnFailure(hr, "Unable to create Powershell modules folder");
|
||||
}
|
||||
|
||||
for (const auto* filename : { DSC_CONFIGURE_PSD1_NAME, DSC_CONFIGURE_PSM1_NAME })
|
||||
for (const auto *filename : {DSC_CONFIGURE_PSD1_NAME, DSC_CONFIGURE_PSM1_NAME})
|
||||
{
|
||||
fs::copy_file(fs::path(installationFolder) / "DSCModules" / filename, modulesPath / filename, fs::copy_options::overwrite_existing, errorCode);
|
||||
|
||||
@@ -477,7 +479,7 @@ UINT __stdcall UninstallDSCModuleCA(MSIHANDLE hInstall)
|
||||
|
||||
std::error_code errorCode;
|
||||
|
||||
for (const auto* filename : { DSC_CONFIGURE_PSD1_NAME, DSC_CONFIGURE_PSM1_NAME })
|
||||
for (const auto *filename : {DSC_CONFIGURE_PSD1_NAME, DSC_CONFIGURE_PSM1_NAME})
|
||||
{
|
||||
fs::remove(versionedModulePath / filename, errorCode);
|
||||
|
||||
@@ -488,7 +490,7 @@ UINT __stdcall UninstallDSCModuleCA(MSIHANDLE hInstall)
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto* modulePath : { &versionedModulePath, &powerToysModulePath })
|
||||
for (const auto *modulePath : {&versionedModulePath, &powerToysModulePath})
|
||||
{
|
||||
fs::remove(*modulePath, errorCode);
|
||||
|
||||
@@ -535,7 +537,7 @@ UINT __stdcall InstallEmbeddedMSIXCA(MSIHANDLE hInstall)
|
||||
using namespace winrt::Windows::Management::Deployment;
|
||||
using namespace winrt::Windows::Foundation;
|
||||
|
||||
Uri msix_uri{ msix_path.wstring() };
|
||||
Uri msix_uri{msix_path.wstring()};
|
||||
PackageManager pm;
|
||||
auto result = pm.AddPackageAsync(msix_uri, nullptr, DeploymentOptions::None).get();
|
||||
if (!result)
|
||||
@@ -569,7 +571,7 @@ UINT __stdcall UninstallEmbeddedMSIXCA(MSIHANDLE hInstall)
|
||||
hr = WcaInitialize(hInstall, "UninstallEmbeddedMSIXCA");
|
||||
ExitOnFailure(hr, "Failed to initialize");
|
||||
|
||||
for (const auto& p : pm.FindPackagesForUser({}, package_name, publisher))
|
||||
for (const auto &p : pm.FindPackagesForUser({}, package_name, publisher))
|
||||
{
|
||||
auto result = pm.RemovePackageAsync(p.Id().FullName()).get();
|
||||
if (result)
|
||||
@@ -683,7 +685,6 @@ UINT __stdcall UninstallCommandNotFoundModuleCA(MSIHANDLE hInstall)
|
||||
command += "-NoProfile -NonInteractive -NoLogo -WindowStyle Hidden -ExecutionPolicy Unrestricted -File \"" + winrt::to_string(installationFolder) + "\\WinUI3Apps\\Assets\\Settings\\Scripts\\DisableModule.ps1" + "\"";
|
||||
#endif
|
||||
|
||||
|
||||
system(command.c_str());
|
||||
|
||||
LExit:
|
||||
@@ -738,10 +739,10 @@ UINT __stdcall RemoveScheduledTasksCA(MSIHANDLE hInstall)
|
||||
HRESULT hr = S_OK;
|
||||
UINT er = ERROR_SUCCESS;
|
||||
|
||||
ITaskService* pService = nullptr;
|
||||
ITaskFolder* pTaskFolder = nullptr;
|
||||
IRegisteredTaskCollection* pTaskCollection = nullptr;
|
||||
ITaskFolder* pRootFolder = nullptr;
|
||||
ITaskService *pService = nullptr;
|
||||
ITaskFolder *pTaskFolder = nullptr;
|
||||
IRegisteredTaskCollection *pTaskCollection = nullptr;
|
||||
ITaskFolder *pRootFolder = nullptr;
|
||||
LONG numTasks = 0;
|
||||
|
||||
hr = WcaInitialize(hInstall, "RemoveScheduledTasksCA");
|
||||
@@ -754,10 +755,10 @@ UINT __stdcall RemoveScheduledTasksCA(MSIHANDLE hInstall)
|
||||
// ------------------------------------------------------
|
||||
// Create an instance of the Task Service.
|
||||
hr = CoCreateInstance(CLSID_TaskScheduler,
|
||||
nullptr,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_ITaskService,
|
||||
reinterpret_cast<void**>(&pService));
|
||||
nullptr,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_ITaskService,
|
||||
reinterpret_cast<void **>(&pService));
|
||||
ExitOnFailure(hr, "Failed to create an instance of ITaskService: %x", hr);
|
||||
|
||||
// Connect to the task service.
|
||||
@@ -785,7 +786,7 @@ UINT __stdcall RemoveScheduledTasksCA(MSIHANDLE hInstall)
|
||||
{
|
||||
// Delete all the tasks found.
|
||||
// If some tasks can't be deleted, the folder won't be deleted later and the user will still be notified.
|
||||
IRegisteredTask* pRegisteredTask = nullptr;
|
||||
IRegisteredTask *pRegisteredTask = nullptr;
|
||||
hr = pTaskCollection->get_Item(_variant_t(i + 1), &pRegisteredTask);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
@@ -861,8 +862,7 @@ UINT __stdcall TelemetryLogInstallSuccessCA(MSIHANDLE hInstall)
|
||||
TraceLoggingWideString(get_product_version().c_str(), "Version"),
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)
|
||||
);
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
|
||||
|
||||
LExit:
|
||||
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
|
||||
@@ -1028,7 +1028,7 @@ UINT __stdcall DetectPrevInstallPathCA(MSIHANDLE hInstall)
|
||||
|
||||
try
|
||||
{
|
||||
if (auto install_path = GetMsiPackageInstalledPath(std::wstring{ currentScope } == L"perUser"))
|
||||
if (auto install_path = GetMsiPackageInstalledPath(std::wstring{currentScope} == L"perUser"))
|
||||
{
|
||||
MsiSetPropertyW(hInstall, L"PREVIOUSINSTALLFOLDER", install_path->data());
|
||||
}
|
||||
@@ -1040,6 +1040,82 @@ UINT __stdcall DetectPrevInstallPathCA(MSIHANDLE hInstall)
|
||||
return WcaFinalize(er);
|
||||
}
|
||||
|
||||
UINT __stdcall InstallCmdPalPackageCA(MSIHANDLE hInstall)
|
||||
{
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::Management::Deployment;
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
UINT er = ERROR_SUCCESS;
|
||||
std::wstring installationFolder;
|
||||
|
||||
hr = WcaInitialize(hInstall, "InstallCmdPalPackage");
|
||||
hr = getInstallFolder(hInstall, installationFolder);
|
||||
|
||||
try
|
||||
{
|
||||
auto msix = package::FindMsixFile(installationFolder + L"\\WinUI3Apps\\CmdPal\\", false);
|
||||
auto dependencies = package::FindMsixFile(installationFolder + L"\\WinUI3Apps\\CmdPal\\Dependencies\\", true);
|
||||
|
||||
if (!msix.empty())
|
||||
{
|
||||
auto msixPath = msix[0];
|
||||
|
||||
if (!package::RegisterPackage(msixPath, dependencies))
|
||||
{
|
||||
Logger::error(L"Failed to install CmdPal package");
|
||||
er = ERROR_INSTALL_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
std::string errorMessage{"Exception thrown while trying to install CmdPal package: "};
|
||||
errorMessage += e.what();
|
||||
Logger::error(errorMessage);
|
||||
|
||||
er = ERROR_INSTALL_FAILURE;
|
||||
}
|
||||
|
||||
er = er == ERROR_SUCCESS ? (SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE) : er;
|
||||
return WcaFinalize(er);
|
||||
}
|
||||
|
||||
UINT __stdcall UnRegisterCmdPalPackageCA(MSIHANDLE hInstall)
|
||||
{
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::Management::Deployment;
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
UINT er = ERROR_SUCCESS;
|
||||
|
||||
hr = WcaInitialize(hInstall, "UnRegisterCmdPalPackageCA");
|
||||
|
||||
try
|
||||
{
|
||||
// Packages to unregister
|
||||
std::wstring packageToRemoveDisplayName {L"Microsoft.CommandPalette"};
|
||||
|
||||
if (!package::UnRegisterPackage(packageToRemoveDisplayName))
|
||||
{
|
||||
Logger::error(L"Failed to unregister package: " + packageToRemoveDisplayName);
|
||||
er = ERROR_INSTALL_FAILURE;
|
||||
}
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
std::string errorMessage{"Exception thrown while trying to unregister the CmdPal package: "};
|
||||
errorMessage += e.what();
|
||||
Logger::error(errorMessage);
|
||||
|
||||
er = ERROR_INSTALL_FAILURE;
|
||||
}
|
||||
|
||||
er = er == ERROR_SUCCESS ? (SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE) : er;
|
||||
return WcaFinalize(er);
|
||||
}
|
||||
|
||||
|
||||
UINT __stdcall UnRegisterContextMenuPackagesCA(MSIHANDLE hInstall)
|
||||
{
|
||||
using namespace winrt::Windows::Foundation;
|
||||
@@ -1053,54 +1129,20 @@ UINT __stdcall UnRegisterContextMenuPackagesCA(MSIHANDLE hInstall)
|
||||
try
|
||||
{
|
||||
// Packages to unregister
|
||||
const std::vector<std::wstring> packagesToRemoveDisplayName{ { L"PowerRenameContextMenu" }, { L"ImageResizerContextMenu" }, { L"FileLocksmithContextMenu" }, { L"NewPlusContextMenu" } };
|
||||
const std::vector<std::wstring> packagesToRemoveDisplayName{{L"PowerRenameContextMenu"}, {L"ImageResizerContextMenu"}, {L"FileLocksmithContextMenu"}, {L"NewPlusContextMenu"}};
|
||||
|
||||
PackageManager packageManager;
|
||||
|
||||
for (auto const& package : packageManager.FindPackages())
|
||||
for (auto const &package : packagesToRemoveDisplayName)
|
||||
{
|
||||
const auto& packageFullName = std::wstring{ package.Id().FullName() };
|
||||
|
||||
for (const auto& packageToRemove : packagesToRemoveDisplayName)
|
||||
if (!package::UnRegisterPackage(package))
|
||||
{
|
||||
if (packageFullName.contains(packageToRemove))
|
||||
{
|
||||
auto deploymentOperation{ packageManager.RemovePackageAsync(packageFullName) };
|
||||
deploymentOperation.get();
|
||||
|
||||
// Check the status of the operation
|
||||
if (deploymentOperation.Status() == AsyncStatus::Error)
|
||||
{
|
||||
auto deploymentResult{ deploymentOperation.GetResults() };
|
||||
auto errorCode = deploymentOperation.ErrorCode();
|
||||
auto errorText = deploymentResult.ErrorText();
|
||||
|
||||
Logger::error(L"Unregister {} package failed. ErrorCode: {}, ErrorText: {}", packageFullName, std::to_wstring(errorCode), errorText);
|
||||
|
||||
er = ERROR_INSTALL_FAILURE;
|
||||
}
|
||||
else if (deploymentOperation.Status() == AsyncStatus::Canceled)
|
||||
{
|
||||
Logger::error(L"Unregister {} package canceled.", packageFullName);
|
||||
|
||||
er = ERROR_INSTALL_FAILURE;
|
||||
}
|
||||
else if (deploymentOperation.Status() == AsyncStatus::Completed)
|
||||
{
|
||||
Logger::info(L"Unregister {} package completed.", packageFullName);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::debug(L"Unregister {} package started.", packageFullName);
|
||||
}
|
||||
}
|
||||
|
||||
Logger::error(L"Failed to unregister package: " + package);
|
||||
er = ERROR_INSTALL_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
catch (std::exception &e)
|
||||
{
|
||||
std::string errorMessage{ "Exception thrown while trying to unregister sparse packages: " };
|
||||
std::string errorMessage{"Exception thrown while trying to unregister sparse packages: "};
|
||||
errorMessage += e.what();
|
||||
Logger::error(errorMessage);
|
||||
|
||||
@@ -1128,7 +1170,7 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
|
||||
}
|
||||
processes.resize(bytes / sizeof(processes[0]));
|
||||
|
||||
std::array<std::wstring_view, 38> processesToTerminate = {
|
||||
std::array<std::wstring_view, 39> processesToTerminate = {
|
||||
L"PowerToys.PowerLauncher.exe",
|
||||
L"PowerToys.Settings.exe",
|
||||
L"PowerToys.AdvancedPaste.exe",
|
||||
@@ -1165,6 +1207,7 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
|
||||
L"PowerToys.WorkspacesLauncherUI.exe",
|
||||
L"PowerToys.WorkspacesEditor.exe",
|
||||
L"PowerToys.WorkspacesWindowArranger.exe",
|
||||
L"Microsoft.CmdPal.UI.exe",
|
||||
L"PowerToys.ZoomIt.exe",
|
||||
L"PowerToys.exe",
|
||||
};
|
||||
@@ -1177,7 +1220,7 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
|
||||
}
|
||||
wchar_t processName[MAX_PATH] = L"<unknown>";
|
||||
|
||||
HANDLE hProcess{ OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE, FALSE, procID) };
|
||||
HANDLE hProcess{OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE, FALSE, procID)};
|
||||
if (!hProcess)
|
||||
{
|
||||
continue;
|
||||
@@ -1197,8 +1240,9 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
|
||||
if (processName == processToTerminate)
|
||||
{
|
||||
const DWORD timeout = 500;
|
||||
auto windowEnumerator = [](HWND hwnd, LPARAM procIDPtr) -> BOOL {
|
||||
auto targetProcID = *reinterpret_cast<const DWORD*>(procIDPtr);
|
||||
auto windowEnumerator = [](HWND hwnd, LPARAM procIDPtr) -> BOOL
|
||||
{
|
||||
auto targetProcID = *reinterpret_cast<const DWORD *>(procIDPtr);
|
||||
DWORD windowProcID = 0;
|
||||
GetWindowThreadProcessId(hwnd, &windowProcID);
|
||||
if (windowProcID == targetProcID)
|
||||
@@ -1224,15 +1268,15 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
|
||||
void initSystemLogger()
|
||||
{
|
||||
static std::once_flag initLoggerFlag;
|
||||
std::call_once(initLoggerFlag, []() {
|
||||
WCHAR temp_path[MAX_PATH];
|
||||
auto ret = GetTempPath(MAX_PATH, temp_path);
|
||||
std::call_once(initLoggerFlag, []()
|
||||
{
|
||||
WCHAR temp_path[MAX_PATH];
|
||||
auto ret = GetTempPath(MAX_PATH, temp_path);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
Logger::init("PowerToysMSI", std::wstring{ temp_path } + L"\\PowerToysMSIInstaller", L"");
|
||||
}
|
||||
});
|
||||
if (ret)
|
||||
{
|
||||
Logger::init("PowerToysMSI", std::wstring{ temp_path } + L"\\PowerToysMSIInstaller", L"");
|
||||
} });
|
||||
}
|
||||
|
||||
// DllMain - Initialize and cleanup WiX custom action utils.
|
||||
|
||||
@@ -18,7 +18,9 @@ EXPORTS
|
||||
TerminateProcessesCA
|
||||
InstallEmbeddedMSIXCA
|
||||
InstallDSCModuleCA
|
||||
InstallCmdPalPackageCA
|
||||
UnApplyModulesRegistryChangeSetsCA
|
||||
UnRegisterCmdPalPackageCA
|
||||
UnRegisterContextMenuPackagesCA
|
||||
UninstallEmbeddedMSIXCA
|
||||
UninstallDSCModuleCA
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build"
|
||||
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<Import Project="..\wix.props" Condition="Exists('..\wix.props')" />
|
||||
<PropertyGroup Label="Globals">
|
||||
@@ -54,6 +55,7 @@
|
||||
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\AdvancedPaste.wxs"" ""$(ProjectDir)..\PowerToysSetup\AdvancedPaste.wxs.bk""""
|
||||
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\Awake.wxs"" ""$(ProjectDir)..\PowerToysSetup\Awake.wxs.bk""""
|
||||
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\BaseApplications.wxs"" ""$(ProjectDir)..\PowerToysSetup\BaseApplications.wxs.bk""""
|
||||
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\CmdPal.wxs"" ""$(ProjectDir)..\PowerToysSetup\CmdPal.wxs.bk""""
|
||||
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\ColorPicker.wxs"" ""$(ProjectDir)..\PowerToysSetup\ColorPicker.wxs.bk""""
|
||||
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\Core.wxs"" ""$(ProjectDir)..\PowerToysSetup\Core.wxs.bk""""
|
||||
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\EnvironmentVariables.wxs"" ""$(ProjectDir)..\PowerToysSetup\EnvironmentVariables.wxs.bk""""
|
||||
|
||||
10
src/CmdPalVersion.props
Normal file
10
src/CmdPalVersion.props
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<CmdPalVersion>0.0.1</CmdPalVersion>
|
||||
<DevEnvironment>Local</DevEnvironment>
|
||||
|
||||
<!-- Forcing for every DLL on by default -->
|
||||
<ChecksumAlgorithm>SHA256</ChecksumAlgorithm>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -5,5 +5,8 @@
|
||||
<IsAotCompatible>true</IsAotCompatible>
|
||||
<CsWinRTAotOptimizerEnabled>true</CsWinRTAotOptimizerEnabled>
|
||||
<CsWinRTAotWarningLevel>2</CsWinRTAotWarningLevel>
|
||||
|
||||
<!-- Suppress DynamicallyAccessedMemberTypes.PublicParameterlessConstructor in fallback code path of Windows SDK projection -->
|
||||
<WarningsNotAsErrors>IL2081</WarningsNotAsErrors>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<!-- Some items may be set in Directory.Build.props in root -->
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<WindowsSdkPackageVersion>10.0.22621.48</WindowsSdkPackageVersion>
|
||||
<WindowsSdkPackageVersion>10.0.22621.57</WindowsSdkPackageVersion>
|
||||
<TargetFramework>net9.0-windows10.0.22621.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
@@ -14,7 +14,7 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<NoWarn></NoWarn>
|
||||
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
|
||||
<WarningsNotAsErrors>CA1720;CA1859;CA2263;CA2022</WarningsNotAsErrors>
|
||||
<WarningsNotAsErrors>CA1720;CA1859;CA2263;CA2022;MVVMTK0045;MVVMTK0049</WarningsNotAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
|
||||
|
||||
@@ -12,10 +12,10 @@ using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1101:PrefixLocalCallsWithThis", Justification = "We follow the C# Core Coding Style which avoids using `this` unless absolutely necessary.")]
|
||||
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1201:ElementsMustAppearInTheCorrectOrder", Justification = "It is not a priority and have hight impact in code changes.")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:ElementsMustBeOrderedByAccess", Justification = "It is not a priority and have hight impact in code changes.")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1203:ConstantsMustAppearBeforeFields", Justification = "It is not a priority and have hight impact in code changes.")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1204:StaticElementsMustAppearBeforeInstanceElements", Justification = "It is not a priority and have hight impact in code changes.")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1201:ElementsMustAppearInTheCorrectOrder", Justification = "It is not a priority and has high impact in code changes.")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:ElementsMustBeOrderedByAccess", Justification = "It is not a priority and has high impact in code changes.")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1203:ConstantsMustAppearBeforeFields", Justification = "It is not a priority and has high impact in code changes.")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1204:StaticElementsMustAppearBeforeInstanceElements", Justification = "It is not a priority and has high impact in code changes.")]
|
||||
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1309:FieldNamesMustNotBeginWithUnderscore", Justification = "We follow the C# Core Coding Style which uses underscores as prefixes rather than using `this.`.")]
|
||||
|
||||
@@ -62,3 +62,9 @@ using System.Diagnostics.CodeAnalysis;
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "<Dotnet port with style preservation>", Scope = "namespaceanddescendants", Target = "MouseWithoutBorders")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "<Dotnet port with style preservation>", Scope = "namespaceanddescendants", Target = "MouseWithoutBorders")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1649:File name should match first type name", Justification = "<Dotnet port with style preservation>", Scope = "namespaceanddescendants", Target = "MouseWithoutBorders")]
|
||||
|
||||
// AOT
|
||||
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0045:Using [ObservableProperty] on fields is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "HostsUILib")]
|
||||
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0045:Using [ObservableProperty] on fields is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "Peek.UI")]
|
||||
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0045:Using [ObservableProperty] on fields is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "Peek.UI.Views")]
|
||||
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.INotifyPropertyChangedGenerator", "MVVMTK0049:Using [INotifyPropertyChanged] is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "type", Target = "~T:Peek.UI.Views.TitleBar")]
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace Common.UI
|
||||
Dashboard,
|
||||
AdvancedPaste,
|
||||
Workspaces,
|
||||
CmdPal,
|
||||
ZoomIt,
|
||||
}
|
||||
|
||||
@@ -78,6 +79,8 @@ namespace Common.UI
|
||||
return "AdvancedPaste";
|
||||
case SettingsWindow.Workspaces:
|
||||
return "Workspaces";
|
||||
case SettingsWindow.CmdPal:
|
||||
return "CmdPal";
|
||||
case SettingsWindow.ZoomIt:
|
||||
return "ZoomIt";
|
||||
default:
|
||||
|
||||
@@ -16,6 +16,10 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredCmdNotFoundEnabledValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredCmdPalEnabledValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredCmdPalEnabledValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredColorPickerEnabledValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredColorPickerEnabledValue());
|
||||
@@ -232,6 +236,10 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getAllowDataDiagnosticsValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredNewPlusReplaceVariablesValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredNewPlusReplaceVariablesValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredRunAtStartupValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredRunAtStartupValue());
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
static GpoRuleConfigured GetConfiguredAlwaysOnTopEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredAwakeEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredCmdNotFoundEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredCmdPalEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredColorPickerEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredCropAndLockEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredFancyZonesEnabledValue();
|
||||
@@ -64,6 +65,7 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
static GpoRuleConfigured GetConfiguredNewPlusHideTemplateFilenameExtensionValue();
|
||||
static GpoRuleConfigured GetAllowDataDiagnosticsValue();
|
||||
static GpoRuleConfigured GetConfiguredRunAtStartupValue();
|
||||
static GpoRuleConfigured GetConfiguredNewPlusReplaceVariablesValue();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace PowerToys
|
||||
static GpoRuleConfigured GetConfiguredAlwaysOnTopEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredAwakeEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredCmdNotFoundEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredCmdPalEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredColorPickerEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredCropAndLockEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredFancyZonesEnabledValue();
|
||||
@@ -68,6 +69,7 @@ namespace PowerToys
|
||||
static GpoRuleConfigured GetConfiguredNewPlusHideTemplateFilenameExtensionValue();
|
||||
static GpoRuleConfigured GetAllowDataDiagnosticsValue();
|
||||
static GpoRuleConfigured GetConfiguredRunAtStartupValue();
|
||||
static GpoRuleConfigured GetConfiguredNewPlusReplaceVariablesValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace ManagedCommon
|
||||
AlwaysOnTop,
|
||||
Awake,
|
||||
ColorPicker,
|
||||
CmdPal,
|
||||
CropAndLock,
|
||||
EnvironmentVariables,
|
||||
FancyZones,
|
||||
|
||||
@@ -9,5 +9,14 @@ namespace Microsoft.PowerToys.UITest
|
||||
/// </summary>
|
||||
public class Button : Element
|
||||
{
|
||||
private static readonly string ExpectedControlType = "ControlType.Button";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Button"/> class.
|
||||
/// </summary>
|
||||
public Button()
|
||||
{
|
||||
this.TargetControlType = Button.ExpectedControlType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,17 +11,40 @@ namespace Microsoft.PowerToys.UITest
|
||||
/// </summary>
|
||||
public class By
|
||||
{
|
||||
private readonly OpenQA.Selenium.By by;
|
||||
private readonly OpenQA.Selenium.By? by;
|
||||
private readonly bool isAccessibilityId;
|
||||
private readonly string? accessibilityId;
|
||||
|
||||
private By(OpenQA.Selenium.By by)
|
||||
{
|
||||
isAccessibilityId = false;
|
||||
this.by = by;
|
||||
}
|
||||
|
||||
private By(string accessibilityId)
|
||||
{
|
||||
isAccessibilityId = true;
|
||||
this.accessibilityId = accessibilityId;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
// override ToString to return detailed debugging content provided by OpenQA.Selenium.By
|
||||
return this.by.ToString();
|
||||
return this.GetAccessibilityId();
|
||||
}
|
||||
|
||||
public bool GetIsAccessibilityId() => this.isAccessibilityId;
|
||||
|
||||
public string GetAccessibilityId()
|
||||
{
|
||||
if (this.isAccessibilityId)
|
||||
{
|
||||
return this.accessibilityId!;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.by!.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -31,6 +54,13 @@ namespace Microsoft.PowerToys.UITest
|
||||
/// <returns>A By object.</returns>
|
||||
public static By Name(string name) => new By(OpenQA.Selenium.By.Name(name));
|
||||
|
||||
/// <summary>
|
||||
/// Creates a By object using the className attribute.
|
||||
/// </summary>
|
||||
/// <param name="className">The className attribute to search for.</param>
|
||||
/// <returns>A By object.</returns>
|
||||
public static By ClassName(string className) => new By(OpenQA.Selenium.By.ClassName(className));
|
||||
|
||||
/// <summary>
|
||||
/// Creates a By object using the ID attribute.
|
||||
/// </summary>
|
||||
@@ -38,6 +68,13 @@ namespace Microsoft.PowerToys.UITest
|
||||
/// <returns>A By object.</returns>
|
||||
public static By Id(string id) => new By(OpenQA.Selenium.By.Id(id));
|
||||
|
||||
/// <summary>
|
||||
/// Creates a By object using the ID attribute.
|
||||
/// </summary>
|
||||
/// <param name="accessibilityId">The ID attribute to search for.</param>
|
||||
/// <returns>A By object.</returns>
|
||||
public static By AccessibilityId(string accessibilityId) => new By(accessibilityId);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a By object using the XPath expression.
|
||||
/// </summary>
|
||||
@@ -70,6 +107,6 @@ namespace Microsoft.PowerToys.UITest
|
||||
/// Converts the By object to an OpenQA.Selenium.By object.
|
||||
/// </summary>
|
||||
/// <returns>An OpenQA.Selenium.By object.</returns>
|
||||
internal OpenQA.Selenium.By ToSeleniumBy() => by;
|
||||
internal OpenQA.Selenium.By ToSeleniumBy() => by!;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,13 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Drawing;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Xml.Linq;
|
||||
using ABI.Windows.Foundation;
|
||||
using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OpenQA.Selenium;
|
||||
using OpenQA.Selenium.Appium;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
using OpenQA.Selenium.Interactions;
|
||||
@@ -22,6 +27,14 @@ namespace Microsoft.PowerToys.UITest
|
||||
|
||||
private WindowsDriver<WindowsElement>? driver;
|
||||
|
||||
protected string? TargetControlType { get; set; }
|
||||
|
||||
internal bool IsMatchingTarget()
|
||||
{
|
||||
var ct = this.ControlType;
|
||||
return string.IsNullOrEmpty(this.TargetControlType) || this.TargetControlType == this.ControlType;
|
||||
}
|
||||
|
||||
internal void SetWindowsElement(WindowsElement windowsElement) => this.windowsElement = windowsElement;
|
||||
|
||||
internal void SetSession(WindowsDriver<WindowsElement> driver) => this.driver = driver;
|
||||
@@ -55,6 +68,14 @@ namespace Microsoft.PowerToys.UITest
|
||||
get { return this.windowsElement?.Selected ?? false; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Rect of the UI element.
|
||||
/// </summary>
|
||||
public Rectangle? Rect
|
||||
{
|
||||
get { return this.windowsElement?.Rect; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the AutomationID of the UI element.
|
||||
/// </summary>
|
||||
@@ -91,7 +112,7 @@ namespace Microsoft.PowerToys.UITest
|
||||
/// Click the UI element.
|
||||
/// </summary>
|
||||
/// <param name="rightClick">If true, performs a right-click; otherwise, performs a left-click. Default value is false</param>
|
||||
public void Click(bool rightClick = false)
|
||||
public virtual void Click(bool rightClick = false)
|
||||
{
|
||||
PerformAction((actions, windowElement) =>
|
||||
{
|
||||
@@ -116,7 +137,7 @@ namespace Microsoft.PowerToys.UITest
|
||||
/// <summary>
|
||||
/// Double Click the UI element.
|
||||
/// </summary>
|
||||
public void DoubleClick()
|
||||
public virtual void DoubleClick()
|
||||
{
|
||||
PerformAction((actions, windowElement) =>
|
||||
{
|
||||
@@ -130,6 +151,54 @@ namespace Microsoft.PowerToys.UITest
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Drag element move offset.
|
||||
/// </summary>
|
||||
/// <param name="offsetX">The offsetX to move.</param>
|
||||
/// <param name="offsetY">The offsetY to move.</param>
|
||||
public void Drag(int offsetX, int offsetY)
|
||||
{
|
||||
PerformAction((actions, windowElement) =>
|
||||
{
|
||||
actions.MoveToElement(windowElement).MoveByOffset(10, 10).ClickAndHold(windowElement).MoveByOffset(offsetX, offsetY).Release();
|
||||
actions.Build().Perform();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Drag element move to other element.
|
||||
/// </summary>
|
||||
/// <param name="element">Move to this element.</param>
|
||||
public void Drag(Element element)
|
||||
{
|
||||
PerformAction((actions, windowElement) =>
|
||||
{
|
||||
actions.MoveToElement(windowElement).ClickAndHold();
|
||||
Assert.IsNotNull(element.windowsElement, "element is null");
|
||||
int dx = (element.windowsElement.Rect.X - windowElement.Rect.X) / 10;
|
||||
int dy = (element.windowsElement.Rect.Y - windowElement.Rect.Y) / 10;
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
actions.MoveByOffset(dx, dy);
|
||||
}
|
||||
|
||||
actions.Release();
|
||||
actions.Build().Perform();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send Key of the element.
|
||||
/// </summary>
|
||||
/// <param name="key">The Key to Send.</param>
|
||||
public void SendKeys(string key)
|
||||
{
|
||||
PerformAction((actions, windowElement) =>
|
||||
{
|
||||
windowElement.SendKeys(key);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the attribute value of the UI element.
|
||||
/// </summary>
|
||||
@@ -139,7 +208,6 @@ namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
Assert.IsNotNull(this.windowsElement, $"WindowsElement is null in method GetAttribute with parameter: attributeName = {attributeName}");
|
||||
var attributeValue = this.windowsElement.GetAttribute(attributeName);
|
||||
Assert.IsNotNull(attributeValue, $"Attribute '{attributeName}' is null.");
|
||||
return attributeValue;
|
||||
}
|
||||
|
||||
@@ -154,17 +222,51 @@ namespace Microsoft.PowerToys.UITest
|
||||
where T : Element, new()
|
||||
{
|
||||
Assert.IsNotNull(this.windowsElement, $"WindowsElement is null in method Find<{typeof(T).Name}> with parameters: by = {by}, timeoutMS = {timeoutMS}");
|
||||
var foundElement = FindHelper.Find<T, AppiumWebElement>(
|
||||
() =>
|
||||
{
|
||||
var element = this.windowsElement.FindElement(by.ToSeleniumBy());
|
||||
Assert.IsNotNull(element, $"Element not found using selector: {by}");
|
||||
return element;
|
||||
},
|
||||
this.driver,
|
||||
timeoutMS);
|
||||
|
||||
return foundElement;
|
||||
// leverage findAll to filter out mismatched elements
|
||||
var collection = this.FindAll<T>(by, timeoutMS);
|
||||
|
||||
Assert.IsTrue(collection.Count > 0, $"Element not found using selector: {by}");
|
||||
|
||||
return collection[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds an element by the selector.
|
||||
/// Shortcut for this.Find<T>(By.Name(name), timeoutMS)
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The class type of the element to find.</typeparam>
|
||||
/// <param name="name">The name for finding the element.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds.</param>
|
||||
/// <returns>The found element.</returns>
|
||||
public T Find<T>(string name, int timeoutMS = 3000)
|
||||
where T : Element, new()
|
||||
{
|
||||
return this.Find<T>(By.Name(name), timeoutMS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds an element by the selector.
|
||||
/// Shortcut for this.Find<Element>(by, timeoutMS)
|
||||
/// </summary>
|
||||
/// <param name="by">The selector to use for finding the element.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds.</param>
|
||||
/// <returns>The found element.</returns>
|
||||
public Element Find(By by, int timeoutMS = 3000)
|
||||
{
|
||||
return this.Find<Element>(by, timeoutMS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds an element by the selector.
|
||||
/// Shortcut for this.Find<Element>(By.Name(name), timeoutMS)
|
||||
/// </summary>
|
||||
/// <param name="name">The name for finding the element.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds.</param>
|
||||
/// <returns>The found element.</returns>
|
||||
public Element Find(string name, int timeoutMS = 3000)
|
||||
{
|
||||
return this.Find<Element>(By.Name(name), timeoutMS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -174,30 +276,75 @@ namespace Microsoft.PowerToys.UITest
|
||||
/// <param name="by">The selector to use for finding the elements.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds.</param>
|
||||
/// <returns>A read-only collection of the found elements.</returns>
|
||||
public ReadOnlyCollection<T>? FindAll<T>(By by, int timeoutMS = 3000)
|
||||
public ReadOnlyCollection<T> FindAll<T>(By by, int timeoutMS = 3000)
|
||||
where T : Element, new()
|
||||
{
|
||||
Assert.IsNotNull(this.windowsElement, $"WindowsElement is null in method FindAll<{typeof(T).Name}> with parameters: by = {by}, timeoutMS = {timeoutMS}");
|
||||
var foundElements = FindHelper.FindAll<T, AppiumWebElement>(
|
||||
() =>
|
||||
{
|
||||
var elements = this.windowsElement.FindElements(by.ToSeleniumBy());
|
||||
Assert.IsTrue(elements.Count > 0, $"Elements not found using selector: {by}");
|
||||
return elements;
|
||||
if (by.GetIsAccessibilityId())
|
||||
{
|
||||
var elements = this.windowsElement.FindElementsByAccessibilityId(by.GetAccessibilityId());
|
||||
return elements;
|
||||
}
|
||||
else
|
||||
{
|
||||
var elements = this.windowsElement.FindElements(by.ToSeleniumBy());
|
||||
return elements;
|
||||
}
|
||||
},
|
||||
this.driver,
|
||||
timeoutMS);
|
||||
|
||||
return foundElements;
|
||||
return foundElements ?? new ReadOnlyCollection<T>([]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds all elements by the selector.
|
||||
/// Shortcut for this.FindAll<T>(By.Name(name), timeoutMS)
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The class type of the elements to find.</typeparam>
|
||||
/// <param name="name">The name for finding the element.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds.</param>
|
||||
/// <returns>A read-only collection of the found elements.</returns>
|
||||
public ReadOnlyCollection<T> FindAll<T>(string name, int timeoutMS = 3000)
|
||||
where T : Element, new()
|
||||
{
|
||||
return this.FindAll<T>(By.Name(name), timeoutMS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds all elements by the selector.
|
||||
/// Shortcut for this.FindAll<Element>(by, timeoutMS)
|
||||
/// </summary>
|
||||
/// <param name="by">The selector to use for finding the elements.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds.</param>
|
||||
/// <returns>A read-only collection of the found elements.</returns>
|
||||
public ReadOnlyCollection<Element> FindAll(By by, int timeoutMS = 3000)
|
||||
{
|
||||
return this.FindAll<Element>(by, timeoutMS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds all elements by the selector.
|
||||
/// Shortcut for this.FindAll<Element>(By.Name(name), timeoutMS)
|
||||
/// </summary>
|
||||
/// <param name="name">The name for finding the element.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds.</param>
|
||||
/// <returns>A read-only collection of the found elements.</returns>
|
||||
public ReadOnlyCollection<Element> FindAll(string name, int timeoutMS = 3000)
|
||||
{
|
||||
return this.FindAll<Element>(By.Name(name), timeoutMS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulates a manual operation on the element.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to perform on the element.</param>
|
||||
/// <param name="msPreAction">The number of milliseconds to wait before the action. Default value is 100 ms</param>
|
||||
/// <param name="msPostAction">The number of milliseconds to wait after the action. Default value is 100 ms</param>
|
||||
protected void PerformAction(Action<Actions, WindowsElement> action, int msPreAction = 100, int msPostAction = 100)
|
||||
/// <param name="msPreAction">The number of milliseconds to wait before the action. Default value is 500 ms</param>
|
||||
/// <param name="msPostAction">The number of milliseconds to wait after the action. Default value is 500 ms</param>
|
||||
protected void PerformAction(Action<Actions, WindowsElement> action, int msPreAction = 500, int msPostAction = 500)
|
||||
{
|
||||
if (msPreAction > 0)
|
||||
{
|
||||
|
||||
23
src/common/UITestAutomation/Element/HyperlinkButton.cs
Normal file
23
src/common/UITestAutomation/Element/HyperlinkButton.cs
Normal file
@@ -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.
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a HyperLinkButton in the UI test environment.
|
||||
/// HyperLinkButton represents a button control that functions as a hyperlink.
|
||||
/// </summary>
|
||||
public class HyperlinkButton : Button
|
||||
{
|
||||
private static readonly string ExpectedControlType = "ControlType.HyperLink";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="HyperlinkButton"/> class.
|
||||
/// </summary>
|
||||
public HyperlinkButton()
|
||||
{
|
||||
this.TargetControlType = HyperlinkButton.ExpectedControlType;
|
||||
}
|
||||
}
|
||||
}
|
||||
59
src/common/UITestAutomation/Element/NavigationViewItem.cs
Normal file
59
src/common/UITestAutomation/Element/NavigationViewItem.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
// 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.PowerToys.UITest
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a NavigationViewItem in the UI test environment.
|
||||
/// NavigationViewItem represents the container for an item in a NavigationView control.
|
||||
/// </summary>
|
||||
public class NavigationViewItem : Element
|
||||
{
|
||||
private static readonly string ExpectedControlType = "ControlType.ListItem";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="NavigationViewItem"/> class.
|
||||
/// </summary>
|
||||
public NavigationViewItem()
|
||||
{
|
||||
this.TargetControlType = NavigationViewItem.ExpectedControlType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Click the ListItem element.
|
||||
/// </summary>
|
||||
/// <param name="rightClick">If true, performs a right-click; otherwise, performs a left-click. Default value is false</param>
|
||||
public override void Click(bool rightClick = false)
|
||||
{
|
||||
PerformAction((actions, windowElement) =>
|
||||
{
|
||||
actions.MoveToElement(windowElement, 10, 10);
|
||||
|
||||
if (rightClick)
|
||||
{
|
||||
actions.ContextClick();
|
||||
}
|
||||
else
|
||||
{
|
||||
actions.Click();
|
||||
}
|
||||
|
||||
actions.Build().Perform();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Double Click the ListItem element.
|
||||
/// </summary>
|
||||
public override void DoubleClick()
|
||||
{
|
||||
PerformAction((actions, windowElement) =>
|
||||
{
|
||||
actions.MoveToElement(windowElement, 10, 10);
|
||||
actions.DoubleClick();
|
||||
actions.Build().Perform();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
23
src/common/UITestAutomation/Element/TextBlock.cs
Normal file
23
src/common/UITestAutomation/Element/TextBlock.cs
Normal file
@@ -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.
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a TextBlock in the UI test environment.
|
||||
/// TextBlock provides a lightweight control for displaying small amounts of flow content.
|
||||
/// </summary>
|
||||
public class TextBlock : Element
|
||||
{
|
||||
private static readonly string ExpectedControlType = "ControlType.Text";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TextBlock"/> class.
|
||||
/// </summary>
|
||||
public TextBlock()
|
||||
{
|
||||
this.TargetControlType = TextBlock.ExpectedControlType;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,10 +7,21 @@ using OpenQA.Selenium;
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a textbox in the UI test environment.
|
||||
/// Represents a TextBox in the UI test environment.
|
||||
/// TextBox represents a control that can be used to display and edit plain text (single or multi-line).
|
||||
/// </summary>
|
||||
public class TextBox : Element
|
||||
{
|
||||
private static readonly string ExpectedControlType = "ControlType.Edit";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TextBox"/> class.
|
||||
/// </summary>
|
||||
public TextBox()
|
||||
{
|
||||
this.TargetControlType = TextBox.ExpectedControlType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the text of the textbox.
|
||||
/// </summary>
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
if (byClickButton)
|
||||
{
|
||||
Find<Button>(By.Name("Maximize")).Click();
|
||||
Find<Button>("Maximize").Click();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -37,7 +37,7 @@ namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
if (byClickButton)
|
||||
{
|
||||
Find<Button>(By.Name("Restore")).Click();
|
||||
Find<Button>("Restore").Click();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -56,7 +56,7 @@ namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
if (byClickButton)
|
||||
{
|
||||
Find<Button>(By.Name("Minimize")).Click();
|
||||
Find<Button>("Minimize").Click();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -74,7 +74,7 @@ namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
if (byClickButton)
|
||||
{
|
||||
Find<Button>(By.Name("Close")).Click();
|
||||
Find<Button>("Close").Click();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -17,11 +17,17 @@ namespace Microsoft.PowerToys.UITest
|
||||
/// </summary>
|
||||
internal static class FindHelper
|
||||
{
|
||||
public static T Find<T, TW>(Func<TW> findElementFunc, WindowsDriver<WindowsElement>? driver, int timeoutMS)
|
||||
public static ReadOnlyCollection<T>? FindAll<T, TW>(Func<IReadOnlyCollection<TW>> findElementsFunc, WindowsDriver<WindowsElement>? driver, int timeoutMS)
|
||||
where T : Element, new()
|
||||
{
|
||||
var item = findElementFunc() as WindowsElement;
|
||||
return NewElement<T>(item, driver, timeoutMS);
|
||||
var items = findElementsFunc();
|
||||
var res = items.Select(item =>
|
||||
{
|
||||
var element = item as WindowsElement;
|
||||
return NewElement<T>(element, driver, timeoutMS);
|
||||
}).Where(item => item.IsMatchingTarget()).ToList();
|
||||
|
||||
return new ReadOnlyCollection<T>(res);
|
||||
}
|
||||
|
||||
public static ReadOnlyCollection<T>? FindAll<T, TW>(Func<ReadOnlyCollection<TW>> findElementsFunc, WindowsDriver<WindowsElement>? driver, int timeoutMS)
|
||||
@@ -32,7 +38,7 @@ namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
var element = item as WindowsElement;
|
||||
return NewElement<T>(element, driver, timeoutMS);
|
||||
}).ToList();
|
||||
}).Where(item => item.IsMatchingTarget()).ToList();
|
||||
|
||||
return new ReadOnlyCollection<T>(res);
|
||||
}
|
||||
|
||||
@@ -4,9 +4,11 @@
|
||||
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OpenQA.Selenium.Appium;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
using OpenQA.Selenium.Interactions;
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
@@ -39,17 +41,48 @@ namespace Microsoft.PowerToys.UITest
|
||||
where T : Element, new()
|
||||
{
|
||||
Assert.IsNotNull(this.WindowsDriver, $"WindowsElement is null in method Find<{typeof(T).Name}> with parameters: by = {by}, timeoutMS = {timeoutMS}");
|
||||
var foundElement = FindHelper.Find<T, WindowsElement>(
|
||||
() =>
|
||||
{
|
||||
var element = this.WindowsDriver.FindElement(by.ToSeleniumBy());
|
||||
Assert.IsNotNull(element, $"Element not found using selector: {by}");
|
||||
return element;
|
||||
},
|
||||
this.WindowsDriver,
|
||||
timeoutMS);
|
||||
|
||||
return foundElement;
|
||||
// leverage findAll to filter out mismatched elements
|
||||
var collection = this.FindAll<T>(by, timeoutMS);
|
||||
|
||||
Assert.IsTrue(collection.Count > 0, $"Element not found using selector: {by}");
|
||||
|
||||
return collection[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shortcut for this.Find<T>(By.Name(name), timeoutMS)
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The class of the element, should be Element or its derived class.</typeparam>
|
||||
/// <param name="name">The name of the element.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 3000).</param>
|
||||
/// <returns>The found element.</returns>
|
||||
public T Find<T>(string name, int timeoutMS = 3000)
|
||||
where T : Element, new()
|
||||
{
|
||||
return this.Find<T>(By.Name(name), timeoutMS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shortcut for this.Find<Element>(by, timeoutMS)
|
||||
/// </summary>
|
||||
/// <param name="by">The selector to find the element.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 3000).</param>
|
||||
/// <returns>The found element.</returns>
|
||||
public Element Find(By by, int timeoutMS = 3000)
|
||||
{
|
||||
return this.Find<Element>(by, timeoutMS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shortcut for this.Find<Element>(By.Name(name), timeoutMS)
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the element.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 3000).</param>
|
||||
/// <returns>The found element.</returns>
|
||||
public Element Find(string name, int timeoutMS = 3000)
|
||||
{
|
||||
return this.Find<Element>(By.Name(name), timeoutMS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -66,13 +99,92 @@ namespace Microsoft.PowerToys.UITest
|
||||
var foundElements = FindHelper.FindAll<T, WindowsElement>(
|
||||
() =>
|
||||
{
|
||||
var elements = this.WindowsDriver.FindElements(by.ToSeleniumBy());
|
||||
return elements;
|
||||
if (by.GetIsAccessibilityId())
|
||||
{
|
||||
var elements = this.WindowsDriver.FindElementsByAccessibilityId(by.GetAccessibilityId());
|
||||
return elements;
|
||||
}
|
||||
else
|
||||
{
|
||||
var elements = this.WindowsDriver.FindElements(by.ToSeleniumBy());
|
||||
return elements;
|
||||
}
|
||||
},
|
||||
this.WindowsDriver,
|
||||
timeoutMS);
|
||||
|
||||
return foundElements ?? new ReadOnlyCollection<T>(new List<T>());
|
||||
return foundElements ?? new ReadOnlyCollection<T>([]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds all elements by selector.
|
||||
/// Shortcut for this.FindAll<T>(By.Name(name), timeoutMS)
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The class of the elements, should be Element or its derived class.</typeparam>
|
||||
/// <param name="name">The name to find the elements.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 3000).</param>
|
||||
/// <returns>A read-only collection of the found elements.</returns>
|
||||
public ReadOnlyCollection<T> FindAll<T>(string name, int timeoutMS = 3000)
|
||||
where T : Element, new()
|
||||
{
|
||||
return this.FindAll<T>(By.Name(name), timeoutMS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds all elements by selector.
|
||||
/// Shortcut for this.FindAll<Element>(by, timeoutMS)
|
||||
/// </summary>
|
||||
/// <param name="by">The selector to find the elements.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 3000).</param>
|
||||
/// <returns>A read-only collection of the found elements.</returns>
|
||||
public ReadOnlyCollection<Element> FindAll(By by, int timeoutMS = 3000)
|
||||
{
|
||||
return this.FindAll<Element>(by, timeoutMS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds all elements by selector.
|
||||
/// Shortcut for this.FindAll<Element>(By.Name(name), timeoutMS)
|
||||
/// </summary>
|
||||
/// <param name="name">The name to find the elements.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 3000).</param>
|
||||
/// <returns>A read-only collection of the found elements.</returns>
|
||||
public ReadOnlyCollection<Element> FindAll(string name, int timeoutMS = 3000)
|
||||
{
|
||||
return this.FindAll<Element>(By.Name(name), timeoutMS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Keyboard Action key.
|
||||
/// </summary>
|
||||
/// <param name="key1">The Keys1 to click.</param>
|
||||
/// <param name="key2">The Keys2 to click.</param>
|
||||
/// <param name="key3">The Keys3 to click.</param>
|
||||
/// <param name="key4">The Keys4 to click.</param>
|
||||
public void KeyboardAction(string key1, string key2 = "", string key3 = "", string key4 = "")
|
||||
{
|
||||
PerformAction((actions, windowElement) =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(key2))
|
||||
{
|
||||
actions.SendKeys(key1);
|
||||
}
|
||||
else if (string.IsNullOrEmpty(key3))
|
||||
{
|
||||
actions.SendKeys(key1).SendKeys(key2);
|
||||
}
|
||||
else if (string.IsNullOrEmpty(key4))
|
||||
{
|
||||
actions.SendKeys(key1).SendKeys(key2).SendKeys(key3);
|
||||
}
|
||||
else
|
||||
{
|
||||
actions.SendKeys(key1).SendKeys(key2).SendKeys(key3).SendKeys(key4);
|
||||
}
|
||||
|
||||
actions.Release();
|
||||
actions.Build().Perform();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -119,5 +231,28 @@ namespace Microsoft.PowerToys.UITest
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulates a manual operation on the element.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to perform on the element.</param>
|
||||
/// <param name="msPreAction">The number of milliseconds to wait before the action. Default value is 500 ms</param>
|
||||
/// <param name="msPostAction">The number of milliseconds to wait after the action. Default value is 500 ms</param>
|
||||
protected void PerformAction(Action<Actions, WindowsDriver<WindowsElement>> action, int msPreAction = 500, int msPostAction = 500)
|
||||
{
|
||||
if (msPreAction > 0)
|
||||
{
|
||||
Task.Delay(msPreAction).Wait();
|
||||
}
|
||||
|
||||
var windowsDriver = this.WindowsDriver;
|
||||
Actions actions = new Actions(this.WindowsDriver);
|
||||
action(actions, windowsDriver);
|
||||
|
||||
if (msPostAction > 0)
|
||||
{
|
||||
Task.Delay(msPostAction).Wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
149
src/common/UITestAutomation/SessionHelper.cs
Normal file
149
src/common/UITestAutomation/SessionHelper.cs
Normal file
@@ -0,0 +1,149 @@
|
||||
// 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.Reflection;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OpenQA.Selenium.Appium;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
/// <summary>
|
||||
/// Nested class for test initialization.
|
||||
/// </summary>
|
||||
internal class SessionHelper
|
||||
{
|
||||
// Default session path is PowerToys settings dashboard
|
||||
private readonly string sessionPath = ModuleConfigData.Instance.GetModulePath(PowerToysModule.PowerToysSettings);
|
||||
|
||||
private string? locationPath;
|
||||
|
||||
private WindowsDriver<WindowsElement> Root { get; set; }
|
||||
|
||||
private WindowsDriver<WindowsElement>? Driver { get; set; }
|
||||
|
||||
private Process? appDriver;
|
||||
|
||||
[UnconditionalSuppressMessage("SingleFile", "IL3000:Avoid accessing Assembly file path when publishing as a single file", Justification = "<Pending>")]
|
||||
public SessionHelper(PowerToysModule scope)
|
||||
{
|
||||
this.sessionPath = ModuleConfigData.Instance.GetModulePath(scope);
|
||||
this.locationPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
|
||||
var winAppDriverProcessInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "C:\\Program Files (x86)\\Windows Application Driver\\WinAppDriver.exe",
|
||||
Verb = "runas",
|
||||
};
|
||||
|
||||
this.appDriver = Process.Start(winAppDriverProcessInfo);
|
||||
|
||||
var desktopCapabilities = new AppiumOptions();
|
||||
desktopCapabilities.AddAdditionalCapability("app", "Root");
|
||||
this.Root = new WindowsDriver<WindowsElement>(new Uri(ModuleConfigData.Instance.GetWindowsApplicationDriverUrl()), desktopCapabilities);
|
||||
|
||||
// Set default timeout to 5 seconds
|
||||
this.Root.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the test environment.
|
||||
/// </summary>
|
||||
/// <param name="scope">The PowerToys module to start.</param>
|
||||
public SessionHelper Init()
|
||||
{
|
||||
this.StartExe(locationPath + this.sessionPath);
|
||||
|
||||
Assert.IsNotNull(this.Driver, $"Failed to initialize the test environment. Driver is null.");
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleans up the test environment.
|
||||
/// </summary>
|
||||
public void Cleanup()
|
||||
{
|
||||
ExitScopeExe();
|
||||
try
|
||||
{
|
||||
appDriver?.Kill();
|
||||
appDriver?.WaitForExit(); // Optional: Wait for the process to exit
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Handle exceptions if needed
|
||||
Debug.WriteLine($"Exception during Cleanup: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts a new exe and takes control of it.
|
||||
/// </summary>
|
||||
/// <param name="appPath">The path to the application executable.</param>
|
||||
public void StartExe(string appPath)
|
||||
{
|
||||
var opts = new AppiumOptions();
|
||||
opts.AddAdditionalCapability("app", appPath);
|
||||
Console.WriteLine($"appPath: {appPath}");
|
||||
this.Driver = new WindowsDriver<WindowsElement>(new Uri(ModuleConfigData.Instance.GetWindowsApplicationDriverUrl()), opts);
|
||||
|
||||
// Set default timeout to 5 seconds
|
||||
this.Driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exit a exe.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the application executable.</param>
|
||||
public void ExitExe(string path)
|
||||
{
|
||||
// Exit Exe
|
||||
string exeName = Path.GetFileNameWithoutExtension(path);
|
||||
|
||||
// PowerToys.FancyZonesEditor
|
||||
Process[] processes = Process.GetProcessesByName(exeName);
|
||||
foreach (Process process in processes)
|
||||
{
|
||||
try
|
||||
{
|
||||
process.Kill();
|
||||
process.WaitForExit(); // Optional: Wait for the process to exit
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Assert.Fail($"Failed to terminate process {process.ProcessName} (ID: {process.Id}): {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exit now exe.
|
||||
/// </summary>
|
||||
public void ExitScopeExe()
|
||||
{
|
||||
ExitExe(sessionPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restarts now exe and takes control of it.
|
||||
/// </summary>
|
||||
public void RestartScopeExe()
|
||||
{
|
||||
ExitExe(sessionPath);
|
||||
StartExe(locationPath + sessionPath);
|
||||
}
|
||||
|
||||
public WindowsDriver<WindowsElement> GetRoot() => this.Root;
|
||||
|
||||
public WindowsDriver<WindowsElement> GetDriver()
|
||||
{
|
||||
Assert.IsNotNull(this.Driver, $"Failed to get driver. Driver is null.");
|
||||
return this.Driver;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Reflection;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OpenQA.Selenium.Appium;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
@@ -15,22 +16,46 @@ namespace Microsoft.PowerToys.UITest
|
||||
/// <summary>
|
||||
/// Base class that should be inherited by all Test Classes.
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class UITestBase
|
||||
{
|
||||
public Session Session { get; set; }
|
||||
|
||||
private readonly TestInit testInit = new TestInit();
|
||||
private readonly SessionHelper sessionHelper;
|
||||
|
||||
private readonly PowerToysModule scope;
|
||||
|
||||
public UITestBase(PowerToysModule scope = PowerToysModule.PowerToysSettings)
|
||||
{
|
||||
this.testInit.SetScope(scope);
|
||||
this.testInit.Init();
|
||||
this.Session = new Session(this.testInit.GetRoot(), this.testInit.GetDriver());
|
||||
this.scope = scope;
|
||||
this.sessionHelper = new SessionHelper(scope).Init();
|
||||
this.Session = new Session(this.sessionHelper.GetRoot(), this.sessionHelper.GetDriver());
|
||||
}
|
||||
|
||||
~UITestBase()
|
||||
/// <summary>
|
||||
/// Initializes the test.
|
||||
/// </summary>
|
||||
[TestInitialize]
|
||||
public void TestInit()
|
||||
{
|
||||
this.testInit.Cleanup();
|
||||
if (this.scope == PowerToysModule.PowerToysSettings)
|
||||
{
|
||||
// close Debug warning dialog if any
|
||||
// Such debug warning dialog seems only appear in PowerToys Settings
|
||||
if (this.FindAll("DEBUG").Count > 0)
|
||||
{
|
||||
this.Find("DEBUG").Find<Button>("Close").Click();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UnInitializes the test.
|
||||
/// </summary>
|
||||
[TestCleanup]
|
||||
public void TestClean()
|
||||
{
|
||||
this.sessionHelper.Cleanup();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -47,6 +72,41 @@ namespace Microsoft.PowerToys.UITest
|
||||
return this.Session.Find<T>(by, timeoutMS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shortcut for this.Session.Find<Element>(By.Name(name), timeoutMS)
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The class of the element, should be Element or its derived class.</typeparam>
|
||||
/// <param name="name">The name of the element.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 3000).</param>
|
||||
/// <returns>The found element.</returns>
|
||||
protected T Find<T>(string name, int timeoutMS = 3000)
|
||||
where T : Element, new()
|
||||
{
|
||||
return this.Session.Find<T>(By.Name(name), timeoutMS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shortcut for this.Session.Find<Element>(by, timeoutMS)
|
||||
/// </summary>
|
||||
/// <param name="by">The selector to find the element.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 3000).</param>
|
||||
/// <returns>The found element.</returns>
|
||||
protected Element Find(By by, int timeoutMS = 3000)
|
||||
{
|
||||
return this.Session.Find(by, timeoutMS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shortcut for this.Session.Find<Element>(By.Name(name), timeoutMS)
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the element.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 3000).</param>
|
||||
/// <returns>The found element.</returns>
|
||||
protected Element Find(string name, int timeoutMS = 3000)
|
||||
{
|
||||
return this.Session.Find(name, timeoutMS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds all elements by selector.
|
||||
/// Shortcut for this.Session.FindAll<T>(by, timeoutMS)
|
||||
@@ -62,93 +122,60 @@ namespace Microsoft.PowerToys.UITest
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Nested class for test initialization.
|
||||
/// Finds all elements by selector.
|
||||
/// Shortcut for this.Session.FindAll<Element>(By.Name(name), timeoutMS)
|
||||
/// </summary>
|
||||
private sealed class TestInit
|
||||
/// <typeparam name="T">The class of the elements, should be Element or its derived class.</typeparam>
|
||||
/// <param name="name">The name of the elements.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 3000).</param>
|
||||
/// <returns>A read-only collection of the found elements.</returns>
|
||||
protected ReadOnlyCollection<T> FindAll<T>(string name, int timeoutMS = 3000)
|
||||
where T : Element, new()
|
||||
{
|
||||
private WindowsDriver<WindowsElement> Root { get; set; }
|
||||
return this.Session.FindAll<T>(By.Name(name), timeoutMS);
|
||||
}
|
||||
|
||||
private WindowsDriver<WindowsElement>? Driver { get; set; }
|
||||
/// <summary>
|
||||
/// Finds all elements by selector.
|
||||
/// Shortcut for this.Session.FindAll<Element>(by, timeoutMS)
|
||||
/// </summary>
|
||||
/// <param name="by">The selector to find the elements.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 3000).</param>
|
||||
/// <returns>A read-only collection of the found elements.</returns>
|
||||
protected ReadOnlyCollection<Element> FindAll(By by, int timeoutMS = 3000)
|
||||
{
|
||||
return this.Session.FindAll<Element>(by, timeoutMS);
|
||||
}
|
||||
|
||||
private static Process? appDriver;
|
||||
/// <summary>
|
||||
/// Finds all elements by selector.
|
||||
/// Shortcut for this.Session.FindAll<Element>(By.Name(name), timeoutMS)
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the elements.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 3000).</param>
|
||||
/// <returns>A read-only collection of the found elements.</returns>
|
||||
protected ReadOnlyCollection<Element> FindAll(string name, int timeoutMS = 3000)
|
||||
{
|
||||
return this.Session.FindAll<Element>(By.Name(name), timeoutMS);
|
||||
}
|
||||
|
||||
// Default session path is PowerToys settings dashboard
|
||||
private static string sessionPath = ModuleConfigData.Instance.GetModulePath(PowerToysModule.PowerToysSettings);
|
||||
/// <summary>
|
||||
/// Restart scope exe.
|
||||
/// </summary>
|
||||
public void RestartScopeExe()
|
||||
{
|
||||
this.sessionHelper.RestartScopeExe();
|
||||
this.Session = new Session(this.sessionHelper.GetRoot(), this.sessionHelper.GetDriver());
|
||||
return;
|
||||
}
|
||||
|
||||
public TestInit()
|
||||
{
|
||||
appDriver = Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = "C:\\Program Files (x86)\\Windows Application Driver\\WinAppDriver.exe",
|
||||
Verb = "runas",
|
||||
});
|
||||
|
||||
var desktopCapabilities = new AppiumOptions();
|
||||
desktopCapabilities.AddAdditionalCapability("app", "Root");
|
||||
this.Root = new WindowsDriver<WindowsElement>(new Uri(ModuleConfigData.Instance.GetWindowsApplicationDriverUrl()), desktopCapabilities);
|
||||
|
||||
// Set default timeout to 5 seconds
|
||||
this.Root.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the test environment.
|
||||
/// </summary>
|
||||
[UnconditionalSuppressMessage("SingleFile", "IL3000:Avoid accessing Assembly file path when publishing as a single file", Justification = "<Pending>")]
|
||||
public void Init()
|
||||
{
|
||||
string? path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
this.StartExe(path + sessionPath);
|
||||
|
||||
Assert.IsNotNull(this.Driver, $"Failed to initialize the test environment. Driver is null.");
|
||||
|
||||
// Set default timeout to 5 seconds
|
||||
this.Driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleans up the test environment.
|
||||
/// </summary>
|
||||
public void Cleanup()
|
||||
{
|
||||
try
|
||||
{
|
||||
appDriver?.Kill();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Handle exceptions if needed
|
||||
Debug.WriteLine($"Exception during Cleanup: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts a new exe and takes control of it.
|
||||
/// </summary>
|
||||
/// <param name="appPath">The path to the application executable.</param>
|
||||
public void StartExe(string appPath)
|
||||
{
|
||||
var opts = new AppiumOptions();
|
||||
opts.AddAdditionalCapability("app", appPath);
|
||||
this.Driver = new WindowsDriver<WindowsElement>(new Uri(ModuleConfigData.Instance.GetWindowsApplicationDriverUrl()), opts);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets scope to the Test Class.
|
||||
/// </summary>
|
||||
/// <param name="scope">The PowerToys module to start.</param>
|
||||
public void SetScope(PowerToysModule scope)
|
||||
{
|
||||
sessionPath = ModuleConfigData.Instance.GetModulePath(scope);
|
||||
}
|
||||
|
||||
public WindowsDriver<WindowsElement> GetRoot() => this.Root;
|
||||
|
||||
public WindowsDriver<WindowsElement> GetDriver()
|
||||
{
|
||||
Assert.IsNotNull(this.Driver, $"Failed to get driver. Driver is null.");
|
||||
return this.Driver;
|
||||
}
|
||||
/// <summary>
|
||||
/// Restart scope exe.
|
||||
/// </summary>
|
||||
public void ExitScopeExe()
|
||||
{
|
||||
this.sessionHelper.ExitScopeExe();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,4 +187,8 @@ namespace winrt::PowerToys::Interop::implementation
|
||||
{
|
||||
return CommonSharedConstants::TERMINATE_SETTINGS_SHARED_EVENT;
|
||||
}
|
||||
hstring Constants::ShowCmdPalEvent()
|
||||
{
|
||||
return CommonSharedConstants::CMDPAL_SHOW_EVENT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ namespace winrt::PowerToys::Interop::implementation
|
||||
static hstring WorkspacesLaunchEditorEvent();
|
||||
static hstring WorkspacesHotkeyEvent();
|
||||
static hstring PowerToysRunnerTerminateSettingsEvent();
|
||||
static hstring ShowCmdPalEvent();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace PowerToys
|
||||
static String WorkspacesLaunchEditorEvent();
|
||||
static String WorkspacesHotkeyEvent();
|
||||
static String PowerToysRunnerTerminateSettingsEvent();
|
||||
static String ShowCmdPalEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,6 +128,10 @@ namespace CommonSharedConstants
|
||||
const wchar_t ZOOMIT_REFRESH_SETTINGS_EVENT[] = L"Local\\PowerToysZoomIt-RefreshSettingsEvent-f053a563-d519-4b0d-8152-a54489c13324";
|
||||
const wchar_t ZOOMIT_EXIT_EVENT[] = L"Local\\PowerToysZoomIt-ExitEvent-36641ce6-df02-4eac-abea-a3fbf9138220";
|
||||
|
||||
// used from quick access window
|
||||
const wchar_t CMDPAL_SHOW_EVENT[] = L"Local\\PowerToysCmdPal-ShowEvent-62336fcd-8611-4023-9b30-091a6af4cc5a";
|
||||
const wchar_t CMDPAL_EXIT_EVENT[] = L"Local\\PowerToysCmdPal-ExitEvent-eb73f6be-3f22-4b36-aee3-62924ba40bfd";
|
||||
|
||||
// Max DWORD for key code to disable keys.
|
||||
const DWORD VK_DISABLED = 0x100;
|
||||
}
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace powertoys_gpo {
|
||||
enum gpo_rule_configured_t {
|
||||
namespace powertoys_gpo
|
||||
{
|
||||
enum gpo_rule_configured_t
|
||||
{
|
||||
gpo_rule_configured_wrong_value = -3, // The policy is set to an unrecognized value
|
||||
gpo_rule_configured_unavailable = -2, // Couldn't access registry
|
||||
gpo_rule_configured_not_configured = -1, // Policy is not configured
|
||||
@@ -53,6 +55,7 @@ namespace powertoys_gpo {
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_SHORTCUT_GUIDE = L"ConfigureEnabledUtilityShortcutGuide";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_TEXT_EXTRACTOR = L"ConfigureEnabledUtilityTextExtractor";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_ADVANCED_PASTE = L"ConfigureEnabledUtilityAdvancedPaste";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_CMD_PAL = L"ConfigureEnabledUtilityCmdPal";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_ZOOM_IT = L"ConfigureEnabledUtilityZoomIt";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_REGISTRY_PREVIEW = L"ConfigureEnabledUtilityRegistryPreview";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_MOUSE_WITHOUT_BORDERS = L"ConfigureEnabledUtilityMouseWithoutBorders";
|
||||
@@ -86,6 +89,7 @@ namespace powertoys_gpo {
|
||||
const std::wstring POLICY_MWB_DISABLE_USER_DEFINED_IP_MAPPING_RULES = L"MwbDisableUserDefinedIpMappingRules";
|
||||
const std::wstring POLICY_MWB_POLICY_DEFINED_IP_MAPPING_RULES = L"MwbPolicyDefinedIpMappingRules";
|
||||
const std::wstring POLICY_NEW_PLUS_HIDE_TEMPLATE_FILENAME_EXTENSION = L"NewPlusHideTemplateFilenameExtension";
|
||||
const std::wstring POLICY_NEW_PLUS_REPLACE_VARIABLES = L"NewPlusReplaceVariablesInTemplateFilenames";
|
||||
|
||||
// Methods used for reading the registry
|
||||
#pragma region ReadRegistryMethods
|
||||
@@ -156,16 +160,17 @@ namespace powertoys_gpo {
|
||||
machine_key_found = false;
|
||||
}
|
||||
|
||||
if(machine_key_found)
|
||||
if (machine_key_found)
|
||||
{
|
||||
// If the path was found in the machine, we need to check if the value for the policy exists.
|
||||
auto res = RegQueryValueExW(key, registry_value_name.c_str(), nullptr, nullptr, reinterpret_cast<LPBYTE>(&value), &valueSize);
|
||||
|
||||
RegCloseKey(key);
|
||||
|
||||
if (res != ERROR_SUCCESS) {
|
||||
if (res != ERROR_SUCCESS)
|
||||
{
|
||||
// Value not found on the path.
|
||||
machine_key_found=false;
|
||||
machine_key_found = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +179,8 @@ namespace powertoys_gpo {
|
||||
// If there's no value found on the machine scope, try to get it from the user scope.
|
||||
if (auto res = RegOpenKeyExW(POLICIES_SCOPE_USER, POLICIES_PATH.c_str(), 0, KEY_READ, &key); res != ERROR_SUCCESS)
|
||||
{
|
||||
if (res == ERROR_FILE_NOT_FOUND) {
|
||||
if (res == ERROR_FILE_NOT_FOUND)
|
||||
{
|
||||
return gpo_rule_configured_not_configured;
|
||||
}
|
||||
return gpo_rule_configured_unavailable;
|
||||
@@ -182,7 +188,8 @@ namespace powertoys_gpo {
|
||||
auto res = RegQueryValueExW(key, registry_value_name.c_str(), nullptr, nullptr, reinterpret_cast<LPBYTE>(&value), &valueSize);
|
||||
RegCloseKey(key);
|
||||
|
||||
if (res != ERROR_SUCCESS) {
|
||||
if (res != ERROR_SUCCESS)
|
||||
{
|
||||
return gpo_rule_configured_not_configured;
|
||||
}
|
||||
}
|
||||
@@ -411,6 +418,11 @@ namespace powertoys_gpo {
|
||||
return getUtilityEnabledValue(POLICY_CONFIGURE_ENABLED_ADVANCED_PASTE);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredCmdPalEnabledValue()
|
||||
{
|
||||
return getUtilityEnabledValue(POLICY_CONFIGURE_ENABLED_CMD_PAL);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredWorkspacesEnabledValue()
|
||||
{
|
||||
return getUtilityEnabledValue(POLICY_CONFIGURE_ENABLED_WORKSPACES);
|
||||
@@ -501,7 +513,7 @@ namespace powertoys_gpo {
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getRunPluginEnabledValue(std::string pluginID)
|
||||
{
|
||||
{
|
||||
if (pluginID == "" || pluginID == " ")
|
||||
{
|
||||
// this plugin id can't exist in the registry
|
||||
@@ -510,7 +522,7 @@ namespace powertoys_gpo {
|
||||
|
||||
std::wstring plugin_id(pluginID.begin(), pluginID.end());
|
||||
auto individual_plugin_setting = getPolicyListValue(POWER_LAUNCHER_INDIVIDUAL_PLUGIN_ENABLED_LIST_PATH, plugin_id);
|
||||
|
||||
|
||||
if (individual_plugin_setting.has_value())
|
||||
{
|
||||
if (*individual_plugin_setting == L"0")
|
||||
@@ -537,7 +549,7 @@ namespace powertoys_gpo {
|
||||
{
|
||||
// If no individual plugin policy exists, we check the policy with the setting for all plugins.
|
||||
return getConfiguredValue(POLICY_CONFIGURE_ENABLED_POWER_LAUNCHER_ALL_PLUGINS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getAllowedAdvancedPasteOnlineAIModelsValue()
|
||||
@@ -601,7 +613,7 @@ namespace powertoys_gpo {
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::wstring ();
|
||||
return std::wstring();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -609,5 +621,11 @@ namespace powertoys_gpo {
|
||||
{
|
||||
return getConfiguredValue(POLICY_NEW_PLUS_HIDE_TEMPLATE_FILENAME_EXTENSION);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredNewPlusReplaceVariablesValue()
|
||||
{
|
||||
return getConfiguredValue(POLICY_NEW_PLUS_REPLACE_VARIABLES);
|
||||
}
|
||||
|
||||
#pragma endregion IndividualModuleSettingPolicies
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
#include <Windows.h>
|
||||
|
||||
#include <exception>
|
||||
#include <filesystem>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
#include <winrt/Windows.ApplicationModel.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
@@ -13,6 +16,11 @@
|
||||
#include "../version/version.h"
|
||||
|
||||
namespace package {
|
||||
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::ApplicationModel;
|
||||
using namespace winrt::Windows::Management::Deployment;
|
||||
|
||||
inline BOOL IsWin11OrGreater()
|
||||
{
|
||||
OSVERSIONINFOEX osvi{};
|
||||
@@ -38,35 +46,35 @@ namespace package {
|
||||
dwlConditionMask);
|
||||
}
|
||||
|
||||
inline bool IsPackageRegistered(std::wstring packageDisplayName)
|
||||
inline std::optional<Package> GetRegisteredPackage(std::wstring packageDisplayName, bool checkVersion)
|
||||
{
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::Management::Deployment;
|
||||
|
||||
PackageManager packageManager;
|
||||
|
||||
for (auto const& package : packageManager.FindPackagesForUser({}))
|
||||
for (const auto& package : packageManager.FindPackagesForUser({}))
|
||||
{
|
||||
const auto& packageFullName = std::wstring{ package.Id().FullName() };
|
||||
const auto& packageVersion = package.Id().Version();
|
||||
|
||||
if (packageFullName.contains(packageDisplayName))
|
||||
{
|
||||
if (packageVersion.Major == VERSION_MAJOR && packageVersion.Minor == VERSION_MINOR && packageVersion.Revision == VERSION_REVISION)
|
||||
// If checkVersion is true, verify if the package has the same version as PowerToys.
|
||||
if ((!checkVersion) || (packageVersion.Major == VERSION_MAJOR && packageVersion.Minor == VERSION_MINOR && packageVersion.Revision == VERSION_REVISION))
|
||||
{
|
||||
return true;
|
||||
return { package };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
inline bool RegisterSparsePackage(std::wstring externalLocation, std::wstring sparsePkgPath)
|
||||
inline bool IsPackageRegisteredWithPowerToysVersion(std::wstring packageDisplayName)
|
||||
{
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::Management::Deployment;
|
||||
return GetRegisteredPackage(packageDisplayName, true).has_value();
|
||||
}
|
||||
|
||||
inline bool RegisterSparsePackage(const std::wstring& externalLocation, const std::wstring& sparsePkgPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
Uri externalUri{ externalLocation };
|
||||
@@ -115,4 +123,174 @@ namespace package {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool UnRegisterPackage(const std::wstring& pkgDisplayName)
|
||||
{
|
||||
try
|
||||
{
|
||||
PackageManager packageManager;
|
||||
const static auto packages = packageManager.FindPackagesForUser({});
|
||||
|
||||
for (auto const& package : packages)
|
||||
{
|
||||
const auto& packageFullName = std::wstring{ package.Id().FullName() };
|
||||
|
||||
if (packageFullName.contains(pkgDisplayName))
|
||||
{
|
||||
auto deploymentOperation{ packageManager.RemovePackageAsync(packageFullName) };
|
||||
deploymentOperation.get();
|
||||
|
||||
// Check the status of the operation
|
||||
if (deploymentOperation.Status() == AsyncStatus::Error)
|
||||
{
|
||||
auto deploymentResult{ deploymentOperation.GetResults() };
|
||||
auto errorCode = deploymentOperation.ErrorCode();
|
||||
auto errorText = deploymentResult.ErrorText();
|
||||
|
||||
Logger::error(L"Unregister {} package failed. ErrorCode: {}, ErrorText: {}", packageFullName, std::to_wstring(errorCode), errorText);
|
||||
}
|
||||
else if (deploymentOperation.Status() == AsyncStatus::Canceled)
|
||||
{
|
||||
Logger::error(L"Unregister {} package canceled.", packageFullName);
|
||||
}
|
||||
else if (deploymentOperation.Status() == AsyncStatus::Completed)
|
||||
{
|
||||
Logger::info(L"Unregister {} package completed.", packageFullName);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::debug(L"Unregister {} package started.", packageFullName);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
Logger::error("Exception thrown while trying to unregister package: {}", e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline std::vector<std::wstring> FindMsixFile(const std::wstring& directoryPath, bool recursive)
|
||||
{
|
||||
if (directoryPath.empty())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists(directoryPath))
|
||||
{
|
||||
Logger::error(L"The directory '" + directoryPath + L"' does not exist.");
|
||||
}
|
||||
|
||||
const std::regex pattern(R"(^.+\.(appx|msix|msixbundle)$)", std::regex_constants::icase);
|
||||
std::vector<std::wstring> matchedFiles;
|
||||
|
||||
try
|
||||
{
|
||||
if (recursive)
|
||||
{
|
||||
for (const auto& entry : std::filesystem::recursive_directory_iterator(directoryPath))
|
||||
{
|
||||
if (entry.is_regular_file())
|
||||
{
|
||||
const auto& fileName = entry.path().filename().string();
|
||||
if (std::regex_match(fileName, pattern))
|
||||
{
|
||||
matchedFiles.push_back(entry.path());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const auto& entry : std::filesystem::directory_iterator(directoryPath))
|
||||
{
|
||||
if (entry.is_regular_file())
|
||||
{
|
||||
const auto& fileName = entry.path().filename().string();
|
||||
if (std::regex_match(fileName, pattern))
|
||||
{
|
||||
matchedFiles.push_back(entry.path());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
Logger::error("An error occurred while searching for MSIX files: " + std::string(ex.what()));
|
||||
}
|
||||
|
||||
return matchedFiles;
|
||||
}
|
||||
|
||||
inline bool RegisterPackage(std::wstring pkgPath, std::vector<std::wstring> dependencies)
|
||||
{
|
||||
try
|
||||
{
|
||||
Uri packageUri{ pkgPath };
|
||||
|
||||
PackageManager packageManager;
|
||||
|
||||
// Declare use of an external location
|
||||
DeploymentOptions options = DeploymentOptions::ForceApplicationShutdown;
|
||||
|
||||
Collections::IVector<Uri> uris = winrt::single_threaded_vector<Uri>();
|
||||
if (!dependencies.empty())
|
||||
{
|
||||
for (const auto& dependency : dependencies)
|
||||
{
|
||||
try
|
||||
{
|
||||
uris.Append(Uri(dependency));
|
||||
}
|
||||
catch (const winrt::hresult_error& ex)
|
||||
{
|
||||
Logger::error(L"Error creating Uri for dependency: %s", ex.message().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IAsyncOperationWithProgress<DeploymentResult, DeploymentProgress> deploymentOperation = packageManager.AddPackageAsync(packageUri, uris, options);
|
||||
deploymentOperation.get();
|
||||
|
||||
// Check the status of the operation
|
||||
if (deploymentOperation.Status() == AsyncStatus::Error)
|
||||
{
|
||||
auto deploymentResult{ deploymentOperation.GetResults() };
|
||||
auto errorCode = deploymentOperation.ErrorCode();
|
||||
auto errorText = deploymentResult.ErrorText();
|
||||
|
||||
Logger::error(L"Register {} package failed. ErrorCode: {}, ErrorText: {}", pkgPath, std::to_wstring(errorCode), errorText);
|
||||
return false;
|
||||
}
|
||||
else if (deploymentOperation.Status() == AsyncStatus::Canceled)
|
||||
{
|
||||
Logger::error(L"Register {} package canceled.", pkgPath);
|
||||
return false;
|
||||
}
|
||||
else if (deploymentOperation.Status() == AsyncStatus::Completed)
|
||||
{
|
||||
Logger::info(L"Register {} package completed.", pkgPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::debug(L"Register {} package started.", pkgPath);
|
||||
}
|
||||
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
Logger::error("Exception thrown while trying to register package: {}", e.what());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -5,22 +5,22 @@ This folder contains samples of DSC files that can be used to configure PowerToy
|
||||
> [!NOTE]
|
||||
> PowerToys DSC user documentation can be found on [Learn Microsoft PowerToys documentation](https://aka.ms/powertoys-docs-dsc-configure).
|
||||
|
||||
### [configuration.dsc.yaml](./configuration.dsc.yaml)
|
||||
### [configuration.winget](./configuration.winget)
|
||||
|
||||
Sample configuration file that changes the enabled state of some modules, changes an integer setting and a hotkey setting.
|
||||
|
||||
### [installAndConfiguration.dsc.yaml](./installAndConfiguration.dsc.yaml)
|
||||
### [installAndConfiguration.winget](./installAndConfiguration.winget)
|
||||
|
||||
Installs PowerToys and applies configuration.dsc.yaml to it.
|
||||
Installs PowerToys and applies configuration.winget to it.
|
||||
|
||||
### [enableAllModules.dsc.yaml](./enableAllModules.dsc.yaml)
|
||||
### [enableAllModules.winget](./enableAllModules.winget)
|
||||
|
||||
Enables all PowerToys utilities.
|
||||
|
||||
### [disableAllModules.dsc.yaml](./disableAllModules.dsc.yaml)
|
||||
### [disableAllModules.winget](./disableAllModules.winget)
|
||||
|
||||
Disables all PowerToys utilities.
|
||||
|
||||
### [configureLauncherPlugins.dsc.yaml](./configureLauncherPlugins.dsc.yaml)
|
||||
### [configureLauncherPlugins.winget](./configureLauncherPlugins.winget)
|
||||
|
||||
Enables PowerToys Run and all its plugins and changes action keyword and global state for the Program plugin.
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) Microsoft Corporation.
|
||||
Licensed under the MIT License. -->
|
||||
<policyDefinitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.16" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<policyDefinitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.17" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<policyNamespaces>
|
||||
<target prefix="powertoys" namespace="Microsoft.Policies.PowerToys" />
|
||||
</policyNamespaces>
|
||||
<resources minRequiredRevision="1.16"/><!-- Last changed with PowerToys v0.89.0 -->
|
||||
<resources minRequiredRevision="1.17"/><!-- Last changed with PowerToys v0.90.0 -->
|
||||
<supportedOn>
|
||||
<definitions>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_64_0" displayName="$(string.SUPPORTED_POWERTOYS_0_64_0)"/>
|
||||
@@ -25,6 +25,7 @@
|
||||
<definition name="SUPPORTED_POWERTOYS_0_86_0" displayName="$(string.SUPPORTED_POWERTOYS_0_86_0)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_88_0" displayName="$(string.SUPPORTED_POWERTOYS_0_88_0)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_89_0" displayName="$(string.SUPPORTED_POWERTOYS_0_89_0)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_90_0" displayName="$(string.SUPPORTED_POWERTOYS_0_90_0)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_64_0_TO_0_87_1" displayName="$(string.SUPPORTED_POWERTOYS_0_64_0_TO_0_87_1)"/>
|
||||
</definitions>
|
||||
</supportedOn>
|
||||
@@ -106,6 +107,16 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="ConfigureEnabledUtilityCmdPal" class="Both" displayName="$(string.ConfigureEnabledUtilityCmdPal)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityCmdPal">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_90_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="ConfigureEnabledUtilityColorPicker" class="Both" displayName="$(string.ConfigureEnabledUtilityColorPicker)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityColorPicker">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_64_0" />
|
||||
@@ -671,5 +682,15 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="NewPlusReplaceVariablesInTemplateFilenames" class="Both" displayName="$(string.NewPlusReplaceVariablesInTemplateFilenames)" explainText="$(string.NewPlusReplaceVariablesInTemplateFilenamesDescription)" key="Software\Policies\PowerToys" valueName="NewPlusReplaceVariablesInTemplateFilenames">
|
||||
<parentCategory ref="NewPlus" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_90_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
</policies>
|
||||
</policyDefinitions>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) Microsoft Corporation.
|
||||
Licensed under the MIT License. -->
|
||||
<policyDefinitionResources xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.16" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<policyDefinitionResources xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.17" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<displayName>PowerToys</displayName>
|
||||
<description>PowerToys</description>
|
||||
<resources>
|
||||
@@ -32,6 +32,7 @@
|
||||
<string id="SUPPORTED_POWERTOYS_0_86_0">PowerToys version 0.86.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_88_0">PowerToys version 0.88.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_89_0">PowerToys version 0.89.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_90_0">PowerToys version 0.90.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_64_0_TO_0_87_1">From PowerToys version 0.64.0 until PowerToys version 0.87.1</string>
|
||||
|
||||
<string id="ConfigureAllUtilityGlobalEnabledStateDescription">This policy configures the enabled state for all PowerToys utilities.
|
||||
@@ -226,6 +227,14 @@ If you enable this policy, the setting is enabled and the extension is hidden.
|
||||
If you disable this policy, the setting is disabled and the extension is shown.
|
||||
|
||||
If you don't configure this policy, the user takes control over the setting and can enable or disable it.
|
||||
</string>
|
||||
<string id="NewPlusReplaceVariablesInTemplateFilenamesDescription">This policy configures if supported variables will get replaced in template filenames.
|
||||
|
||||
If you enable this policy, the setting is enabled and supported variables in filenames will get replaced.
|
||||
|
||||
If you disable this policy, the setting is disabled and variables in filenames will not get replaced.
|
||||
|
||||
If you don't configure this policy, the user will be able to control the setting and can enable or disable it.
|
||||
</string>
|
||||
|
||||
<string id="ConfigureAllUtilityGlobalEnabledState">Configure global utility enabled state</string>
|
||||
@@ -234,6 +243,7 @@ If you don't configure this policy, the user takes control over the setting and
|
||||
<string id="ConfigureEnabledUtilityAwake">Awake: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityColorPicker">Color Picker: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityCmdNotFound">Command Not Found: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityCmdPal">CmdPal: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityCropAndLock">Crop And Lock: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityEnvironmentVariables">Environment Variables: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityFancyZones">FancyZones: Configure enabled state</string>
|
||||
@@ -290,6 +300,7 @@ If you don't configure this policy, the user takes control over the setting and
|
||||
<string id="NewPlusHideTemplateFilenameExtension">Hide template filename extension</string>
|
||||
<string id="AllowDiagnosticData">Allow sending diagnostic data</string>
|
||||
<string id="ConfigureRunAtStartup">Configure the run at startup setting</string>
|
||||
<string id="NewPlusReplaceVariablesInTemplateFilenames">Replace variables in template filenames</string>
|
||||
</stringTable>
|
||||
|
||||
<presentationTable>
|
||||
|
||||
@@ -69,6 +69,10 @@
|
||||
<PackageReference Include="WinUIEx" />
|
||||
<!-- HACK: To make sure the version pulled in by Microsoft.Extensions.Hosting is current. -->
|
||||
<PackageReference Include="System.Text.Json" />
|
||||
<!-- This line forces the WebView2 version used by Windows App SDK to be the one we expect from Directory.Packages.props . -->
|
||||
<PackageReference Include="Microsoft.Web.WebView2" />
|
||||
<!-- HACK: CmdPal uses CommunityToolkit.Common directly. Align the version. -->
|
||||
<PackageReference Include="CommunityToolkit.Common" />
|
||||
<Manifest Include="$(ApplicationManifest)" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<!-- Look at Directory.Build.props in root for common stuff as well -->
|
||||
<Import Project="..\..\..\Common.Dotnet.CsWinRT.props" />
|
||||
<Import Project="..\..\..\Common.SelfContained.props" />
|
||||
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>EnvironmentVariables</RootNamespace>
|
||||
@@ -67,6 +67,10 @@
|
||||
<PackageReference Include="WinUIEx" />
|
||||
<!-- HACK: To make sure the version pulled in by Microsoft.Extensions.Hosting is current. -->
|
||||
<PackageReference Include="System.Text.Json" />
|
||||
<!-- This line forces the WebView2 version used by Windows App SDK to be the one we expect from Directory.Packages.props . -->
|
||||
<PackageReference Include="Microsoft.Web.WebView2" />
|
||||
<!-- HACK: CmdPal uses CommunityToolkit.Common directly. Align the version. -->
|
||||
<PackageReference Include="CommunityToolkit.Common" />
|
||||
<Manifest Include="$(ApplicationManifest)" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
<ProjectPriFileName>PowerToys.EnvironmentVariablesUILib.pri</ProjectPriFileName>
|
||||
<GenerateLibraryLayout>true</GenerateLibraryLayout>
|
||||
<IsPackable>true</IsPackable>
|
||||
<!-- The default generated file path exceeds the length limit 260 on the build agent. Using a shorter path as a workaround. -->
|
||||
<CompilerGeneratedFilesOutputPath>$(ProjectDir)obj\g</CompilerGeneratedFilesOutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
@@ -53,4 +55,8 @@
|
||||
<PackageReference Include="System.Text.Json" />
|
||||
<Manifest Include="$(ApplicationManifest)" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="EnsureCompilerGeneratedFilesOutputPathExists" BeforeTargets="XamlPreCompile">
|
||||
<MakeDir Directories="$(CompilerGeneratedFilesOutputPath)" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
||||
@@ -83,7 +83,7 @@ public:
|
||||
std::wstring path = get_module_folderpath(globals::instance);
|
||||
std::wstring packageUri = path + L"\\FileLocksmithContextMenuPackage.msix";
|
||||
|
||||
if (!package::IsPackageRegistered(constants::nonlocalizable::ContextMenuPackageName))
|
||||
if (!package::IsPackageRegisteredWithPowerToysVersion(constants::nonlocalizable::ContextMenuPackageName))
|
||||
{
|
||||
package::RegisterSparsePackage(path, packageUri);
|
||||
}
|
||||
|
||||
@@ -63,6 +63,10 @@
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />
|
||||
<PackageReference Include="System.Drawing.Common" />
|
||||
<PackageReference Include="WinUIEx" />
|
||||
<!-- This line forces the WebView2 version used by Windows App SDK to be the one we expect from Directory.Packages.props . -->
|
||||
<PackageReference Include="Microsoft.Web.WebView2" />
|
||||
<!-- HACK: CmdPal uses CommunityToolkit.Common directly. Align the version. -->
|
||||
<PackageReference Include="CommunityToolkit.Common" />
|
||||
<Manifest Include="$(ApplicationManifest)" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
<!-- This package is a dependency of Microsoft.Extensions.Logging.EventLog, but we need to set it here so we can exclude the assets, so it doesn't conflict with the 8.0.1 dll coming from .NET SDK. -->
|
||||
<ExcludeAssets>runtime</ExcludeAssets> <!-- Should already be present on .net sdk runtime, so we avoid the conflicting runtime version from nuget -->
|
||||
</PackageReference>
|
||||
<!-- HACK: CmdPal uses CommunityToolkit.Common directly. Align the version. -->
|
||||
<PackageReference Include="CommunityToolkit.Common" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -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.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.PowerToys.UITest;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
@@ -18,8 +18,18 @@ namespace Hosts.UITests
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test if Empty-view is shown when no entries are present.
|
||||
/// And 'Add an entry' button from Empty-view is functional.
|
||||
/// Test Empty-view in the Hosts-File-Editor
|
||||
/// <list type="bullet">
|
||||
/// <item>
|
||||
/// <description>Validating Empty-view is shown if no entries in the list.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>Validating Empty-view is NOT shown if 1 or more entries in the list.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>Validating Add-an-entry HyperlinkButton in Empty-view works correctly.</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestEmptyView()
|
||||
@@ -28,20 +38,25 @@ namespace Hosts.UITests
|
||||
this.RemoveAllEntries();
|
||||
|
||||
// 'Add an entry' button (only show-up when list is empty) should be visible
|
||||
Assert.IsTrue(this.FindAll<Button>(By.Name("Add an entry")).Count == 1, "'Add an entry' button should be visible in the empty view");
|
||||
Assert.IsTrue(this.FindAll<HyperlinkButton>("Add an entry").Count == 1, "'Add an entry' button should be visible in the empty view");
|
||||
|
||||
// Click 'Add an entry' from empty-view for adding Host override rule
|
||||
this.Find<Button>(By.Name("Add an entry")).Click();
|
||||
this.Find<HyperlinkButton>("Add an entry").Click();
|
||||
|
||||
this.AddEntry("192.168.0.1", "localhost", false, false);
|
||||
|
||||
// Should have one row now and not more empty view
|
||||
Assert.IsTrue(this.FindAll<Button>(By.Name("Delete")).Count == 1, "Should have one row now");
|
||||
Assert.IsTrue(this.FindAll<Button>(By.Name("Add an entry")).Count == 0, "'Add an entry' button should be invisible if not empty view");
|
||||
Assert.IsTrue(this.FindAll<Button>("Delete").Count == 1, "Should have one row now");
|
||||
Assert.IsTrue(this.FindAll<HyperlinkButton>("Add an entry").Count == 0, "'Add an entry' button should be invisible if not empty view");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test if 'New entry' button is functional
|
||||
/// Test Adding-entry Button in the Hosts-File-Editor
|
||||
/// <list type="bullet">
|
||||
/// <item>
|
||||
/// <description>Validating Adding-entry Button works correctly.</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestAddingEntry()
|
||||
@@ -49,11 +64,155 @@ namespace Hosts.UITests
|
||||
this.CloseWarningDialog();
|
||||
this.RemoveAllEntries();
|
||||
|
||||
Assert.IsTrue(this.FindAll<Button>(By.Name("Delete")).Count == 0, "Should have no row after removing all");
|
||||
Assert.IsTrue(this.FindAll<Button>("Delete").Count == 0, "Should have no row after removing all");
|
||||
|
||||
this.AddEntry("192.168.0.1", "localhost", true);
|
||||
|
||||
Assert.IsTrue(this.FindAll<Button>(By.Name("Delete")).Count == 1, "Should have one row now");
|
||||
Assert.IsTrue(this.FindAll<Button>("Delete").Count == 1, "Should have one row now");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test Multiple-hosts validation logic
|
||||
/// <list type="bullet">
|
||||
/// <item>
|
||||
/// <description>Validating the Add button should be Disabled if more than 9 hosts in one entry.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>Validating the Add button should be Enabled if less or equal 9 hosts in one entry.</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestTooManyHosts()
|
||||
{
|
||||
this.CloseWarningDialog();
|
||||
|
||||
// only at most 9 hosts allowed in one entry
|
||||
string validHosts = string.Join(" ", "host_1", "host_2", "host_3", "host_4", "host_5", "host_6", "host_7", "host_8", "host_9");
|
||||
|
||||
// should not allow to add more than 9 hosts in one entry, hosts are separated by space
|
||||
string inValidHosts = validHosts + " more_host";
|
||||
|
||||
this.Find<Button>("New entry").Click();
|
||||
|
||||
Assert.IsFalse(this.Find<Button>("Add").Enabled, "Add button should be Disabled by default");
|
||||
|
||||
this.Find<TextBox>("Address").SetText("127.0.0.1");
|
||||
|
||||
this.Find<TextBox>("Hosts").SetText(validHosts);
|
||||
Assert.IsTrue(this.Find<Button>("Add").Enabled, "Add button should be Enabled with validHosts");
|
||||
|
||||
this.Find<TextBox>("Hosts").SetText(inValidHosts);
|
||||
Assert.IsFalse(this.Find<Button>("Add").Enabled, "Add button should be Disabled with inValidHosts");
|
||||
|
||||
this.Find<Button>("Cancel").Click();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test Error-message in the Hosts-File-Editor
|
||||
/// <list type="bullet">
|
||||
/// <item>
|
||||
/// <description>Validating error message should be shown if not run as admin.</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestErrorMessageWithNonAdminPermission()
|
||||
{
|
||||
this.CloseWarningDialog();
|
||||
this.RemoveAllEntries();
|
||||
|
||||
// Add new URL override and a warning tip should be shown
|
||||
this.AddEntry("192.168.0.1", "localhost", true);
|
||||
|
||||
Assert.IsTrue(
|
||||
this.FindAll<TextBlock>("The hosts file cannot be saved because the program isn't running as administrator.").Count == 1,
|
||||
"Should display host-file saving error if not run as administrator");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test Filter-panel function in the Hosts-File-Editor
|
||||
/// <list type="bullet">
|
||||
/// <item>
|
||||
/// <description>Validating Address filter matching pattern: contains, endsWith, startsWith, exactly-match.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>Validating Hosts filter matching pattern: contains, endsWith, startsWith, exactly-match.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>Validating click Filters Button to open filter-panel, and click Filter Button again to close filter-panel.</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestFilterControl()
|
||||
{
|
||||
this.CloseWarningDialog();
|
||||
this.RemoveAllEntries();
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
this.AddEntry("192.168.0." + i, "localhost_" + i, true);
|
||||
}
|
||||
|
||||
// Open-filter-panel
|
||||
this.Find<Button>("Filters").Click();
|
||||
Assert.IsTrue(this.FindAll<Button>("Clear filters").Count == 1, "Filter panel should be opened afer click Filter Button");
|
||||
|
||||
var addressFilterCases = new KeyValuePair<string, int>[]
|
||||
{
|
||||
// contains text, expected matched more rows
|
||||
new("168.0", 10),
|
||||
|
||||
// ends with text, expected matched 1 row
|
||||
new("168.0.1", 1),
|
||||
|
||||
// starts with text, expected matched more rows
|
||||
new("192.168.", 10),
|
||||
|
||||
// full text, expected matched 1 row
|
||||
new("192.168.0.1", 1),
|
||||
|
||||
// no-matching text, expected matched no row
|
||||
new("127.0.0", 0),
|
||||
|
||||
// empty filter, should display all rows
|
||||
new(string.Empty, 10),
|
||||
};
|
||||
|
||||
foreach (var (addressFilter, expectedCount) in addressFilterCases)
|
||||
{
|
||||
this.Find<TextBox>("Address").SetText(addressFilter);
|
||||
Assert.IsTrue(this.Find("Entries").FindAll<Button>("Delete").Count == expectedCount);
|
||||
}
|
||||
|
||||
var hostFilterCases = new KeyValuePair<string, int>[]
|
||||
{
|
||||
// contains text, expected matched more rows
|
||||
new("host_", 10),
|
||||
|
||||
// ends with text, expected matched 1 row
|
||||
new("host_4", 1),
|
||||
|
||||
// starts with text, expected matched more rows
|
||||
new("localhost", 10),
|
||||
|
||||
// full text, expected matched 1 row
|
||||
new("localhost_5", 1),
|
||||
|
||||
// empty filter, should display all rows
|
||||
new(string.Empty, 10),
|
||||
};
|
||||
|
||||
foreach (var (hostFilterCase, expectedCount) in hostFilterCases)
|
||||
{
|
||||
this.Find<TextBox>("Hosts").SetText(hostFilterCase);
|
||||
Assert.IsTrue(this.Find("Entries").FindAll<Button>("Delete").Count == expectedCount);
|
||||
}
|
||||
|
||||
// Close-filter-panel
|
||||
this.Find<Button>("Filters").Click();
|
||||
Assert.IsFalse(this.FindAll<Button>("Clear filters").Count == 1, "Filter panel should be closed afer click Filter Button");
|
||||
}
|
||||
|
||||
private void AddEntry(string ip, string host, bool active = true, bool clickAddEntryButton = true)
|
||||
@@ -61,21 +220,21 @@ namespace Hosts.UITests
|
||||
if (clickAddEntryButton)
|
||||
{
|
||||
// Click 'Add an entry' for adding Host override rule
|
||||
this.Find<Button>(By.Name("New entry")).Click();
|
||||
this.Find<Button>("New entry").Click();
|
||||
}
|
||||
|
||||
// Adding a new host override localhost -> 192.168.0.1
|
||||
Assert.IsFalse(this.Find<Button>(By.Name("Add")).Enabled, "Add button should be Disabled by default");
|
||||
Assert.IsFalse(this.Find<Button>("Add").Enabled, "Add button should be Disabled by default");
|
||||
|
||||
Assert.IsTrue(this.Find<TextBox>(By.Name("Address")).SetText(ip, false).Text == ip);
|
||||
Assert.IsTrue(this.Find<TextBox>(By.Name("Hosts")).SetText(host, false).Text == host);
|
||||
Assert.IsTrue(this.Find<TextBox>("Address").SetText(ip).Text == ip);
|
||||
Assert.IsTrue(this.Find<TextBox>("Hosts").SetText(host).Text == host);
|
||||
|
||||
this.Find<ToggleSwitch>(By.Name("Active")).Toggle(active);
|
||||
this.Find<ToggleSwitch>("Active").Toggle(active);
|
||||
|
||||
Assert.IsTrue(this.Find<Button>(By.Name("Add")).Enabled, "Add button should be Enabled after providing valid inputs");
|
||||
Assert.IsTrue(this.Find<Button>("Add").Enabled, "Add button should be Enabled after providing valid inputs");
|
||||
|
||||
// Add the entry
|
||||
this.Find<Button>(By.Name("Add")).Click();
|
||||
this.Find<Button>("Add").Click();
|
||||
|
||||
// 0.5 second delay after adding an entry
|
||||
Task.Delay(500).Wait();
|
||||
@@ -84,25 +243,25 @@ namespace Hosts.UITests
|
||||
private void CloseWarningDialog()
|
||||
{
|
||||
// Find 'Accept' button which come in 'Warning' dialog
|
||||
if (this.FindAll<Window>(By.Name("Warning")).Count > 0 &&
|
||||
this.FindAll<Button>(By.Name("Accept")).Count > 0)
|
||||
if (this.FindAll("Warning").Count > 0 &&
|
||||
this.FindAll<Button>("Accept").Count > 0)
|
||||
{
|
||||
// Hide Warning dialog if any
|
||||
this.Find<Button>(By.Name("Accept")).Click();
|
||||
this.Find<Button>("Accept").Click();
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveAllEntries()
|
||||
{
|
||||
// Delete all existing host-override rules
|
||||
foreach (var deleteBtn in this.FindAll<Button>(By.Name("Delete")))
|
||||
foreach (var deleteBtn in this.FindAll<Button>("Delete"))
|
||||
{
|
||||
deleteBtn.Click();
|
||||
this.Find<Button>(By.Name("Yes")).Click();
|
||||
this.Find<Button>("Yes").Click();
|
||||
}
|
||||
|
||||
// Should have no row left, and no more delete button
|
||||
Assert.IsTrue(this.FindAll<Button>(By.Name("Delete")).Count == 0);
|
||||
Assert.IsTrue(this.FindAll<Button>("Delete").Count == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
129
src/modules/Hosts/Hosts.UITests/HostsSettingTests.cs
Normal file
129
src/modules/Hosts/Hosts.UITests/HostsSettingTests.cs
Normal file
@@ -0,0 +1,129 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.PowerToys.UITest;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Hosts.UITests
|
||||
{
|
||||
[TestClass]
|
||||
public class HostsSettingTests : UITestBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Test Warning Dialog at startup
|
||||
/// <list type="bullet">
|
||||
/// <item>
|
||||
/// <description>Validating Warning-Dialog will be shown if 'Show a warning at startup' toggle is On.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>Validating Warning-Dialog will NOT be shown if 'Show a warning at startup' toggle is Off.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>Validating click 'Quit' button in Warning-Dialog, the Hosts File Editor window would be closed.</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <description>Validating click 'Accept' button in Warning-Dialog, the Hosts File Editor window would NOT be closed.</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestWarningDialog()
|
||||
{
|
||||
this.LaunchFromSetting(showWarning: true);
|
||||
|
||||
// Validating Warning-Dialog will be shown if 'Show a warning at startup' toggle is on
|
||||
Assert.IsTrue(this.FindAll("Warning").Count > 0, "Should show warning dialog");
|
||||
|
||||
// Quit Hosts File Editor
|
||||
this.Find<Button>("Quit").Click();
|
||||
|
||||
// Wait for 500 ms to make sure Hosts File Editor is closed
|
||||
Task.Delay(500).Wait();
|
||||
|
||||
// Validating click 'Quit' button in Warning-Dialog, the Hosts File Editor window would be closed
|
||||
Assert.IsTrue(this.IsHostsFileEditorClosed(), "Hosts File Editor should be closed after click Quit button in Warning Dialog");
|
||||
|
||||
// Re-attaching to Setting Windows
|
||||
this.Session.Attach(PowerToysModule.PowerToysSettings);
|
||||
|
||||
this.Find<Button>("Launch Hosts File Editor").Click();
|
||||
|
||||
// wait for 500 ms to make sure Hosts File Editor is launched
|
||||
Task.Delay(500).Wait();
|
||||
|
||||
this.Session.Attach(PowerToysModule.Hosts);
|
||||
|
||||
// Should show warning dialog
|
||||
Assert.IsTrue(this.FindAll("Warning").Count > 0, "Should show warning dialog");
|
||||
|
||||
// Quit Hosts File Editor
|
||||
this.Find<Button>("Accept").Click();
|
||||
|
||||
Task.Delay(500).Wait();
|
||||
|
||||
// Validating click 'Accept' button in Warning-Dialog, the Hosts File Editor window would NOT be closed
|
||||
Assert.IsFalse(this.IsHostsFileEditorClosed(), "Hosts File Editor should NOT be closed after click Accept button in Warning Dialog");
|
||||
|
||||
// Close Hosts File Editor window
|
||||
this.Session.Find<Window>("Hosts File Editor").Close();
|
||||
|
||||
// Restore back to PowerToysSettings Session
|
||||
this.Session.Attach(PowerToysModule.PowerToysSettings);
|
||||
|
||||
this.LaunchFromSetting(showWarning: false);
|
||||
|
||||
// Should NOT show warning dialog
|
||||
Assert.IsTrue(this.FindAll("Warning").Count == 0, "Should NOT show warning dialog");
|
||||
|
||||
// Host Editor Window should not be closed
|
||||
Assert.IsFalse(this.IsHostsFileEditorClosed(), "Hosts File Editor should NOT be closed");
|
||||
|
||||
// Close Hosts File Editor window
|
||||
this.Session.Find<Window>("Hosts File Editor").Close();
|
||||
|
||||
// Restore back to PowerToysSettings Session
|
||||
this.Session.Attach(PowerToysModule.PowerToysSettings);
|
||||
}
|
||||
|
||||
private bool IsHostsFileEditorClosed()
|
||||
{
|
||||
try
|
||||
{
|
||||
this.Session.FindAll<Window>("Hosts File Editor");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Validate if editor window closed by checking exception.Message
|
||||
return ex.Message.Contains("Currently selected window has been closed");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void LaunchFromSetting(bool showWarning = false, bool launchAsAdmin = false)
|
||||
{
|
||||
// Goto Hosts File Editor setting page
|
||||
if (this.FindAll<NavigationViewItem>("Hosts File Editor").Count == 0)
|
||||
{
|
||||
// Expand Advanced list-group if needed
|
||||
this.Find<NavigationViewItem>("Advanced").Click();
|
||||
}
|
||||
|
||||
this.Find<NavigationViewItem>("Hosts File Editor").Click();
|
||||
|
||||
this.Find<ToggleSwitch>("Enable Hosts File Editor").Toggle(true);
|
||||
this.Find<ToggleSwitch>("Launch as administrator").Toggle(launchAsAdmin);
|
||||
this.Find<ToggleSwitch>("Show a warning at startup").Toggle(showWarning);
|
||||
|
||||
// launch Hosts File Editor
|
||||
this.Find<Button>("Launch Hosts File Editor").Click();
|
||||
|
||||
Task.Delay(500).Wait();
|
||||
|
||||
this.Session.Attach(PowerToysModule.Hosts);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
## This is for tracking UI-Tests migration progress for Hosts File Editor Module
|
||||
Refer to [release check list] (https://github.com/microsoft/PowerToys/blob/releaseChecklist/doc/releases/tests-checklist-template.md#hosts-file-editor) for all manual tests.
|
||||
|
||||
### Existing Manual Test-cases run by previous PowerToys owner
|
||||
For existing manual test-cases, we will convert them to UI-Tests and run them in CI and Release pipeline
|
||||
|
||||
* Launch Host File Editor:
|
||||
- [x] Verify the application exits if "Quit" is clicked on the initial warning. (**HostsSettingTests.TestWarningDialog**)
|
||||
- [x] Launch Host File Editor again and click "Accept". The module should not close. (**HostModuleTests.TestEmptyView**)
|
||||
- [ ] Launch Host File Editor again and click "Accept". The module should not close. Open the hosts file (`%WinDir%\System32\Drivers\Etc`) in a text editor that auto-refreshes so you can see the changes applied by the editor in real time. (VSCode is an editor like this, for example)
|
||||
- [ ] Enable and disable lines and verify they are applied to the file.
|
||||
- [ ] Add a new entry and verify it's applied.
|
||||
- [ ] Add manually an entry with more than 9 hosts in hosts file (Windows limitation) and verify it is split correctly on loading and the info bar is shown.
|
||||
- [x] Try to filter for lines and verify you can find them. (**HostModuleTests.TestFilterControl**)
|
||||
- [ ] Click the "Open hosts file" button and verify it opens in your default editor. (likely Notepad)
|
||||
* Test the different settings and verify they are applied:
|
||||
- [ ] Launch as Administrator.
|
||||
- [x] Show a warning at startup. (**HostsSettingTests.TestWarningDialog**)
|
||||
- [ ] Additional lines position.
|
||||
|
||||
### Additional UI-Tests cases
|
||||
- [x] Add manually an entry with more than 9 hosts and Add button should be disabled. (**HostModuleTests.TestTooManyHosts**)
|
||||
- [x] Add manually an entry with less or equal 9 hosts and Add button should be enabled. (**HostModuleTests.TestTooManyHosts**)
|
||||
- [x] Should show empty view if no entries. (**HostModuleTests.TestEmptyView**)
|
||||
- [x] Add a new entry with valid or invalid input (**HostModuleTests.TestAddHost**)
|
||||
- [x] Show save host file error if not run as Administrator. (**HostModuleTests.TestErrorMessageWithNonAdminPermission**)
|
||||
@@ -66,6 +66,10 @@
|
||||
<PackageReference Include="WinUIEx" />
|
||||
<!-- HACK: To make sure the version pulled in by Microsoft.Extensions.Hosting is current. -->
|
||||
<PackageReference Include="System.Text.Json" />
|
||||
<!-- This line forces the WebView2 version used by Windows App SDK to be the one we expect from Directory.Packages.props . -->
|
||||
<PackageReference Include="Microsoft.Web.WebView2" />
|
||||
<!-- HACK: CmdPal uses CommunityToolkit.Common directly. Align the version. -->
|
||||
<PackageReference Include="CommunityToolkit.Common" />
|
||||
<Manifest Include="$(ApplicationManifest)" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.IO.Abstractions;
|
||||
using System.Threading;
|
||||
|
||||
using Common.UI;
|
||||
using HostsEditor.Telemetry;
|
||||
using HostsUILib.Helpers;
|
||||
using HostsUILib.Settings;
|
||||
using HostsUILib.ViewModels;
|
||||
@@ -38,6 +39,8 @@ namespace Hosts
|
||||
/// </summary>
|
||||
public App()
|
||||
{
|
||||
PowerToysTelemetry.Log.WriteEvent(new HostEditorStartEvent() { TimeStamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() });
|
||||
|
||||
string appLanguage = LanguageHelper.LoadLanguage();
|
||||
if (!string.IsNullOrEmpty(appLanguage))
|
||||
{
|
||||
|
||||
@@ -2,10 +2,13 @@
|
||||
// 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 Hosts.Helpers;
|
||||
using HostsEditor.Telemetry;
|
||||
using HostsUILib.Helpers;
|
||||
using HostsUILib.Views;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
@@ -44,6 +47,8 @@ namespace Hosts
|
||||
Activated += MainWindow_Activated;
|
||||
|
||||
MainPage = Host.GetService<HostsMainPage>();
|
||||
|
||||
PowerToysTelemetry.Log.WriteEvent(new HostEditorStartFinishEvent() { TimeStamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() });
|
||||
}
|
||||
|
||||
private void MainWindow_Activated(object sender, WindowActivatedEventArgs args)
|
||||
|
||||
18
src/modules/Hosts/Hosts/Telemetry/HostEditorStartEvent.cs
Normal file
18
src/modules/Hosts/Hosts/Telemetry/HostEditorStartEvent.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
// 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.Tracing;
|
||||
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace HostsEditor.Telemetry;
|
||||
|
||||
[EventData]
|
||||
public class HostEditorStartEvent() : EventBase, IEvent
|
||||
{
|
||||
public long TimeStamp { get; set; }
|
||||
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// 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.Tracing;
|
||||
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace HostsEditor.Telemetry;
|
||||
|
||||
[EventData]
|
||||
public class HostEditorStartFinishEvent() : EventBase, IEvent
|
||||
{
|
||||
public long TimeStamp { get; set; }
|
||||
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
}
|
||||
@@ -202,7 +202,9 @@ namespace HostsUILib.ViewModels
|
||||
}
|
||||
|
||||
_entries.CollectionChanged += Entries_CollectionChanged;
|
||||
#pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code
|
||||
Entries = new AdvancedCollectionView(_entries, true);
|
||||
#pragma warning restore IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code
|
||||
Entries.SortDescriptions.Add(new SortDescription(nameof(Entry.Id), SortDirection.Ascending));
|
||||
ApplyFilters();
|
||||
OnPropertyChanged(nameof(Entries));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.241114003\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.241114003\build\native\Microsoft.WindowsAppSDK.props')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.250205002\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.250205002\build\native\Microsoft.WindowsAppSDK.props')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.props')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<PropertyGroup Label="Globals">
|
||||
@@ -140,8 +140,8 @@
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2739.15\build\native\Microsoft.Web.WebView2.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2739.15\build\native\Microsoft.Web.WebView2.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.241114003\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.241114003\build\native\Microsoft.WindowsAppSDK.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.250205002\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.250205002\build\native\Microsoft.WindowsAppSDK.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
@@ -152,8 +152,8 @@
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2739.15\build\native\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2739.15\build\native\Microsoft.Web.WebView2.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.241114003\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.241114003\build\native\Microsoft.WindowsAppSDK.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.241114003\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.241114003\build\native\Microsoft.WindowsAppSDK.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.250205002\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.250205002\build\native\Microsoft.WindowsAppSDK.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.250205002\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.250205002\build\native\Microsoft.WindowsAppSDK.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Web.WebView2" version="1.0.2739.15" targetFramework="native" />
|
||||
<package id="Microsoft.Web.WebView2" version="1.0.2903.40" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.231216.1" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.SDK.BuildTools" version="10.0.22621.2428" targetFramework="native" />
|
||||
<package id="Microsoft.WindowsAppSDK" version="1.6.241114003" targetFramework="native" />
|
||||
<package id="Microsoft.WindowsAppSDK" version="1.6.250205002" targetFramework="native" />
|
||||
</packages>
|
||||
@@ -13,7 +13,7 @@
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<UseWinUI>true</UseWinUI>
|
||||
<Platforms>x64;ARM64</Platforms>
|
||||
<GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
|
||||
<GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
|
||||
@@ -55,6 +55,8 @@
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />
|
||||
<PackageReference Include="WinUIEx" />
|
||||
<!-- This line forces the WebView2 version used by Windows App SDK to be the one we expect from Directory.Packages.props . -->
|
||||
<PackageReference Include="Microsoft.Web.WebView2" />
|
||||
<Manifest Include="$(ApplicationManifest)" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
string filePath = stringData;
|
||||
|
||||
_ = Common.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||
_ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||
{
|
||||
if (File.Exists(filePath) || Directory.Exists(filePath))
|
||||
{
|
||||
@@ -579,7 +579,7 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
if (postAct.Equals("desktop", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_ = ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||
_ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||
{
|
||||
savingFolder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\MouseWithoutBorders\\";
|
||||
|
||||
@@ -696,7 +696,7 @@ namespace MouseWithoutBorders
|
||||
Path.GetFileName(fileName),
|
||||
remoteMachine);
|
||||
|
||||
_ = ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||
_ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||
{
|
||||
ProcessStartInfo startInfo = new();
|
||||
startInfo.UseShellExecute = true;
|
||||
|
||||
@@ -1,277 +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.Diagnostics.CodeAnalysis;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// <summary>
|
||||
// Keyboard/Mouse hook callback implementation.
|
||||
// </summary>
|
||||
// <history>
|
||||
// 2008 created by Truong Do (ductdo).
|
||||
// 2009-... modified by Truong Do (TruongDo).
|
||||
// 2023- Included in PowerToys.
|
||||
// </history>
|
||||
using MouseWithoutBorders.Class;
|
||||
using MouseWithoutBorders.Core;
|
||||
using MouseWithoutBorders.Form;
|
||||
|
||||
using Thread = MouseWithoutBorders.Core.Thread;
|
||||
|
||||
namespace MouseWithoutBorders
|
||||
{
|
||||
internal partial class Common
|
||||
{
|
||||
private static readonly DATA KeybdPackage = new();
|
||||
private static readonly DATA MousePackage = new();
|
||||
#pragma warning disable SA1307 // Accessible fields should begin with upper-case names
|
||||
internal static ulong inputEventCount;
|
||||
internal static ulong invalidPackageCount;
|
||||
#pragma warning restore SA1307
|
||||
internal static int MOVE_MOUSE_RELATIVE = 100000;
|
||||
internal static int XY_BY_PIXEL = 300000;
|
||||
|
||||
static Common()
|
||||
{
|
||||
}
|
||||
|
||||
internal static ulong InvalidPackageCount
|
||||
{
|
||||
get => Common.invalidPackageCount;
|
||||
set => Common.invalidPackageCount = value;
|
||||
}
|
||||
|
||||
internal static ulong InputEventCount
|
||||
{
|
||||
get => Common.inputEventCount;
|
||||
set => Common.inputEventCount = value;
|
||||
}
|
||||
|
||||
internal static ulong RealInputEventCount
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
private static Point actualLastPos;
|
||||
private static int myLastX;
|
||||
private static int myLastY;
|
||||
|
||||
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Dotnet port with style preservation")]
|
||||
internal static void MouseEvent(MOUSEDATA e, int dx, int dy)
|
||||
{
|
||||
try
|
||||
{
|
||||
PaintCount = 0;
|
||||
bool switchByMouseEnabled = IsSwitchingByMouseEnabled();
|
||||
|
||||
if (switchByMouseEnabled && Sk != null && (DesMachineID == MachineID || !Setting.Values.MoveMouseRelatively) && e.dwFlags == WM_MOUSEMOVE)
|
||||
{
|
||||
Point p = MachineStuff.MoveToMyNeighbourIfNeeded(e.X, e.Y, MachineStuff.desMachineID);
|
||||
|
||||
if (!p.IsEmpty)
|
||||
{
|
||||
HasSwitchedMachineSinceLastCopy = true;
|
||||
|
||||
Logger.LogDebug(string.Format(
|
||||
CultureInfo.CurrentCulture,
|
||||
"***** Host Machine: newDesMachineIdEx set = [{0}]. Mouse is now at ({1},{2})",
|
||||
MachineStuff.newDesMachineIdEx,
|
||||
e.X,
|
||||
e.Y));
|
||||
|
||||
myLastX = e.X;
|
||||
myLastY = e.Y;
|
||||
|
||||
PrepareToSwitchToMachine(MachineStuff.newDesMachineIdEx, p);
|
||||
}
|
||||
}
|
||||
|
||||
if (MachineStuff.desMachineID != MachineID && MachineStuff.SwitchLocation.Count <= 0)
|
||||
{
|
||||
MousePackage.Des = MachineStuff.desMachineID;
|
||||
MousePackage.Type = PackageType.Mouse;
|
||||
MousePackage.Md.dwFlags = e.dwFlags;
|
||||
MousePackage.Md.WheelDelta = e.WheelDelta;
|
||||
|
||||
// Relative move
|
||||
if (Setting.Values.MoveMouseRelatively && Math.Abs(dx) >= MOVE_MOUSE_RELATIVE && Math.Abs(dy) >= MOVE_MOUSE_RELATIVE)
|
||||
{
|
||||
MousePackage.Md.X = dx;
|
||||
MousePackage.Md.Y = dy;
|
||||
}
|
||||
else
|
||||
{
|
||||
MousePackage.Md.X = (e.X - MachineStuff.primaryScreenBounds.Left) * 65535 / screenWidth;
|
||||
MousePackage.Md.Y = (e.Y - MachineStuff.primaryScreenBounds.Top) * 65535 / screenHeight;
|
||||
}
|
||||
|
||||
SkSend(MousePackage, null, false);
|
||||
|
||||
if (MousePackage.Md.dwFlags is WM_LBUTTONUP or WM_RBUTTONUP)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
|
||||
NativeMethods.GetCursorPos(ref actualLastPos);
|
||||
|
||||
if (actualLastPos != Common.LastPos)
|
||||
{
|
||||
Logger.LogDebug($"Mouse cursor has moved unexpectedly: Expected: {Common.LastPos}, actual: {actualLastPos}.");
|
||||
Common.LastPos = actualLastPos;
|
||||
}
|
||||
}
|
||||
|
||||
#if SHOW_ON_WINLOGON_EX
|
||||
if (RunOnLogonDesktop && e.dwFlags == WM_RBUTTONUP &&
|
||||
desMachineID == machineID &&
|
||||
e.x > 2 && e.x < 100 && e.y > 2 && e.y < 20)
|
||||
{
|
||||
DoSomethingInUIThread(delegate()
|
||||
{
|
||||
MainForm.HideMenuWhenRunOnLogonDesktop();
|
||||
MainForm.MainMenu.Hide();
|
||||
MainForm.MainMenu.Show(e.x - 5, e.y - 3);
|
||||
});
|
||||
}
|
||||
#endif
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log(ex);
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool IsSwitchingByMouseEnabled()
|
||||
{
|
||||
return (EasyMouseOption)Setting.Values.EasyMouse == EasyMouseOption.Enable || InputHook.EasyMouseKeyDown;
|
||||
}
|
||||
|
||||
internal static void PrepareToSwitchToMachine(ID newDesMachineID, Point desMachineXY)
|
||||
{
|
||||
Logger.LogDebug($"PrepareToSwitchToMachine: newDesMachineID = {newDesMachineID}, desMachineXY = {desMachineXY}");
|
||||
|
||||
if (((GetTick() - MachineStuff.lastJump < 100) && (GetTick() - MachineStuff.lastJump > 0)) || MachineStuff.desMachineID == ID.ALL)
|
||||
{
|
||||
Logger.LogDebug("PrepareToSwitchToMachine: lastJump");
|
||||
return;
|
||||
}
|
||||
|
||||
MachineStuff.lastJump = GetTick();
|
||||
|
||||
string newDesMachineName = MachineStuff.NameFromID(newDesMachineID);
|
||||
|
||||
if (!IsConnectedTo(newDesMachineID))
|
||||
{// Connection lost, cancel switching
|
||||
Logger.LogDebug("No active connection found for " + newDesMachineName);
|
||||
|
||||
// ShowToolTip("No active connection found for [" + newDesMachineName + "]!", 500);
|
||||
}
|
||||
else
|
||||
{
|
||||
MachineStuff.newDesMachineID = newDesMachineID;
|
||||
MachineStuff.SwitchLocation.X = desMachineXY.X;
|
||||
MachineStuff.SwitchLocation.Y = desMachineXY.Y;
|
||||
MachineStuff.SwitchLocation.ResetCount();
|
||||
_ = EvSwitch.Set();
|
||||
|
||||
// PostMessage(mainForm.Handle, WM_SWITCH, IntPtr.Zero, IntPtr.Zero);
|
||||
if (newDesMachineID != DragDrop.DragMachine)
|
||||
{
|
||||
if (!DragDrop.IsDragging && !DragDrop.IsDropping)
|
||||
{
|
||||
if (DragDrop.MouseDown && !RunOnLogonDesktop && !RunOnScrSaverDesktop)
|
||||
{
|
||||
DragDrop.DragDropStep02();
|
||||
}
|
||||
}
|
||||
else if (DragDrop.DragMachine != (ID)1)
|
||||
{
|
||||
DragDrop.ChangeDropMachine();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DragDrop.DragDropStep11();
|
||||
}
|
||||
|
||||
// Change des machine
|
||||
if (MachineStuff.desMachineID != newDesMachineID)
|
||||
{
|
||||
Logger.LogDebug("MouseEvent: Switching to new machine:" + newDesMachineName);
|
||||
|
||||
// Ask current machine to hide the Mouse cursor
|
||||
if (newDesMachineID != ID.ALL && MachineStuff.desMachineID != MachineID)
|
||||
{
|
||||
SendPackage(MachineStuff.desMachineID, PackageType.HideMouse);
|
||||
}
|
||||
|
||||
DesMachineID = newDesMachineID;
|
||||
|
||||
if (MachineStuff.desMachineID == MachineID)
|
||||
{
|
||||
if (GetTick() - clipboardCopiedTime < BIG_CLIPBOARD_DATA_TIMEOUT)
|
||||
{
|
||||
clipboardCopiedTime = 0;
|
||||
Common.GetRemoteClipboard("PrepareToSwitchToMachine");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ask the new active machine to get clipboard data (if the data is too big)
|
||||
SendPackage(MachineStuff.desMachineID, PackageType.MachineSwitched);
|
||||
}
|
||||
|
||||
_ = Interlocked.Increment(ref switchCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static void SaveSwitchCount()
|
||||
{
|
||||
if (SwitchCount > 0)
|
||||
{
|
||||
_ = Task.Run(() =>
|
||||
{
|
||||
Setting.Values.SwitchCount += SwitchCount;
|
||||
_ = Interlocked.Exchange(ref switchCount, 0);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
internal static void KeybdEvent(KEYBDDATA e)
|
||||
{
|
||||
try
|
||||
{
|
||||
PaintCount = 0;
|
||||
if (MachineStuff.desMachineID != MachineStuff.newDesMachineID)
|
||||
{
|
||||
Logger.LogDebug("KeybdEvent: Switching to new machine...");
|
||||
DesMachineID = MachineStuff.newDesMachineID;
|
||||
}
|
||||
|
||||
if (MachineStuff.desMachineID != MachineID)
|
||||
{
|
||||
KeybdPackage.Des = MachineStuff.desMachineID;
|
||||
KeybdPackage.Type = PackageType.Keyboard;
|
||||
KeybdPackage.Kd = e;
|
||||
KeybdPackage.DateTime = GetTick();
|
||||
SkSend(KeybdPackage, null, false);
|
||||
if (KeybdPackage.Kd.dwFlags is WM_KEYUP or WM_SYSKEYUP)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,526 +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.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
using System.Windows.Forms;
|
||||
|
||||
// <summary>
|
||||
// Some other helper methods.
|
||||
// </summary>
|
||||
// <history>
|
||||
// 2008 created by Truong Do (ductdo).
|
||||
// 2009-... modified by Truong Do (TruongDo).
|
||||
// 2023- Included in PowerToys.
|
||||
// </history>
|
||||
using Microsoft.Win32;
|
||||
using MouseWithoutBorders.Class;
|
||||
using MouseWithoutBorders.Core;
|
||||
using static System.Windows.Forms.Control;
|
||||
|
||||
namespace MouseWithoutBorders
|
||||
{
|
||||
internal partial class Common
|
||||
{
|
||||
internal const string HELPER_FORM_TEXT = "Mouse without Borders Helper";
|
||||
internal const string HelperProcessName = "PowerToys.MouseWithoutBordersHelper";
|
||||
private static bool signalHelperToExit;
|
||||
private static bool signalWatchDogToExit;
|
||||
internal static long WndProcCounter;
|
||||
|
||||
private static void WatchDogThread()
|
||||
{
|
||||
long oldCounter = WndProcCounter;
|
||||
|
||||
do
|
||||
{
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
|
||||
if (signalWatchDogToExit)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (BlockingUI)
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
|
||||
if (WndProcCounter == oldCounter)
|
||||
{
|
||||
Process p = Process.GetCurrentProcess();
|
||||
string procInfo = $"{p.PrivateMemorySize64 / 1024 / 1024}MB, {p.TotalProcessorTime}, {Environment.ProcessorCount}.";
|
||||
string threadStacks = $"{procInfo} {Thread.DumpThreadsStack()}";
|
||||
Logger.TelemetryLogTrace(threadStacks, SeverityLevel.Error);
|
||||
break;
|
||||
}
|
||||
|
||||
oldCounter = WndProcCounter;
|
||||
}
|
||||
while (true);
|
||||
}
|
||||
|
||||
private static void HelperThread()
|
||||
{
|
||||
// SuppressFlow fixes an issue on service mode, where the helper process can't get enough permissions to be started again.
|
||||
// More details can be found on: https://github.com/microsoft/PowerToys/pull/36892
|
||||
using var asyncFlowControl = System.Threading.ExecutionContext.SuppressFlow();
|
||||
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
_ = EvSwitch.WaitOne(); // Switching to another machine?
|
||||
|
||||
if (signalHelperToExit)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (MachineStuff.NewDesMachineID != Common.MachineID && MachineStuff.NewDesMachineID != ID.ALL)
|
||||
{
|
||||
HideMouseCursor(false);
|
||||
Common.MainFormDotEx(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MachineStuff.SwitchLocation.Count > 0)
|
||||
{
|
||||
MachineStuff.SwitchLocation.Count--;
|
||||
|
||||
// When we want to move mouse by pixels, we add 300k to x and y (search for XY_BY_PIXEL for other related code).
|
||||
Logger.LogDebug($"+++++ Moving mouse to {MachineStuff.SwitchLocation.X}, {MachineStuff.SwitchLocation.Y}");
|
||||
|
||||
// MaxXY = 65535 so 100k is safe.
|
||||
if (MachineStuff.SwitchLocation.X > XY_BY_PIXEL - 100000 || MachineStuff.SwitchLocation.Y > XY_BY_PIXEL - 100000)
|
||||
{
|
||||
InputSimulation.MoveMouse(MachineStuff.SwitchLocation.X - XY_BY_PIXEL, MachineStuff.SwitchLocation.Y - XY_BY_PIXEL);
|
||||
}
|
||||
else
|
||||
{
|
||||
InputSimulation.MoveMouseEx(MachineStuff.SwitchLocation.X, MachineStuff.SwitchLocation.Y);
|
||||
}
|
||||
|
||||
Common.MainFormDot();
|
||||
}
|
||||
}
|
||||
|
||||
if (MachineStuff.NewDesMachineID == Common.MachineID)
|
||||
{
|
||||
ReleaseAllKeys();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log(e);
|
||||
}
|
||||
|
||||
signalHelperToExit = false;
|
||||
Logger.LogDebug("^^^Helper Thread exiting...^^^");
|
||||
}
|
||||
|
||||
internal static void MainFormDotEx(bool bCheckTS)
|
||||
{
|
||||
Logger.LogDebug("***** MainFormDotEx:");
|
||||
|
||||
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
|
||||
{
|
||||
int left = MachineStuff.PrimaryScreenBounds.Left + ((MachineStuff.PrimaryScreenBounds.Right - MachineStuff.PrimaryScreenBounds.Left) / 2) - 1;
|
||||
int top = Setting.Values.HideMouse ? 3 : MachineStuff.PrimaryScreenBounds.Top + ((MachineStuff.PrimaryScreenBounds.Bottom - MachineStuff.PrimaryScreenBounds.Top) / 2);
|
||||
|
||||
Common.MainFormVisible = true;
|
||||
|
||||
if (Setting.Values.HideMouse && Setting.Values.StealFocusWhenSwitchingMachine && Common.SendMessageToHelper(0x407, new IntPtr(left), new IntPtr(top), true) == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
/* When user just switches to the Logon desktop, user is actually on the "Windows Default Lock Screen" (LockApp).
|
||||
* If a click is sent to this during switch, it actually triggers a desktop switch on the local machine causing a reconnection affecting the machine switch.
|
||||
* We can detect and skip in this case.
|
||||
* */
|
||||
IntPtr foreGroundWindow = NativeMethods.GetForegroundWindow();
|
||||
string foreGroundWindowText = GetText(foreGroundWindow);
|
||||
|
||||
bool mouseClick = true;
|
||||
|
||||
if (foreGroundWindowText.Equals("Windows Default Lock Screen", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
mouseClick = false;
|
||||
}
|
||||
|
||||
// Window title may be localized, check process name:
|
||||
if (mouseClick)
|
||||
{
|
||||
_ = NativeMethods.GetWindowThreadProcessId(foreGroundWindow, out uint pid);
|
||||
|
||||
if (pid > 0)
|
||||
{
|
||||
string foreGroundWindowProcess = Process.GetProcessById((int)pid)?.ProcessName;
|
||||
|
||||
if (foreGroundWindowProcess.Equals("LockApp", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
mouseClick = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mouseClick)
|
||||
{
|
||||
InputSimulation.MouseClickDotForm(left + 1, top + 1);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CustomCursor.ShowFakeMouseCursor(int.MinValue, int.MinValue);
|
||||
}
|
||||
|
||||
internal static void MainForm3Pixels()
|
||||
{
|
||||
Logger.LogDebug("***** MainFormDotLarge:");
|
||||
|
||||
DoSomethingInUIThread(
|
||||
() =>
|
||||
{
|
||||
MainForm.Left = MachineStuff.PrimaryScreenBounds.Left + ((MachineStuff.PrimaryScreenBounds.Right - MachineStuff.PrimaryScreenBounds.Left) / 2) - 2;
|
||||
MainForm.Top = Setting.Values.HideMouse ? 3 : MachineStuff.PrimaryScreenBounds.Top + ((MachineStuff.PrimaryScreenBounds.Bottom - MachineStuff.PrimaryScreenBounds.Top) / 2) - 1;
|
||||
MainForm.Width = 3;
|
||||
MainForm.Height = 3;
|
||||
MainForm.Opacity = 0.11D;
|
||||
MainForm.TopMost = true;
|
||||
|
||||
if (Setting.Values.HideMouse)
|
||||
{
|
||||
MainForm.BackColor = Color.Black;
|
||||
MainForm.Show();
|
||||
Common.MainFormVisible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
MainForm.BackColor = Color.White;
|
||||
MainForm.Hide();
|
||||
Common.MainFormVisible = false;
|
||||
}
|
||||
},
|
||||
true);
|
||||
|
||||
CustomCursor.ShowFakeMouseCursor(int.MinValue, int.MinValue);
|
||||
}
|
||||
|
||||
internal static void MainFormDot()
|
||||
{
|
||||
DoSomethingInUIThread(
|
||||
() =>
|
||||
{
|
||||
_ = Common.SendMessageToHelper(0x408, IntPtr.Zero, IntPtr.Zero, false);
|
||||
|
||||
MainForm.Left = MachineStuff.PrimaryScreenBounds.Left + ((MachineStuff.PrimaryScreenBounds.Right - MachineStuff.PrimaryScreenBounds.Left) / 2) - 1;
|
||||
MainForm.Top = Setting.Values.HideMouse ? 3 : MachineStuff.PrimaryScreenBounds.Top + ((MachineStuff.PrimaryScreenBounds.Bottom - MachineStuff.PrimaryScreenBounds.Top) / 2);
|
||||
MainForm.Width = 1;
|
||||
MainForm.Height = 1;
|
||||
MainForm.Opacity = 0.15;
|
||||
MainForm.Hide();
|
||||
Common.MainFormVisible = false;
|
||||
},
|
||||
true);
|
||||
|
||||
CustomCursor.ShowFakeMouseCursor(int.MinValue, int.MinValue);
|
||||
}
|
||||
|
||||
internal static void ToggleIcon()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (toggleIconsIndex < TOGGLE_ICONS_SIZE)
|
||||
{
|
||||
Common.DoSomethingInUIThread(() => Common.MainForm.ChangeIcon(toggleIcons[toggleIconsIndex++]));
|
||||
}
|
||||
else
|
||||
{
|
||||
toggleIconsIndex = 0;
|
||||
toggleIcons = null;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log(e);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void RunDDHelper(bool cleanUp = false)
|
||||
{
|
||||
if (Common.RunOnLogonDesktop || Common.RunOnScrSaverDesktop)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (cleanUp)
|
||||
{
|
||||
try
|
||||
{
|
||||
Process[] ps = Process.GetProcessesByName(HelperProcessName);
|
||||
foreach (Process p in ps)
|
||||
{
|
||||
p.KillProcess();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log(e);
|
||||
_ = Common.SendMessageToHelper(SharedConst.QUIT_CMD, IntPtr.Zero, IntPtr.Zero);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Common.IsMyDesktopActive())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Common.IpcChannelCreated)
|
||||
{
|
||||
Logger.TelemetryLogTrace($"{nameof(Common.IpcChannelCreated)} = {Common.IpcChannelCreated}. {Logger.GetStackTrace(new StackTrace())}", SeverityLevel.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!MainForm.IsDisposed)
|
||||
{
|
||||
MainForm.NotifyIcon.Visible = false;
|
||||
MainForm.NotifyIcon.Visible = Setting.Values.ShowOriginalUI;
|
||||
}
|
||||
|
||||
IntPtr h = (IntPtr)NativeMethods.FindWindow(null, Common.HELPER_FORM_TEXT);
|
||||
|
||||
if (h.ToInt32() <= 0)
|
||||
{
|
||||
_ = Common.CreateProcessInInputDesktopSession(
|
||||
$"\"{Path.GetDirectoryName(Application.ExecutablePath)}\\{HelperProcessName}.exe\"",
|
||||
string.Empty,
|
||||
Common.GetInputDesktop(),
|
||||
0);
|
||||
|
||||
HasSwitchedMachineSinceLastCopy = true;
|
||||
|
||||
// Common.CreateLowIntegrityProcess("\"" + Path.GetDirectoryName(Application.ExecutablePath) + "\\MouseWithoutBordersHelper.exe\"", string.Empty, 0, false, 0);
|
||||
var processes = Process.GetProcessesByName(HelperProcessName);
|
||||
if (processes?.Length == 0)
|
||||
{
|
||||
Logger.Log("Unable to start helper process.");
|
||||
Common.ShowToolTip("Error starting Mouse Without Borders Helper, clipboard sharing will not work!", 5000, ToolTipIcon.Error);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log("Helper process started.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var processes = Process.GetProcessesByName(HelperProcessName);
|
||||
if (processes?.Length > 0)
|
||||
{
|
||||
Logger.Log("Helper process found running.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log("Invalid helper process found running.");
|
||||
Common.ShowToolTip("Error finding Mouse Without Borders Helper, clipboard sharing will not work!", 5000, ToolTipIcon.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static int SendMessageToHelper(int msg, IntPtr wparam, IntPtr lparam, bool wait = true, bool log = true)
|
||||
{
|
||||
int h = NativeMethods.FindWindow(null, Common.HELPER_FORM_TEXT);
|
||||
int rv = -1;
|
||||
|
||||
if (h > 0)
|
||||
{
|
||||
rv = wait
|
||||
? (int)NativeMethods.SendMessage((IntPtr)h, msg, wparam, lparam)
|
||||
: NativeMethods.PostMessage((IntPtr)h, msg, wparam, lparam) ? 1 : 0;
|
||||
}
|
||||
|
||||
if (log)
|
||||
{
|
||||
Logger.LogDebug($"SendMessageToHelper: HelperWindow={h}, Return={rv}, msg={msg}, w={wparam.ToInt32()}, l={lparam.ToInt32()}, Post={!wait}");
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
internal static bool IsWindows8AndUp()
|
||||
{
|
||||
return (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 2)
|
||||
|| Environment.OSVersion.Version.Major > 6;
|
||||
}
|
||||
|
||||
internal static string GetMiniLog(IEnumerable<ControlCollection> optionControls)
|
||||
{
|
||||
string log = string.Empty;
|
||||
|
||||
log += "=============================================================================================================================\r\n";
|
||||
log += $"{Application.ProductName} version {Application.ProductVersion}\r\n";
|
||||
|
||||
log += $"{Setting.Values.Username}/{GetDebugInfo(MyKey)}\r\n";
|
||||
log += $"{MachineName}/{MachineID}/{DesMachineID}\r\n";
|
||||
log += $"Id: {Setting.Values.DeviceId}\r\n";
|
||||
log += $"Matrix: {string.Join(",", MachineStuff.MachineMatrix)}\r\n";
|
||||
log += $"McPool: {Setting.Values.MachinePoolString}\r\n";
|
||||
|
||||
log += "\r\nOPTIONS:\r\n";
|
||||
|
||||
foreach (ControlCollection controlCollection in optionControls)
|
||||
{
|
||||
foreach (object c in controlCollection)
|
||||
{
|
||||
if (c is CheckBox checkBox)
|
||||
{
|
||||
log += $"({(checkBox.Checked ? 1 : 0)}) {checkBox.Text}\r\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c is RadioButton radioButton)
|
||||
{
|
||||
log += $"({(radioButton.Checked ? 1 : 0)}) {radioButton.Name}.[{radioButton.Text}]\r\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c is ComboBox comboBox)
|
||||
{
|
||||
log += $"{comboBox.Name} = {comboBox.Text}\r\n";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log += "\r\n";
|
||||
|
||||
SocketStuff sk = Sk;
|
||||
|
||||
if (sk?.TcpSockets != null)
|
||||
{
|
||||
foreach (TcpSk tcp in sk.TcpSockets)
|
||||
{
|
||||
log += $"{Common.MachineName}{(tcp.IsClient ? "=>" : "<=")}{tcp.MachineName}({tcp.MachineId}):{tcp.Status}\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
log += string.Format(CultureInfo.CurrentCulture, "Helper:{0}\r\n", SendMessageToHelper(0x400, IntPtr.Zero, IntPtr.Zero));
|
||||
|
||||
log += Setting.Values.LastPersonalizeLogonScr + "\r\n";
|
||||
log += "Name2IP =\r\n" + Setting.Values.Name2IP + "\r\n";
|
||||
|
||||
log += "Last 10 trace messages:\r\n";
|
||||
|
||||
log += string.Join(Environment.NewLine, Logger.LogCounter.Select(item => $"({item.Value}): {item.Key}").Take(10));
|
||||
|
||||
log += "\r\n=============================================================================================================================";
|
||||
|
||||
return log;
|
||||
}
|
||||
|
||||
internal static bool GetUserName()
|
||||
{
|
||||
if (string.IsNullOrEmpty(Setting.Values.Username) && !Common.RunOnLogonDesktop)
|
||||
{
|
||||
if (Program.User.Contains("system", StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
_ = Common.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||
{
|
||||
// See: https://stackoverflow.com/questions/19487541/how-to-get-windows-user-name-from-sessionid
|
||||
static string GetUsernameBySessionId(int sessionId)
|
||||
{
|
||||
string username = "SYSTEM";
|
||||
if (NativeMethods.WTSQuerySessionInformation(IntPtr.Zero, sessionId, NativeMethods.WTSInfoClass.WTSUserName, out nint buffer, out int strLen) && strLen > 1)
|
||||
{
|
||||
username = Marshal.PtrToStringAnsi(buffer);
|
||||
NativeMethods.WTSFreeMemory(buffer);
|
||||
|
||||
if (NativeMethods.WTSQuerySessionInformation(IntPtr.Zero, sessionId, NativeMethods.WTSInfoClass.WTSDomainName, out buffer, out strLen) && strLen > 1)
|
||||
{
|
||||
username = @$"{Marshal.PtrToStringAnsi(buffer)}\{username}";
|
||||
NativeMethods.WTSFreeMemory(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
return username;
|
||||
}
|
||||
|
||||
// The most direct way to fetch the username is WindowsIdentity.GetCurrent(true).Name
|
||||
// but GetUserName can run within an ExecutionContext.SuppressFlow block, which creates issues
|
||||
// with WindowsIdentity.GetCurrent.
|
||||
// See: https://stackoverflow.com/questions/76998988/exception-when-using-executioncontext-suppressflow-in-net-7
|
||||
// So we use WTSQuerySessionInformation as a workaround.
|
||||
Setting.Values.Username = GetUsernameBySessionId(Process.GetCurrentProcess().SessionId);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Setting.Values.Username = Program.User;
|
||||
}
|
||||
|
||||
Logger.LogDebug("[Username] = " + Setting.Values.Username);
|
||||
}
|
||||
|
||||
return !string.IsNullOrEmpty(Setting.Values.Username);
|
||||
}
|
||||
|
||||
internal static void ShowOneWayModeMessage()
|
||||
{
|
||||
ToggleShowTopMostMessage(
|
||||
@"
|
||||
Due to Security Controls, a remote device cannot control a SAW device.
|
||||
Please use the keyboard and Mouse from the SAW device.
|
||||
(Press Esc to hide this message)
|
||||
",
|
||||
string.Empty,
|
||||
10);
|
||||
}
|
||||
|
||||
internal static void ApplyCADSetting()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Setting.Values.DisableCAD)
|
||||
{
|
||||
RegistryKey k = Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System");
|
||||
if (k != null)
|
||||
{
|
||||
k.SetValue("DisableCAD", 1, RegistryValueKind.DWord);
|
||||
k.Close();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RegistryKey k = Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System");
|
||||
if (k != null)
|
||||
{
|
||||
k.SetValue("DisableCAD", 0, RegistryValueKind.DWord);
|
||||
k.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -93,7 +93,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
internal static void Init()
|
||||
{
|
||||
_ = Common.GetUserName();
|
||||
_ = Helper.GetUserName();
|
||||
Common.GeneratedKey = true;
|
||||
|
||||
try
|
||||
@@ -148,7 +148,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
private static void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
|
||||
{
|
||||
Common.WndProcCounter++;
|
||||
Helper.WndProcCounter++;
|
||||
|
||||
if (e.Mode is PowerModes.Resume or PowerModes.Suspend)
|
||||
{
|
||||
@@ -167,21 +167,21 @@ namespace MouseWithoutBorders
|
||||
watchDogThread.Start();
|
||||
*/
|
||||
|
||||
helper = new Thread(new ThreadStart(HelperThread), "Helper Thread");
|
||||
helper = new Thread(new ThreadStart(Helper.HelperThread), "Helper Thread");
|
||||
helper.SetApartmentState(ApartmentState.STA);
|
||||
helper.Start();
|
||||
}
|
||||
|
||||
private static void AskHelperThreadsToExit(int waitTime)
|
||||
{
|
||||
signalHelperToExit = true;
|
||||
signalWatchDogToExit = true;
|
||||
Helper.signalHelperToExit = true;
|
||||
Helper.signalWatchDogToExit = true;
|
||||
_ = EvSwitch.Set();
|
||||
|
||||
int c = 0;
|
||||
if (helper != null && c < waitTime)
|
||||
{
|
||||
while (signalHelperToExit)
|
||||
while (Helper.signalHelperToExit)
|
||||
{
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
@@ -251,7 +251,7 @@ namespace MouseWithoutBorders
|
||||
private static void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
|
||||
{
|
||||
Logger.LogDebug("NetworkAvailabilityEventArgs.IsAvailable: " + e.IsAvailable.ToString(CultureInfo.InvariantCulture));
|
||||
Common.WndProcCounter++;
|
||||
Helper.WndProcCounter++;
|
||||
ScheduleReopenSocketsDueToNetworkChanges(!e.IsAvailable);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,314 +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.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
|
||||
// <summary>
|
||||
// Impersonation.
|
||||
// </summary>
|
||||
// <history>
|
||||
// 2008 created by Truong Do (ductdo).
|
||||
// 2009-... modified by Truong Do (TruongDo).
|
||||
// 2023- Included in PowerToys.
|
||||
// </history>
|
||||
using MouseWithoutBorders.Class;
|
||||
using MouseWithoutBorders.Core;
|
||||
|
||||
namespace MouseWithoutBorders
|
||||
{
|
||||
internal partial class Common
|
||||
{
|
||||
internal static bool RunElevated()
|
||||
{
|
||||
return WindowsIdentity.GetCurrent().Owner.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid);
|
||||
}
|
||||
|
||||
internal static bool ImpersonateLoggedOnUserAndDoSomething(Action targetFunc)
|
||||
{
|
||||
if (Common.RunWithNoAdminRight)
|
||||
{
|
||||
targetFunc();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// SuppressFlow fixes an issue on service mode, where WTSQueryUserToken runs successfully once and then fails
|
||||
// on subsequent calls. The reason appears to be an unknown issue with reverting the impersonation,
|
||||
// meaning that subsequent impersonation attempts run as the logged-on user and fail.
|
||||
// This is a workaround.
|
||||
using var asyncFlowControl = System.Threading.ExecutionContext.SuppressFlow();
|
||||
|
||||
uint dwSessionId;
|
||||
IntPtr hUserToken = IntPtr.Zero, hUserTokenDup = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
dwSessionId = (uint)Process.GetCurrentProcess().SessionId;
|
||||
uint rv = NativeMethods.WTSQueryUserToken(dwSessionId, ref hUserToken);
|
||||
var lastError = rv == 0 ? Marshal.GetLastWin32Error() : 0;
|
||||
|
||||
Logger.LogDebug($"{nameof(NativeMethods.WTSQueryUserToken)} returned {rv.ToString(CultureInfo.CurrentCulture)}");
|
||||
|
||||
if (rv == 0)
|
||||
{
|
||||
Logger.Log($"{nameof(NativeMethods.WTSQueryUserToken)} failed with: {lastError}.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!NativeMethods.DuplicateToken(hUserToken, (int)NativeMethods.SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, ref hUserTokenDup))
|
||||
{
|
||||
Logger.TelemetryLogTrace($"{nameof(NativeMethods.DuplicateToken)} Failed! {Logger.GetStackTrace(new StackTrace())}", SeverityLevel.Warning);
|
||||
_ = NativeMethods.CloseHandle(hUserToken);
|
||||
_ = NativeMethods.CloseHandle(hUserTokenDup);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NativeMethods.ImpersonateLoggedOnUser(hUserTokenDup))
|
||||
{
|
||||
targetFunc();
|
||||
_ = NativeMethods.RevertToSelf();
|
||||
_ = NativeMethods.CloseHandle(hUserToken);
|
||||
_ = NativeMethods.CloseHandle(hUserTokenDup);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log("ImpersonateLoggedOnUser Failed!");
|
||||
_ = NativeMethods.CloseHandle(hUserToken);
|
||||
_ = NativeMethods.CloseHandle(hUserTokenDup);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static int CreateProcessInInputDesktopSession(string commandLine, string arg, string desktop, short wShowWindow, bool lowIntegrity = false)
|
||||
|
||||
// As user who runs explorer.exe
|
||||
{
|
||||
if (!Program.User.Contains("system", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
ProcessStartInfo s = new(commandLine, arg);
|
||||
s.WindowStyle = wShowWindow != 0 ? ProcessWindowStyle.Normal : ProcessWindowStyle.Hidden;
|
||||
Process p = Process.Start(s);
|
||||
|
||||
return p == null ? 0 : p.Id;
|
||||
}
|
||||
|
||||
string commandLineWithArg = commandLine + " " + arg;
|
||||
int lastError;
|
||||
int dwSessionId;
|
||||
IntPtr hUserToken = IntPtr.Zero, hUserTokenDup = IntPtr.Zero;
|
||||
|
||||
Logger.LogDebug("CreateProcessInInputDesktopSession called, launching " + commandLineWithArg + " on " + desktop);
|
||||
|
||||
try
|
||||
{
|
||||
dwSessionId = Process.GetCurrentProcess().SessionId;
|
||||
|
||||
// Get the user token used by DuplicateTokenEx
|
||||
lastError = (int)NativeMethods.WTSQueryUserToken((uint)dwSessionId, ref hUserToken);
|
||||
|
||||
NativeMethods.STARTUPINFO si = default;
|
||||
si.cb = Marshal.SizeOf(si);
|
||||
si.lpDesktop = "winsta0\\" + desktop;
|
||||
si.wShowWindow = wShowWindow;
|
||||
|
||||
NativeMethods.SECURITY_ATTRIBUTES sa = default;
|
||||
sa.Length = Marshal.SizeOf(sa);
|
||||
|
||||
if (!NativeMethods.DuplicateTokenEx(hUserToken, NativeMethods.MAXIMUM_ALLOWED, ref sa, (int)NativeMethods.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, (int)NativeMethods.TOKEN_TYPE.TokenPrimary, ref hUserTokenDup))
|
||||
{
|
||||
lastError = Marshal.GetLastWin32Error();
|
||||
Logger.Log(string.Format(CultureInfo.CurrentCulture, "DuplicateTokenEx error: {0} Token does not have the privilege.", lastError));
|
||||
_ = NativeMethods.CloseHandle(hUserToken);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lowIntegrity)
|
||||
{
|
||||
NativeMethods.TOKEN_MANDATORY_LABEL tIL;
|
||||
|
||||
// Low
|
||||
string sIntegritySid = "S-1-16-4096";
|
||||
|
||||
bool rv = NativeMethods.ConvertStringSidToSid(sIntegritySid, out IntPtr pIntegritySid);
|
||||
|
||||
if (!rv)
|
||||
{
|
||||
Logger.Log("ConvertStringSidToSid failed");
|
||||
_ = NativeMethods.CloseHandle(hUserToken);
|
||||
_ = NativeMethods.CloseHandle(hUserTokenDup);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tIL.Label.Attributes = NativeMethods.SE_GROUP_INTEGRITY;
|
||||
tIL.Label.Sid = pIntegritySid;
|
||||
|
||||
rv = NativeMethods.SetTokenInformation(hUserTokenDup, NativeMethods.TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, ref tIL, (uint)Marshal.SizeOf(tIL) + (uint)IntPtr.Size);
|
||||
|
||||
if (!rv)
|
||||
{
|
||||
Logger.Log("SetTokenInformation failed");
|
||||
_ = NativeMethods.CloseHandle(hUserToken);
|
||||
_ = NativeMethods.CloseHandle(hUserTokenDup);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint dwCreationFlags = NativeMethods.NORMAL_PRIORITY_CLASS | NativeMethods.CREATE_NEW_CONSOLE;
|
||||
IntPtr pEnv = IntPtr.Zero;
|
||||
|
||||
if (NativeMethods.CreateEnvironmentBlock(ref pEnv, hUserTokenDup, true))
|
||||
{
|
||||
dwCreationFlags |= NativeMethods.CREATE_UNICODE_ENVIRONMENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
pEnv = IntPtr.Zero;
|
||||
}
|
||||
|
||||
_ = NativeMethods.CreateProcessAsUser(
|
||||
hUserTokenDup, // client's access token
|
||||
null, // file to execute
|
||||
commandLineWithArg, // command line
|
||||
ref sa, // pointer to process SECURITY_ATTRIBUTES
|
||||
ref sa, // pointer to thread SECURITY_ATTRIBUTES
|
||||
false, // handles are not inheritable
|
||||
(int)dwCreationFlags, // creation flags
|
||||
pEnv, // pointer to new environment block
|
||||
null, // name of current directory
|
||||
ref si, // pointer to STARTUPINFO structure
|
||||
out NativeMethods.PROCESS_INFORMATION pi); // receives information about new process
|
||||
|
||||
// GetLastError should be 0
|
||||
int iResultOfCreateProcessAsUser = Marshal.GetLastWin32Error();
|
||||
Logger.LogDebug("CreateProcessAsUser returned " + iResultOfCreateProcessAsUser.ToString(CultureInfo.CurrentCulture));
|
||||
|
||||
// Close handles task
|
||||
_ = NativeMethods.CloseHandle(hUserToken);
|
||||
_ = NativeMethods.CloseHandle(hUserTokenDup);
|
||||
|
||||
return (iResultOfCreateProcessAsUser == 0) ? (int)pi.dwProcessId : 0;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log(e);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if CUSTOMIZE_LOGON_SCREEN
|
||||
internal static bool CreateLowIntegrityProcess(string commandLine, string args, int wait, bool killIfTimedOut, long limitedMem, short wShowWindow = 0)
|
||||
{
|
||||
int processId = CreateProcessInInputDesktopSession(commandLine, args, "default", wShowWindow, true);
|
||||
|
||||
if (processId <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wait > 0)
|
||||
{
|
||||
if (limitedMem > 0)
|
||||
{
|
||||
int sec = 0;
|
||||
while (true)
|
||||
{
|
||||
Process p;
|
||||
|
||||
try
|
||||
{
|
||||
if ((p = Process.GetProcessById(processId)) == null)
|
||||
{
|
||||
Logger.Log("Process exited!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
Logger.Log("GetProcessById.ArgumentException");
|
||||
break;
|
||||
}
|
||||
|
||||
if ((!p.HasExited && p.PrivateMemorySize64 > limitedMem) || (++sec > (wait / 1000)))
|
||||
{
|
||||
Logger.Log(string.Format(CultureInfo.CurrentCulture, "Process log (mem): {0}, {1}", sec, p.PrivateMemorySize64));
|
||||
return false;
|
||||
}
|
||||
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Process p;
|
||||
|
||||
if ((p = Process.GetProcessById(processId)) == null)
|
||||
{
|
||||
Logger.Log("Process exited!");
|
||||
}
|
||||
else if (NativeMethods.WaitForSingleObject(p.Handle, wait) != NativeMethods.WAIT_OBJECT_0 && killIfTimedOut)
|
||||
{
|
||||
Logger.Log("Process log (time).");
|
||||
TerminateProcessTree(p.Handle, (uint)processId, -1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static void TerminateProcessTree(IntPtr hProcess, uint processID, int exitCode)
|
||||
{
|
||||
if (processID > 0 && hProcess.ToInt32() > 0)
|
||||
{
|
||||
Process[] processes = Process.GetProcesses();
|
||||
int dwSessionId = Process.GetCurrentProcess().SessionId;
|
||||
|
||||
foreach (Process p in processes)
|
||||
{
|
||||
if (p.SessionId == dwSessionId)
|
||||
{
|
||||
NativeMethods.PROCESS_BASIC_INFORMATION processBasicInformation = default;
|
||||
|
||||
try
|
||||
{
|
||||
if (NativeMethods.NtQueryInformationProcess(p.Handle, 0, ref processBasicInformation, (uint)Marshal.SizeOf(processBasicInformation), out uint bytesWritten) >= 0)
|
||||
{// NT_SUCCESS(...)
|
||||
if (processBasicInformation.InheritedFromUniqueProcessId == processID)
|
||||
{
|
||||
TerminateProcessTree(p.Handle, processBasicInformation.UniqueProcessId, exitCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (InvalidOperationException e)
|
||||
{
|
||||
Logger.Log(e);
|
||||
continue;
|
||||
}
|
||||
catch (Win32Exception e)
|
||||
{
|
||||
Logger.Log(e);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ = NativeMethods.TerminateProcess(hProcess, (IntPtr)exitCode);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1,161 +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.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.ServiceProcess;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
// <summary>
|
||||
// Service control code.
|
||||
// </summary>
|
||||
// <history>
|
||||
// 2008 created by Truong Do (ductdo).
|
||||
// 2009-... modified by Truong Do (TruongDo).
|
||||
// 2023- Included in PowerToys.
|
||||
// </history>
|
||||
using MouseWithoutBorders.Class;
|
||||
using MouseWithoutBorders.Core;
|
||||
|
||||
[module: SuppressMessage("Microsoft.Globalization", "CA1300:SpecifyMessageBoxOptions", Scope = "member", Target = "MouseWithoutBorders.Common.#StartMouseWithoutBordersService()", Justification = "Dotnet port with style preservation")]
|
||||
|
||||
namespace MouseWithoutBorders
|
||||
{
|
||||
internal partial class Common
|
||||
{
|
||||
private static bool shownErrMessage;
|
||||
private static DateTime lastStartServiceTime = DateTime.UtcNow;
|
||||
|
||||
internal static void StartMouseWithoutBordersService(string desktopToRunMouseWithoutBordersOn = null, string startTag1 = "byapp", string startTag2 = null)
|
||||
{
|
||||
// NOTE(@yuyoyuppe): the new flow assumes we run both mwb processes directly from the svc.
|
||||
if (Common.RunWithNoAdminRight || true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.Log($"{nameof(StartMouseWithoutBordersService)}: {Logger.GetStackTrace(new StackTrace())}.");
|
||||
|
||||
Task task = Task.Run(() =>
|
||||
{
|
||||
Process[] ps = Process.GetProcessesByName("MouseWithoutBordersSvc");
|
||||
|
||||
if (ps.Length != 0)
|
||||
{
|
||||
if (DateTime.UtcNow - lastStartServiceTime < TimeSpan.FromSeconds(5))
|
||||
{
|
||||
Logger.Log($"{nameof(StartMouseWithoutBordersService)}: Aborted.");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (Process pp in ps)
|
||||
{
|
||||
Logger.Log(string.Format(CultureInfo.InvariantCulture, "Killing process MouseWithoutBordersSvc {0}.", pp.Id));
|
||||
pp.KillProcess();
|
||||
}
|
||||
}
|
||||
|
||||
lastStartServiceTime = DateTime.UtcNow;
|
||||
ServiceController service = new("MouseWithoutBordersSvc");
|
||||
|
||||
try
|
||||
{
|
||||
Logger.Log("Starting " + service.ServiceName);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
if (!shownErrMessage)
|
||||
{
|
||||
shownErrMessage = true;
|
||||
_ = MessageBox.Show(
|
||||
Application.ProductName + " is not installed yet, please run Setup.exe first!",
|
||||
Application.ProductName,
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Error);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
int c = 0;
|
||||
|
||||
while (service.Status != ServiceControllerStatus.Stopped && c++ < 5)
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
service = new ServiceController("MouseWithoutBordersSvc");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(desktopToRunMouseWithoutBordersOn))
|
||||
{
|
||||
startTag2 ??= Process.GetCurrentProcess().SessionId.ToString(CultureInfo.InvariantCulture);
|
||||
service.Start(new string[] { startTag1, startTag2 });
|
||||
}
|
||||
else
|
||||
{
|
||||
service.Start(new string[] { desktopToRunMouseWithoutBordersOn });
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log(e);
|
||||
|
||||
// ERROR_SERVICE_ALREADY_RUNNING
|
||||
if (!(shownErrMessage || ((e?.InnerException as Win32Exception)?.NativeErrorCode == 1056)))
|
||||
{
|
||||
shownErrMessage = true;
|
||||
_ = MessageBox.Show(
|
||||
"Cannot start service " + service.ServiceName + ": " + e.Message,
|
||||
Common.BinaryName,
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Error);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
// Wait for the task while not blocking the UI thread.
|
||||
do
|
||||
{
|
||||
MMSleep(1);
|
||||
|
||||
if (task.IsCanceled || task.IsCompleted || task.IsFaulted)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (true);
|
||||
}
|
||||
|
||||
internal static void StartServiceAndSendLogoffSignal()
|
||||
{
|
||||
try
|
||||
{
|
||||
Process[] p = Process.GetProcessesByName("winlogon");
|
||||
Process me = Process.GetCurrentProcess();
|
||||
string myWinlogon = p?.FirstOrDefault(item => item.SessionId == me.SessionId)?.Id.ToString(CultureInfo.InvariantCulture) ?? null;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(myWinlogon))
|
||||
{
|
||||
StartMouseWithoutBordersService(null, "logoff");
|
||||
}
|
||||
else
|
||||
{
|
||||
StartMouseWithoutBordersService(null, "logoff", myWinlogon);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log($"{nameof(StartServiceAndSendLogoffSignal)}: {e.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -269,7 +269,7 @@ namespace MouseWithoutBorders
|
||||
if (!Common.RunWithNoAdminRight)
|
||||
{
|
||||
Logger.LogDebug("*** Starting on active Desktop: " + desktopToRunMouseWithoutBordersOn);
|
||||
StartMouseWithoutBordersService(desktopToRunMouseWithoutBordersOn);
|
||||
Service.StartMouseWithoutBordersService(desktopToRunMouseWithoutBordersOn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
if (!IsMyDesktopActive() || Common.CurrentProcess.SessionId != NativeMethods.WTSGetActiveConsoleSessionId())
|
||||
{
|
||||
Common.RunDDHelper(true);
|
||||
Helper.RunDDHelper(true);
|
||||
int waitCount = 20;
|
||||
|
||||
while (NativeMethods.WTSGetActiveConsoleSessionId() == 0xFFFFFFFF && waitCount > 0)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user