mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-01-07 21:06:58 +01:00
Compare commits
326 Commits
regist
...
yaqingmi/d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f387e6c99 | ||
|
|
2c4577422b | ||
|
|
f65a4495b0 | ||
|
|
fd9641cdc5 | ||
|
|
147c0d3ec5 | ||
|
|
e1316e6631 | ||
|
|
4d1dbea5d1 | ||
|
|
46aa43cb69 | ||
|
|
01359c4b0c | ||
|
|
508b95cf5b | ||
|
|
5946b98f87 | ||
|
|
e61e5b6d83 | ||
|
|
67272ad073 | ||
|
|
a79126373f | ||
|
|
3688995511 | ||
|
|
255a11df85 | ||
|
|
d713a3001d | ||
|
|
614af1dd77 | ||
|
|
469ffd93ea | ||
|
|
797941954d | ||
|
|
8a07b7b560 | ||
|
|
f0a23ceaeb | ||
|
|
f2373cf259 | ||
|
|
cfdcf91625 | ||
|
|
2f678d1fb3 | ||
|
|
f49625210c | ||
|
|
602eef8830 | ||
|
|
90a489352b | ||
|
|
13a6287dea | ||
|
|
6cb852077a | ||
|
|
cdc5f073f0 | ||
|
|
0427a7a7b0 | ||
|
|
2d0d12f06c | ||
|
|
06e5db6ff0 | ||
|
|
1a097ae09c | ||
|
|
980ca46cdb | ||
|
|
6a1999d601 | ||
|
|
5655c61794 | ||
|
|
371b7f0868 | ||
|
|
b6bcc92eb4 | ||
|
|
2ac464279a | ||
|
|
8ce198a47b | ||
|
|
15ef9189ba | ||
|
|
2c555e2c2b | ||
|
|
83817700e1 | ||
|
|
7e92a9a5e9 | ||
|
|
fe067def65 | ||
|
|
6b9c99c2f6 | ||
|
|
ba6af794ac | ||
|
|
9cb99be4e9 | ||
|
|
c2dddab4ac | ||
|
|
1eb60302df | ||
|
|
11781d11e9 | ||
|
|
ad974bd679 | ||
|
|
49e5bbb5f0 | ||
|
|
7efbd2f013 | ||
|
|
ba230eca07 | ||
|
|
30df5e0df2 | ||
|
|
9a6c64f9c0 | ||
|
|
7dc2a05c45 | ||
|
|
1a14dce5a3 | ||
|
|
26fe36ab8d | ||
|
|
06b56a10bd | ||
|
|
fc804a8156 | ||
|
|
f63fcfd91c | ||
|
|
195ff24a85 | ||
|
|
5691c5754b | ||
|
|
100d560f9e | ||
|
|
25c29ade8e | ||
|
|
8dfa55fe28 | ||
|
|
6c317c4ee1 | ||
|
|
54e058e82d | ||
|
|
b0e7473760 | ||
|
|
f085ba0cd2 | ||
|
|
884bfc71d3 | ||
|
|
252cf2670f | ||
|
|
211bb15be0 | ||
|
|
2752b217e5 | ||
|
|
4be6129835 | ||
|
|
583614449d | ||
|
|
b0afc57e77 | ||
|
|
d4e577bb81 | ||
|
|
e1ad7e39c6 | ||
|
|
e8b02cd797 | ||
|
|
2eb51a1861 | ||
|
|
91077c71a9 | ||
|
|
997622fac8 | ||
|
|
232e1b79bd | ||
|
|
5ec2728dea | ||
|
|
d314fa075e | ||
|
|
90723d5b12 | ||
|
|
ddb9d8ecc6 | ||
|
|
f2a5505601 | ||
|
|
311ab88ec3 | ||
|
|
856cbaa293 | ||
|
|
4067be17b2 | ||
|
|
b4020c6720 | ||
|
|
f87c1bc448 | ||
|
|
c04400e7df | ||
|
|
05218e8af6 | ||
|
|
f49daa24e0 | ||
|
|
c1c9720992 | ||
|
|
750bb429c5 | ||
|
|
7f5aaf26dc | ||
|
|
af8d5402c8 | ||
|
|
6cf73ce839 | ||
|
|
4f9e829155 | ||
|
|
397d5cf655 | ||
|
|
01584f33e1 | ||
|
|
67463abf98 | ||
|
|
e95a570d48 | ||
|
|
cb27874805 | ||
|
|
f65a3fc06f | ||
|
|
c7789abf04 | ||
|
|
e700f86ace | ||
|
|
a16f784011 | ||
|
|
4e0db267dc | ||
|
|
0e98cbd57e | ||
|
|
f15bed5323 | ||
|
|
d3c4e808d0 | ||
|
|
2b5181b4c9 | ||
|
|
77852f2137 | ||
|
|
60f50d853b | ||
|
|
f1bda8d71f | ||
|
|
21aa49cefb | ||
|
|
b902d3adf0 | ||
|
|
82ff0615d4 | ||
|
|
5081d6d31e | ||
|
|
293fa262bb | ||
|
|
578d99f3b3 | ||
|
|
badb029bcf | ||
|
|
bec6754aa3 | ||
|
|
d986592737 | ||
|
|
662f04ed34 | ||
|
|
abec5eb96a | ||
|
|
71ec39ff89 | ||
|
|
017b9e6339 | ||
|
|
c8b1a925b3 | ||
|
|
e0e3772cdd | ||
|
|
6b8798fb94 | ||
|
|
03bc72c436 | ||
|
|
5c8aa67781 | ||
|
|
836cfbf698 | ||
|
|
b32c04fca1 | ||
|
|
91d504511f | ||
|
|
3d3682672c | ||
|
|
b9474e9f60 | ||
|
|
c5b29188b8 | ||
|
|
e59b6d3051 | ||
|
|
4cb72ee126 | ||
|
|
6625289a10 | ||
|
|
2f0dae347f | ||
|
|
f3ddba8aa5 | ||
|
|
55f8f3a53e | ||
|
|
4744d23857 | ||
|
|
c42f8b0a1b | ||
|
|
70da33783d | ||
|
|
a7994402fe | ||
|
|
41472a483c | ||
|
|
5fa416b962 | ||
|
|
aa7d89c8de | ||
|
|
94e8559796 | ||
|
|
fd7cccefa2 | ||
|
|
ae2bb61d26 | ||
|
|
52b4150e3b | ||
|
|
fe53a9c89a | ||
|
|
6dc0211867 | ||
|
|
a708a3afaa | ||
|
|
fc4d3a96c3 | ||
|
|
a347d740ca | ||
|
|
e8359931ac | ||
|
|
1cb215d1a6 | ||
|
|
b7f99e88ef | ||
|
|
6f43aac26a | ||
|
|
d7e826d2ac | ||
|
|
9e8754a592 | ||
|
|
49687251d3 | ||
|
|
f72ccd12fd | ||
|
|
4b44858a48 | ||
|
|
53ae118e72 | ||
|
|
31df702704 | ||
|
|
ea2542b235 | ||
|
|
c6776d0d45 | ||
|
|
d48286a3eb | ||
|
|
7a5b25cd3e | ||
|
|
1eccbc3021 | ||
|
|
ce620e427f | ||
|
|
0f6ff59d2e | ||
|
|
721c84d3a6 | ||
|
|
96ba445cfa | ||
|
|
16157231d4 | ||
|
|
a641b46f57 | ||
|
|
51e9e9d46a | ||
|
|
5157ffc895 | ||
|
|
60bbf070e1 | ||
|
|
d597bd267d | ||
|
|
2623eb10f3 | ||
|
|
8e27940b77 | ||
|
|
c6750d3a62 | ||
|
|
37836c656d | ||
|
|
39e8231831 | ||
|
|
2cb63f5fbe | ||
|
|
e931135d50 | ||
|
|
5b39d1551d | ||
|
|
25a8c95049 | ||
|
|
c60c79af67 | ||
|
|
dd5279b9b8 | ||
|
|
5e88d47f3d | ||
|
|
aeec3a967f | ||
|
|
78921eb7d3 | ||
|
|
9173ac27df | ||
|
|
be1968aaa5 | ||
|
|
33cc612e40 | ||
|
|
a9a41ca1a2 | ||
|
|
4e7bd34c4d | ||
|
|
43783d2cff | ||
|
|
79bd825f91 | ||
|
|
69c2e9c568 | ||
|
|
df3e3414d2 | ||
|
|
7368458a72 | ||
|
|
4d7691a56f | ||
|
|
2f9fea2287 | ||
|
|
29551898ca | ||
|
|
048b07c1ce | ||
|
|
7575c040f8 | ||
|
|
e52dd68fe4 | ||
|
|
3e9a6a1e64 | ||
|
|
14919dff10 | ||
|
|
57cbcc2c3e | ||
|
|
5d03667bcf | ||
|
|
2b4d13ccb9 | ||
|
|
665e957cde | ||
|
|
dadd306555 | ||
|
|
ce57d818a7 | ||
|
|
68f76409ab | ||
|
|
bf877c4e40 | ||
|
|
53003b9969 | ||
|
|
394583fca9 | ||
|
|
20cd0ec7f4 | ||
|
|
dfb727f9a3 | ||
|
|
a13abc3803 | ||
|
|
f68f408be3 | ||
|
|
a62acf7a71 | ||
|
|
648c3eb0bf | ||
|
|
f6b53d1088 | ||
|
|
8862b22c45 | ||
|
|
4377de260f | ||
|
|
1f81d14000 | ||
|
|
1d358af600 | ||
|
|
18a1107ec4 | ||
|
|
8e90d8e4c5 | ||
|
|
abd6314b2e | ||
|
|
a298f67b81 | ||
|
|
c89280cd9e | ||
|
|
0e62e2ddd4 | ||
|
|
595231f64b | ||
|
|
7894c1e5ad | ||
|
|
d2d71bf797 | ||
|
|
3eb5ca294a | ||
|
|
7bdd6c660a | ||
|
|
0277938f18 | ||
|
|
dd7b6f3ea9 | ||
|
|
0187d1abcd | ||
|
|
7bd2b50126 | ||
|
|
53f8499434 | ||
|
|
b127611462 | ||
|
|
622770134e | ||
|
|
ceca607142 | ||
|
|
77a5ef7d32 | ||
|
|
39073f0467 | ||
|
|
924898ae94 | ||
|
|
75f2b0927c | ||
|
|
f54ab6ebd5 | ||
|
|
dd5997ab06 | ||
|
|
6bdbb6b552 | ||
|
|
84dd551d84 | ||
|
|
a00f56e317 | ||
|
|
2b7307d32e | ||
|
|
83bb82322d | ||
|
|
92fb931e1e | ||
|
|
c4f8f09fab | ||
|
|
82bc3b7c85 | ||
|
|
9c95835384 | ||
|
|
1867ac8f02 | ||
|
|
127e079efe | ||
|
|
03540e307c | ||
|
|
a10578f7d3 | ||
|
|
9c08c957e5 | ||
|
|
c73b88f575 | ||
|
|
fc1c4abd0a | ||
|
|
22efeb3f63 | ||
|
|
63c4089441 | ||
|
|
fd206ecdee | ||
|
|
ccb77ff601 | ||
|
|
bbc8beb006 | ||
|
|
3b05cf127a | ||
|
|
8494858314 | ||
|
|
04c80c40a2 | ||
|
|
42edf9da97 | ||
|
|
c38faa959a | ||
|
|
fc94cd758e | ||
|
|
61a00aa669 | ||
|
|
cca3f442e2 | ||
|
|
22e29d1253 | ||
|
|
8a2d4745fa | ||
|
|
bf2685757a | ||
|
|
b8cef42776 | ||
|
|
959a54bcd9 | ||
|
|
491d51afaf | ||
|
|
f263042aeb | ||
|
|
c09a5337c4 | ||
|
|
9a658eb884 | ||
|
|
4eb11d6f9b | ||
|
|
a5a354a70f | ||
|
|
744316c400 | ||
|
|
f2370912f3 | ||
|
|
5cc30df4db | ||
|
|
f81f65db3d | ||
|
|
9f008a65d6 | ||
|
|
d243b58715 | ||
|
|
abf4626843 | ||
|
|
3874a3b893 | ||
|
|
8687b310db | ||
|
|
c7ed8ee0c3 | ||
|
|
8c21f794af | ||
|
|
18befd7149 |
@@ -6,12 +6,16 @@ properties:
|
||||
directives:
|
||||
description: Enable Developer Mode
|
||||
allowPrerelease: true
|
||||
# Requires elevation for the set operation
|
||||
securityContext: elevated
|
||||
settings:
|
||||
Ensure: Present
|
||||
- resource: Microsoft.WinGet.DSC/WinGetPackage
|
||||
id: vsPackage
|
||||
directives:
|
||||
description: Install Visual Studio 2022 Enterprise (Any edition will work)
|
||||
# Requires elevation for the set operation
|
||||
securityContext: elevated
|
||||
settings:
|
||||
id: Microsoft.VisualStudio.2022.Enterprise
|
||||
source: winget
|
||||
@@ -21,6 +25,8 @@ properties:
|
||||
directives:
|
||||
description: Install required VS workloads
|
||||
allowPrerelease: true
|
||||
# Requires elevation for the get and set operations
|
||||
securityContext: elevated
|
||||
settings:
|
||||
productId: Microsoft.VisualStudio.Product.Enterprise
|
||||
channelId: VisualStudio.17.Release
|
||||
@@ -6,12 +6,16 @@ properties:
|
||||
directives:
|
||||
description: Enable Developer Mode
|
||||
allowPrerelease: true
|
||||
# Requires elevation for the set operation
|
||||
securityContext: elevated
|
||||
settings:
|
||||
Ensure: Present
|
||||
- resource: Microsoft.WinGet.DSC/WinGetPackage
|
||||
id: vsPackage
|
||||
directives:
|
||||
description: Install Visual Studio 2022 Professional (Any edition will work)
|
||||
# Requires elevation for the set operation
|
||||
securityContext: elevated
|
||||
settings:
|
||||
id: Microsoft.VisualStudio.2022.Professional
|
||||
source: winget
|
||||
@@ -21,6 +25,8 @@ properties:
|
||||
directives:
|
||||
description: Install required VS workloads
|
||||
allowPrerelease: true
|
||||
# Requires elevation for the get and set operations
|
||||
securityContext: elevated
|
||||
settings:
|
||||
productId: Microsoft.VisualStudio.Product.Professional
|
||||
channelId: VisualStudio.17.Release
|
||||
@@ -6,12 +6,16 @@ properties:
|
||||
directives:
|
||||
description: Enable Developer Mode
|
||||
allowPrerelease: true
|
||||
# Requires elevation for the set operation
|
||||
securityContext: elevated
|
||||
settings:
|
||||
Ensure: Present
|
||||
- resource: Microsoft.WinGet.DSC/WinGetPackage
|
||||
id: vsPackage
|
||||
directives:
|
||||
description: Install Visual Studio 2022 Community (Any edition will work)
|
||||
# Requires elevation for the set operation
|
||||
securityContext: elevated
|
||||
settings:
|
||||
id: Microsoft.VisualStudio.2022.Community
|
||||
source: winget
|
||||
@@ -21,6 +25,8 @@ properties:
|
||||
directives:
|
||||
description: Install required VS workloads
|
||||
allowPrerelease: true
|
||||
# Requires elevation for the get and set operations
|
||||
securityContext: elevated
|
||||
settings:
|
||||
productId: Microsoft.VisualStudio.Product.Community
|
||||
channelId: VisualStudio.17.Release
|
||||
@@ -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"
|
||||
]
|
||||
|
||||
34
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
34
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -1,6 +1,5 @@
|
||||
name: "🕷️ Bug report"
|
||||
description: Report errors or unexpected behavior
|
||||
type: Bug
|
||||
labels:
|
||||
- Issue-Bug
|
||||
- Needs-Triage
|
||||
@@ -8,15 +7,17 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Please make sure to [search for existing issues](https://github.com/microsoft/PowerToys/issues) before filing a new one!
|
||||
- type: input
|
||||
- id: version
|
||||
type: input
|
||||
attributes:
|
||||
label: Microsoft PowerToys version
|
||||
placeholder: 0.70.0
|
||||
placeholder: X.XX.X
|
||||
description: Hover over system tray icon or look at Settings
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
- id: installed
|
||||
type: dropdown
|
||||
attributes:
|
||||
label: Installation method
|
||||
description: How / Where was PowerToys installed from?
|
||||
@@ -33,14 +34,6 @@ body:
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Running as admin
|
||||
description: Are you running PowerToys as Admin?
|
||||
options:
|
||||
- "Yes"
|
||||
- "No"
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Area(s) with issue?
|
||||
@@ -53,6 +46,7 @@ body:
|
||||
- Awake
|
||||
- ColorPicker
|
||||
- Command not found
|
||||
- Command Palette
|
||||
- Crop and Lock
|
||||
- Environment Variables
|
||||
- FancyZones
|
||||
@@ -66,7 +60,7 @@ body:
|
||||
- Keyboard Manager
|
||||
- Mouse Utilities
|
||||
- Mouse Without Borders
|
||||
- New+
|
||||
- New+
|
||||
- Peek
|
||||
- PowerRename
|
||||
- PowerToys Run
|
||||
@@ -105,6 +99,19 @@ body:
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- id: additionalInfo
|
||||
type: textarea
|
||||
attributes:
|
||||
label: Additional Information
|
||||
placeholder: |
|
||||
OS version
|
||||
.Net version
|
||||
System Language
|
||||
User or System Installation
|
||||
Running as admin
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Other Software
|
||||
@@ -115,3 +122,4 @@ body:
|
||||
My Cool Application v0.3 (include a code snippet if it would help!)
|
||||
validations:
|
||||
required: false
|
||||
|
||||
|
||||
7
.github/actions/spell-check/allow/code.txt
vendored
7
.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
|
||||
@@ -267,6 +271,7 @@ mengyuanchen
|
||||
|
||||
# DllName
|
||||
testhost
|
||||
Testably
|
||||
|
||||
#Tools
|
||||
OIP
|
||||
OIP
|
||||
10
.github/actions/spell-check/allow/names.txt
vendored
10
.github/actions/spell-check/allow/names.txt
vendored
@@ -79,6 +79,7 @@ Gershaft
|
||||
Giordani
|
||||
Gokce
|
||||
gordon
|
||||
Griese
|
||||
grzhan
|
||||
Guo
|
||||
hanselman
|
||||
@@ -109,6 +110,7 @@ Lambson
|
||||
Laute
|
||||
laviusmotileng
|
||||
Leilei
|
||||
Loewen
|
||||
Luecking
|
||||
Mahalingam
|
||||
Markovic
|
||||
@@ -153,6 +155,7 @@ Santossio
|
||||
Schoen
|
||||
Sekan
|
||||
Seraphima
|
||||
Shmuelie
|
||||
skttl
|
||||
somil
|
||||
Soref
|
||||
@@ -184,6 +187,9 @@ zhaopy
|
||||
zhaoqpcn
|
||||
Zoltan
|
||||
Zykova
|
||||
Sameerjs
|
||||
ruslanlap
|
||||
vednig
|
||||
|
||||
# OTHERS
|
||||
|
||||
@@ -196,6 +202,7 @@ cortana
|
||||
dlnilsson
|
||||
fancymouse
|
||||
firefox
|
||||
fudan
|
||||
gpt
|
||||
Inkscape
|
||||
Markdig
|
||||
@@ -211,6 +218,7 @@ regedit
|
||||
roslyn
|
||||
Spotify
|
||||
Vanara
|
||||
wangyi
|
||||
WEX
|
||||
windowwalker
|
||||
winui
|
||||
@@ -218,7 +226,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$
|
||||
|
||||
254
.github/actions/spell-check/expect.txt
vendored
254
.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
|
||||
26
.github/workflows/dependency-review.yml
vendored
Normal file
26
.github/workflows/dependency-review.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
# Dependency Review Action
|
||||
#
|
||||
# This Action will scan dependency manifest files that change as part of a Pull Request,
|
||||
# surfacing known-vulnerable versions of the packages declared or updated in the PR.
|
||||
# Once installed, if the workflow run is marked as required,
|
||||
# PRs introducing known-vulnerable packages will be blocked from merging.
|
||||
#
|
||||
# As recommended by Microsoft's security guidelines (https://docs.opensource.microsoft.com/security/tsg/actions/#requirements-for-security-hardening-your-own-github-actions),
|
||||
# 3rd-party actions should be pinned to a specific commit hash to prevent supply chain attacks.
|
||||
# This update aligns with best practices; 1st/2nd-party actions is not required hash pinning.
|
||||
#
|
||||
# Source repository: https://github.com/actions/dependency-review-action
|
||||
name: 'Dependency Review'
|
||||
on: [pull_request]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
dependency-review:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: 'Checkout Repository'
|
||||
uses: actions/checkout@v4
|
||||
- name: 'Dependency Review'
|
||||
uses: actions/dependency-review-action@v4
|
||||
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@v4
|
||||
with:
|
||||
dotnet-version: '9.0.x'
|
||||
|
||||
- uses: microsoft/setup-msstore-cli@v1
|
||||
|
||||
- name: Fetch Store Credential
|
||||
|
||||
8
.github/workflows/spelling2.yml
vendored
8
.github/workflows/spelling2.yml
vendored
@@ -93,7 +93,7 @@ jobs:
|
||||
steps:
|
||||
- name: check-spelling
|
||||
id: spelling
|
||||
uses: check-spelling/check-spelling@v0.0.24
|
||||
uses: check-spelling/check-spelling@67debf50669c7fc76fc8f5d7f996384535a72b77 # v0.0.24
|
||||
with:
|
||||
config: .github/actions/spell-check
|
||||
suppress_push_for_open_pull_request: ${{ github.actor != 'dependabot[bot]' && 1 }}
|
||||
@@ -156,7 +156,7 @@ jobs:
|
||||
if: (success() || failure()) && needs.spelling.outputs.followup && github.event_name == 'push'
|
||||
steps:
|
||||
- name: comment
|
||||
uses: check-spelling/check-spelling@v0.0.24
|
||||
uses: check-spelling/check-spelling@67debf50669c7fc76fc8f5d7f996384535a72b77 # v0.0.24
|
||||
with:
|
||||
config: .github/actions/spell-check
|
||||
checkout: true
|
||||
@@ -175,7 +175,7 @@ jobs:
|
||||
if: (success() || failure()) && needs.spelling.outputs.followup && contains(github.event_name, 'pull_request')
|
||||
steps:
|
||||
- name: comment
|
||||
uses: check-spelling/check-spelling@v0.0.24
|
||||
uses: check-spelling/check-spelling@67debf50669c7fc76fc8f5d7f996384535a72b77 # v0.0.24
|
||||
with:
|
||||
config: .github/actions/spell-check
|
||||
checkout: true
|
||||
@@ -202,7 +202,7 @@ jobs:
|
||||
cancel-in-progress: false
|
||||
steps:
|
||||
- name: apply spelling updates
|
||||
uses: check-spelling/check-spelling@v0.0.24
|
||||
uses: check-spelling/check-spelling@67debf50669c7fc76fc8f5d7f996384535a72b77 # v0.0.24
|
||||
with:
|
||||
experimental_apply_changes_via_bot: ${{ github.repository_owner != 'microsoft' && 1 }}
|
||||
checkout: true
|
||||
|
||||
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"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -128,6 +128,7 @@
|
||||
"PowerToys.KeyboardManager.dll",
|
||||
"KeyboardManagerEditor\\PowerToys.KeyboardManagerEditor.exe",
|
||||
"KeyboardManagerEngine\\PowerToys.KeyboardManagerEngine.exe",
|
||||
"PowerToys.KeyboardManagerEditorLibraryWrapper.dll",
|
||||
|
||||
"PowerToys.Launcher.dll",
|
||||
"PowerToys.PowerLauncher.dll",
|
||||
@@ -216,7 +217,11 @@
|
||||
"PowerToys.ZoomItSettingsInterop.dll",
|
||||
|
||||
"WinUI3Apps\\PowerToys.Settings.dll",
|
||||
"WinUI3Apps\\PowerToys.Settings.exe"
|
||||
"WinUI3Apps\\PowerToys.Settings.exe",
|
||||
|
||||
"PowerToys.CmdPalModuleInterface.dll",
|
||||
"CmdPalKeyboardService.dll",
|
||||
"*Microsoft.CmdPal.UI_*.msix"
|
||||
],
|
||||
"SigningInfo": {
|
||||
"Operations": [
|
||||
@@ -326,6 +331,8 @@
|
||||
"TestableIO.System.IO.Abstractions.Wrappers.dll",
|
||||
"WinUI3Apps\\TestableIO.System.IO.Abstractions.Wrappers.dll",
|
||||
"WinUI3Apps\\OpenAI.dll",
|
||||
"Testably.Abstractions.FileSystem.Interface.dll",
|
||||
"WinUI3Apps\\Testably.Abstractions.FileSystem.Interface.dll",
|
||||
"ColorCode.Core.dll",
|
||||
"ColorCode.UWP.dll",
|
||||
"UnitsNet.dll",
|
||||
|
||||
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"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,16 +1,24 @@
|
||||
Param(
|
||||
# Using the default value of 1.6 for winAppSdkVersionNumber and useExperimentalVersion as false
|
||||
# Using the default value of 1.7 for winAppSdkVersionNumber and useExperimentalVersion as false
|
||||
[Parameter(Mandatory=$False,Position=1)]
|
||||
[string]$winAppSdkVersionNumber = "1.6",
|
||||
[string]$winAppSdkVersionNumber = "1.7",
|
||||
|
||||
# When the pipeline calls the PS1 file, the passed parameters are converted to string type
|
||||
[Parameter(Mandatory=$False,Position=2)]
|
||||
[boolean]$useExperimentalVersion = $False
|
||||
[boolean]$useExperimentalVersion = $False,
|
||||
|
||||
# Root folder Path for processing
|
||||
[Parameter(Mandatory=$False,Position=3)]
|
||||
[string]$rootPath = $(Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path)),
|
||||
|
||||
# Root folder Path for processing
|
||||
[Parameter(Mandatory=$False,Position=4)]
|
||||
[string]$sourceLink = "https://microsoft.pkgs.visualstudio.com/ProjectReunion/_packaging/Project.Reunion.nuget.internal/nuget/v3/index.json"
|
||||
)
|
||||
|
||||
function Update-NugetConfig {
|
||||
param (
|
||||
[string]$filePath = "nuget.config"
|
||||
[string]$filePath = [System.IO.Path]::Combine($rootPath, "nuget.config")
|
||||
)
|
||||
|
||||
Write-Host "Updating nuget.config file"
|
||||
@@ -35,7 +43,33 @@ function Update-NugetConfig {
|
||||
$xml.Save($filePath)
|
||||
}
|
||||
|
||||
$sourceLink = "https://microsoft.pkgs.visualstudio.com/ProjectReunion/_packaging/Project.Reunion.nuget.internal/nuget/v3/index.json"
|
||||
function Read-FileWithEncoding {
|
||||
param (
|
||||
[string]$Path
|
||||
)
|
||||
|
||||
$reader = New-Object System.IO.StreamReader($Path, $true) # auto-detect encoding
|
||||
$content = $reader.ReadToEnd()
|
||||
$encoding = $reader.CurrentEncoding
|
||||
$reader.Close()
|
||||
|
||||
return [PSCustomObject]@{
|
||||
Content = $content
|
||||
Encoding = $encoding
|
||||
}
|
||||
}
|
||||
|
||||
function Write-FileWithEncoding {
|
||||
param (
|
||||
[string]$Path,
|
||||
[string]$Content,
|
||||
[System.Text.Encoding]$Encoding
|
||||
)
|
||||
|
||||
$writer = New-Object System.IO.StreamWriter($Path, $false, $Encoding)
|
||||
$writer.Write($Content)
|
||||
$writer.Close()
|
||||
}
|
||||
|
||||
# Execute nuget list and capture the output
|
||||
if ($useExperimentalVersion) {
|
||||
@@ -79,50 +113,54 @@ if ($latestVersion) {
|
||||
}
|
||||
|
||||
# Update packages.config files
|
||||
Get-ChildItem -Recurse packages.config | ForEach-Object {
|
||||
$content = Get-Content $_.FullName -Raw
|
||||
Get-ChildItem -Path $rootPath -Recurse packages.config | ForEach-Object {
|
||||
$file = Read-FileWithEncoding -Path $_.FullName
|
||||
$content = $file.Content
|
||||
if ($content -match 'package id="Microsoft.WindowsAppSDK"') {
|
||||
$newVersionString = 'package id="Microsoft.WindowsAppSDK" version="' + $WinAppSDKVersion + '"'
|
||||
$oldVersionString = 'package id="Microsoft.WindowsAppSDK" version="[-.0-9a-zA-Z]*"'
|
||||
$content = $content -replace $oldVersionString, $newVersionString
|
||||
Set-Content -Path $_.FullName -Value $content
|
||||
Write-FileWithEncoding -Path $_.FullName -Content $content -Encoding $file.encoding
|
||||
Write-Host "Modified " $_.FullName
|
||||
}
|
||||
}
|
||||
|
||||
# Update Directory.Packages.props file
|
||||
$propsFile = "Directory.Packages.props"
|
||||
$propsFile = [System.IO.Path]::Combine($rootPath,"Directory.Packages.props")
|
||||
if (Test-Path $propsFile) {
|
||||
$content = Get-Content $propsFile -Raw
|
||||
$file = Read-FileWithEncoding -Path $propsFile
|
||||
$content = $file.Content
|
||||
if ($content -match '<PackageVersion Include="Microsoft.WindowsAppSDK"') {
|
||||
$newVersionString = '<PackageVersion Include="Microsoft.WindowsAppSDK" Version="' + $WinAppSDKVersion + '" />'
|
||||
$oldVersionString = '<PackageVersion Include="Microsoft.WindowsAppSDK" Version="[-.0-9a-zA-Z]*" />'
|
||||
$content = $content -replace $oldVersionString, $newVersionString
|
||||
Set-Content -Path $propsFile -Value $content
|
||||
Write-FileWithEncoding -Path $propsFile -Content $content -Encoding $file.encoding
|
||||
Write-Host "Modified " $propsFile
|
||||
}
|
||||
}
|
||||
|
||||
# Update .vcxproj files
|
||||
Get-ChildItem -Recurse *.vcxproj | ForEach-Object {
|
||||
$content = Get-Content $_.FullName -Raw
|
||||
Get-ChildItem -Path $rootPath -Recurse *.vcxproj | ForEach-Object {
|
||||
$file = Read-FileWithEncoding -Path $_.FullName
|
||||
$content = $file.Content
|
||||
if ($content -match '\\Microsoft.WindowsAppSDK.') {
|
||||
$newVersionString = '\Microsoft.WindowsAppSDK.' + $WinAppSDKVersion + '\'
|
||||
$oldVersionString = '\\Microsoft.WindowsAppSDK.[-.0-9a-zA-Z]*\\'
|
||||
$content = $content -replace $oldVersionString, $newVersionString
|
||||
Set-Content -Path $_.FullName -Value $content
|
||||
Write-FileWithEncoding -Path $_.FullName -Content $content -Encoding $file.encoding
|
||||
Write-Host "Modified " $_.FullName
|
||||
}
|
||||
}
|
||||
|
||||
# Update .csproj files
|
||||
Get-ChildItem -Recurse *.csproj | ForEach-Object {
|
||||
$content = Get-Content $_.FullName -Raw
|
||||
Get-ChildItem -Path $rootPath -Recurse *.csproj | ForEach-Object {
|
||||
$file = Read-FileWithEncoding -Path $_.FullName
|
||||
$content = $file.Content
|
||||
if ($content -match 'PackageReference Include="Microsoft.WindowsAppSDK"') {
|
||||
$newVersionString = 'PackageReference Include="Microsoft.WindowsAppSDK" Version="'+ $WinAppSDKVersion + '"'
|
||||
$oldVersionString = 'PackageReference Include="Microsoft.WindowsAppSDK" Version="[-.0-9a-zA-Z]*"'
|
||||
$content = $content -replace $oldVersionString, $newVersionString
|
||||
Set-Content -Path $_.FullName -Value $content
|
||||
Write-FileWithEncoding -Path $_.FullName -Content $content -Encoding $file.encoding
|
||||
Write-Host "Modified " $_.FullName
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.PowerToys.Telemetry" version="2.0.2" />
|
||||
<package id="Microsoft.PowerToys.Telemetry" version="2.0.3" />
|
||||
</packages>
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
"notificationAliases": ["powertoys@microsoft.com"],
|
||||
"instanceUrl": "https://microsoft.visualstudio.com",
|
||||
"projectName": "OS",
|
||||
"areaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\SHINE\\PowerToys"
|
||||
"areaPath": "OS\\Windows Client and Services\\WinPD\\DFX-Developer Fundamentals and Experiences\\DEFT\\PowerToys"
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ parameters:
|
||||
default: true
|
||||
- name: winAppSDKVersionNumber
|
||||
type: string
|
||||
default: 1.6
|
||||
default: 1.7
|
||||
- name: useExperimentalVersion
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
@@ -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,18 +106,42 @@ 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
|
||||
- template: .pipelines/v2/templates/steps-fetch-and-prepare-localizations.yml@self
|
||||
|
||||
- script: |
|
||||
call nuget.exe restore -configFile .pipelines/release-nuget.config -PackagesDirectory . .pipelines/packages.config || exit /b 1
|
||||
move /Y "Microsoft.PowerToys.Telemetry.2.0.2\build\include\TraceLoggingDefines.h" "src\common\Telemetry\TraceLoggingDefines.h" || exit /b 1
|
||||
move /Y "Microsoft.PowerToys.Telemetry.2.0.2\build\include\TelemetryBase.cs" "src\common\Telemetry\TelemetryBase.cs" || exit /b 1
|
||||
- pwsh: |-
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$PSNativeCommandUseErrorActionPreference = $true
|
||||
& nuget.exe restore -configFile .pipelines/release-nuget.config -PackagesDirectory . .pipelines/packages.config
|
||||
Move-Item -Force -Verbose "Microsoft.PowerToys.Telemetry.*\build\include\TraceLoggingDefines.h" "src\common\Telemetry\TraceLoggingDefines.h"
|
||||
Move-Item -Force -Verbose "Microsoft.PowerToys.Telemetry.*\build\include\TelemetryBase.cs" "src\common\Telemetry\TelemetryBase.cs"
|
||||
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]
|
||||
@@ -115,5 +150,7 @@ extends:
|
||||
parameters:
|
||||
versionNumber: ${{ parameters.versionNumber }}
|
||||
includePublicSymbolServer: ${{ parameters.publishSymbolsToPublic }}
|
||||
${{ if ne(parameters.publishSymbolsToPublic, true) }}:
|
||||
symbolExpiryTime: 10 # For private builds, expire symbols within 10 days. The default is 100 years.
|
||||
subscription: $(SymbolPublishingServiceConnection)
|
||||
symbolProject: $(SymbolPublishingProject)
|
||||
|
||||
@@ -50,12 +50,18 @@ parameters:
|
||||
- name: runTests
|
||||
type: boolean
|
||||
default: true
|
||||
- name: buildTests
|
||||
type: boolean
|
||||
default: true
|
||||
- name: useVSPreview
|
||||
type: boolean
|
||||
default: false
|
||||
- name: versionNumber
|
||||
type: string
|
||||
default: '0.0.1'
|
||||
- name: cmdPalVersionNumber
|
||||
type: string
|
||||
default: '0.0.1'
|
||||
- name: useLatestWinAppSDK
|
||||
type: boolean
|
||||
default: false
|
||||
@@ -96,6 +102,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.
|
||||
@@ -106,7 +113,7 @@ jobs:
|
||||
JobOutputArtifactName: build-$(BuildPlatform)-$(BuildConfiguration)${{ parameters.artifactStem }}
|
||||
NUGET_RESTORE_MSBUILD_ARGS: /p:Platform=$(BuildPlatform) # Required for nuget to work due to self contained
|
||||
NODE_OPTIONS: --max_old_space_size=16384
|
||||
${{ if eq(parameters.runTests, true) }}:
|
||||
${{ if or(eq(parameters.runTests, true), eq(parameters.buildTests, true)) }}:
|
||||
MSBuildMainBuildTargets: Build;Test
|
||||
${{ else }}:
|
||||
MSBuildMainBuildTargets: Build
|
||||
@@ -145,7 +152,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 +249,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,11 +342,16 @@ 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
|
||||
|
||||
# Check if all projects (located in src sub-folder) import common props
|
||||
- pwsh: |-
|
||||
& '.pipelines/verifyCommonProps.ps1' -sourceDir '$(build.sourcesdirectory)\src'
|
||||
displayName: Audit shared common props for CSharp projects in src sub-folder
|
||||
|
||||
# Check if deps.json files don't reference different dll versions.
|
||||
- pwsh: |-
|
||||
& '.pipelines/verifyDepsJsonLibraryVersions.ps1' -targetDir '$(build.sourcesdirectory)\$(BuildPlatform)\$(BuildConfiguration)'
|
||||
@@ -360,6 +398,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 +500,7 @@ jobs:
|
||||
$machinePlat = "hash_machine_$(BuildPlatform).txt";
|
||||
$combinedUserPath = $p + $userPlat;
|
||||
$combinedMachinePath = $p + $machinePlat;
|
||||
|
||||
|
||||
echo $p
|
||||
|
||||
echo $userPlat
|
||||
@@ -445,7 +510,7 @@ jobs:
|
||||
echo $machinePlat
|
||||
echo $machineHash
|
||||
echo $combinedMachinePath
|
||||
|
||||
|
||||
$userHash | out-file -filepath $combinedUserPath
|
||||
$machineHash | out-file -filepath $combinedMachinePath
|
||||
displayName: Calculate file hashes
|
||||
@@ -457,7 +522,7 @@ jobs:
|
||||
displayName: Stage GPO files
|
||||
|
||||
# Running the tests may result in future jobs consuming artifacts out of this build
|
||||
- ${{ if eq(parameters.runTests, true) }}:
|
||||
- ${{ if or(eq(parameters.runTests, true), eq(parameters.buildTests, true)) }}:
|
||||
- task: CopyFiles@2
|
||||
displayName: Stage entire build output
|
||||
inputs:
|
||||
|
||||
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
|
||||
@@ -11,24 +11,36 @@ parameters:
|
||||
- name: useLatestWebView2
|
||||
type: boolean
|
||||
default: false
|
||||
- name: isUIAutomationPipeline
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
- job: Test${{ parameters.platform }}${{ parameters.configuration }}
|
||||
displayName: Test ${{ parameters.platform }} ${{ parameters.configuration }}
|
||||
timeoutInMinutes: 300
|
||||
variables:
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
${{ if or(eq(parameters.platform, 'x64Win10'), eq(parameters.platform, 'x64Win11')) }}:
|
||||
BuildPlatform: x64
|
||||
${{ else }}:
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
TestPlatform: ${{ parameters.platform }}
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
SrcPath: $(Build.Repository.LocalPath)
|
||||
TestArtifactsName: build-${{ parameters.platform }}-${{ parameters.configuration }}${{ parameters.inputArtifactStem }}
|
||||
TestArtifactsName: build-${{ variables.BuildPlatform }}-${{ parameters.configuration }}${{ parameters.inputArtifactStem }}
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionId'], 'cb55739e-4afe-46a3-970f-1b49d8ee7564') }}:
|
||||
${{ if ne(parameters.platform, 'ARM64') }}:
|
||||
name: SHINE-INT-Testing-x64
|
||||
${{ if and(eq(parameters.isUIAutomationPipeline, true), eq(parameters.platform, 'x64Win11')) }}:
|
||||
demands: ImageOverride -equals SHINE-W11-Testing
|
||||
${{ else }}:
|
||||
name: SHINE-INT-Testing-arm64
|
||||
${{ else }}:
|
||||
${{ if ne(parameters.platform, 'ARM64') }}:
|
||||
name: SHINE-OSS-Testing-x64
|
||||
${{ if and(eq(parameters.isUIAutomationPipeline, true), eq(parameters.platform, 'x64Win11')) }}:
|
||||
demands: ImageOverride -equals SHINE-W11-Testing
|
||||
${{ else }}:
|
||||
name: SHINE-OSS-Testing-arm64
|
||||
steps:
|
||||
@@ -61,9 +73,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:
|
||||
@@ -92,8 +113,16 @@ jobs:
|
||||
vsTestVersion: 'toolsInstaller'
|
||||
uiTests: true
|
||||
rerunFailedTests: true
|
||||
testAssemblyVer2: |
|
||||
**\UITests-FancyZones.dll
|
||||
**\UITests-FancyZonesEditor.dll
|
||||
!**\obj\**
|
||||
!**\ref\**
|
||||
${{ if eq(parameters.isUIAutomationPipeline, true) }}:
|
||||
testAssemblyVer2: |
|
||||
**\*UITest*.dll
|
||||
!**\obj\**
|
||||
!**\ref\**
|
||||
${{ else }}:
|
||||
testAssemblyVer2: |
|
||||
**\UITests-FancyZones.dll
|
||||
**\UITests-FancyZonesEditor.dll
|
||||
!**\obj\**
|
||||
!**\ref\**
|
||||
env:
|
||||
platform: '$(TestPlatform)'
|
||||
|
||||
@@ -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
.pipelines/v2/templates/pipeline-ui-tests-automation.yml
Normal file
87
.pipelines/v2/templates/pipeline-ui-tests-automation.yml
Normal file
@@ -0,0 +1,87 @@
|
||||
variables:
|
||||
- name: runCodesignValidationInjectionBG
|
||||
value: false
|
||||
- name: EnablePipelineCache
|
||||
value: true
|
||||
- ${{ if eq(parameters.enableMsBuildCaching, true) }}:
|
||||
- name: EnablePipelineCache
|
||||
value: true
|
||||
|
||||
parameters:
|
||||
- name: buildPlatforms
|
||||
type: object
|
||||
default:
|
||||
- x64
|
||||
- arm64
|
||||
- name: enableMsBuildCaching
|
||||
type: boolean
|
||||
default: false
|
||||
- name: useVSPreview
|
||||
type: boolean
|
||||
default: false
|
||||
- name: useLatestWebView2
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
stages:
|
||||
- ${{ each platform in parameters.buildPlatforms }}:
|
||||
- stage: Build_${{ platform }}
|
||||
displayName: Build ${{ platform }}
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: job-build-project.yml
|
||||
parameters:
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionId'], 'cb55739e-4afe-46a3-970f-1b49d8ee7564') }}:
|
||||
name: SHINE-INT-L
|
||||
${{ else }}:
|
||||
name: SHINE-OSS-L
|
||||
${{ if eq(parameters.useVSPreview, true) }}:
|
||||
demands: ImageOverride -equals SHINE-VS17-Preview
|
||||
buildPlatforms:
|
||||
- ${{ platform }}
|
||||
buildConfigurations: [Release]
|
||||
enablePackageCaching: true
|
||||
enableMsBuildCaching: ${{ parameters.enableMsBuildCaching }}
|
||||
runTests: false
|
||||
buildTests: true
|
||||
useVSPreview: ${{ parameters.useVSPreview }}
|
||||
|
||||
- ${{ if eq(platform, 'x64') }}:
|
||||
- stage: Test_x64Win10
|
||||
displayName: Test x64Win10
|
||||
dependsOn:
|
||||
- Build_${{platform}}
|
||||
jobs:
|
||||
- template: job-test-project.yml
|
||||
parameters:
|
||||
platform: x64Win10
|
||||
configuration: Release
|
||||
useLatestWebView2: ${{ parameters.useLatestWebView2 }}
|
||||
isUIAutomationPipeline: true
|
||||
|
||||
- ${{ if eq(platform, 'x64') }}:
|
||||
- stage: Test_x64Win11
|
||||
displayName: Test x64Win11
|
||||
dependsOn:
|
||||
- Build_${{platform}}
|
||||
jobs:
|
||||
- template: job-test-project.yml
|
||||
parameters:
|
||||
platform: x64Win11
|
||||
configuration: Release
|
||||
useLatestWebView2: ${{ parameters.useLatestWebView2 }}
|
||||
isUIAutomationPipeline: true
|
||||
|
||||
- ${{ if ne(platform, 'x64') }}:
|
||||
- stage: Test_${{ platform }}
|
||||
displayName: Test ${{ platform }}
|
||||
dependsOn:
|
||||
- Build_${{platform}}
|
||||
jobs:
|
||||
- template: job-test-project.yml
|
||||
parameters:
|
||||
platform: ${{ platform }}
|
||||
configuration: Release
|
||||
useLatestWebView2: ${{ parameters.useLatestWebView2 }}
|
||||
isUIAutomationPipeline: true
|
||||
@@ -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'
|
||||
|
||||
@@ -17,6 +17,7 @@ steps:
|
||||
arguments: >
|
||||
-winAppSdkVersionNumber ${{ parameters.versionNumber }}
|
||||
-useExperimentalVersion $${{ parameters.useExperimentalVersion }}
|
||||
-rootPath "$(build.sourcesdirectory)"
|
||||
|
||||
- script: echo $(WinAppSDKVersion)
|
||||
displayName: 'Display WinAppSDK Version Found'
|
||||
|
||||
54
.pipelines/verifyCommonProps.ps1
Normal file
54
.pipelines/verifyCommonProps.ps1
Normal file
@@ -0,0 +1,54 @@
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory = $True, Position = 1)]
|
||||
[string]$sourceDir
|
||||
)
|
||||
|
||||
# scan all csharp project in the source directory
|
||||
function Get-CSharpProjects {
|
||||
param (
|
||||
[string]$path
|
||||
)
|
||||
|
||||
# Get all .csproj files under the specified path
|
||||
return Get-ChildItem -Path $path -Recurse -Filter *.csproj | Select-Object -ExpandProperty FullName
|
||||
}
|
||||
|
||||
# Check if the project file imports 'Common.Dotnet.CsWinRT.props'
|
||||
function Test-ImportSharedCsWinRTProps {
|
||||
param (
|
||||
[string]$filePath
|
||||
)
|
||||
|
||||
# Load the XML content of the .csproj file
|
||||
[xml]$csprojContent = Get-Content -Path $filePath
|
||||
|
||||
|
||||
# Check if the Import element with Project attribute containing 'Common.Dotnet.CsWinRT.props' exists
|
||||
return $csprojContent.Project.Import | Where-Object { $null -ne $_.Project -and $_.Project.EndsWith('Common.Dotnet.CsWinRT.props') }
|
||||
}
|
||||
|
||||
# Call the function with the provided source directory
|
||||
$csprojFilesArray = Get-CSharpProjects -path $sourceDir
|
||||
|
||||
$hasInvalidCsProj = $false
|
||||
|
||||
# Enumerate the array of file paths and call Validate-ImportSharedCsWinRTProps for each file
|
||||
foreach ($csprojFile in $csprojFilesArray) {
|
||||
# Skip if the file ends with 'TemplateCmdPalExtension.csproj'
|
||||
if ($csprojFile -like '*TemplateCmdPalExtension.csproj') {
|
||||
continue
|
||||
}
|
||||
|
||||
$importExists = Test-ImportSharedCsWinRTProps -filePath $csprojFile
|
||||
if (!$importExists) {
|
||||
Write-Output "$csprojFile need to import 'Common.Dotnet.CsWinRT.props'."
|
||||
$hasInvalidCsProj = $true
|
||||
}
|
||||
}
|
||||
|
||||
if ($hasInvalidCsProj) {
|
||||
exit 1
|
||||
}
|
||||
|
||||
exit 0
|
||||
@@ -15,9 +15,14 @@ Param(
|
||||
$referencedFileVersionsPerDll = @{}
|
||||
$totalFailures = 0
|
||||
|
||||
Get-ChildItem $targetDir -Recurse -Filter *.deps.json -Exclude *UITests*,MouseJump.Common.UnitTests*,*.FuzzTests* | ForEach-Object {
|
||||
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
|
||||
|
||||
@@ -86,5 +91,4 @@ if ($totalFailures -gt 0) {
|
||||
}
|
||||
|
||||
Write-Host -ForegroundColor Green "All " $referencedFileVersionsPerDll.keys.Count " libraries are mentioned with the same version across the dependencies.`r`n"
|
||||
exit 0
|
||||
|
||||
exit 0
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
23
COMMUNITY.md
23
COMMUNITY.md
@@ -16,7 +16,7 @@ Christian contributed New+ utility
|
||||
CleanCodeDeveloper helped do massive amounts of code stability and image resizer work.
|
||||
|
||||
### [@plante-msft](https://github.com/plante-msft) - Connor Plante
|
||||
Connor was the creator of Workspaces and helped create PowerToys Run v2
|
||||
Connor was the creator of Workspaces and helped create Command Palette (PowerToys Run v2)
|
||||
|
||||
### [@damienleroy](https://github.com/damienleroy) - [Damien Leroy](https://www.linkedin.com/in/Damien-Leroy-b2734416a/)
|
||||
Damien has helped out by developing and contributing the Quick Accent utility.
|
||||
@@ -46,7 +46,7 @@ Jeff added in multiple new features into Keyboard manager, such as key chord sup
|
||||
Joe has helped triaging, discussing, issues as well as fixing bugs and building features for Text Extractor.
|
||||
|
||||
### [@joadoumie](https://github.com/joadoumie) - Jordi Adoumie
|
||||
Jordi helped innovate amazing new features into Advanced Paste and helped create PowerToys Run v2
|
||||
Jordi helped innovate amazing new features into Advanced Paste and helped create Command Palette (PowerToys Run v2)
|
||||
|
||||
### [@jsoref](https://github.com/jsoref) - [Josh Soref](https://check-spelling.dev/)
|
||||
Helping keep our spelling correct :)
|
||||
@@ -57,6 +57,9 @@ Color Picker is from Martin.
|
||||
### [@mikeclayton](https://github.com/mikeclayton) - [Michael Clayton](https://michael-clayton.com)
|
||||
Michael contributed the [initial version](https://github.com/microsoft/PowerToys/issues/23216) of the Mouse Jump tool and [a number of updates](https://github.com/microsoft/PowerToys/pulls?q=is%3Apr+author%3Amikeclayton) based on his FancyMouse utility.
|
||||
|
||||
### [@pedrolamas](https://github.com/pedrolamas/) - Pedro Lamas
|
||||
Pedro helped create the thumbnail and File Explorer previewers for 3D files like STL and GCode. If you like 3D printing, these are very helpful.
|
||||
|
||||
### [@PesBandi](https://github.com/PesBandi/) - PesBandi
|
||||
PesBandi has helped do massive amounts of Quick Accent and bug fixes.
|
||||
|
||||
@@ -184,15 +187,11 @@ ZoomIt source code was originally implemented by [Sysinternals](https://sysinter
|
||||
- [@crutkas](https://github.com/crutkas/) - Clint Rutkas - Lead
|
||||
- [@cinnamon-msft](https://github.com/cinnamon-msft) - Kayla Cinnamon - Lead
|
||||
- [@nguyen-dows](https://github.com/nguyen-dows) - Christopher Nguyen - Product Manager
|
||||
- [@jaimecbernardo](https://github.com/jaimecbernardo) - Jaime Bernardo - Dev lead
|
||||
- [@craigloewen-msft](https://github.com/craigloewen-msft) - Craig Loewen - Product Manager
|
||||
- [@zhiwei-ms](https://github.com/zhiwei-ms) - Zhiwei Yu - Product Manager
|
||||
- [@dhowett](https://github.com/dhowett) - Dustin Howett - Dev lead
|
||||
- [@yeelam-gordon](https://github.com/yeelam-gordon) - Gordon Lam - Dev lead
|
||||
- [@jamrobot](https://github.com/jamrobot) - Jerry Xu - Dev lead
|
||||
- [@drawbyperpetual](https://github.com/drawbyperpetual) - Anirudha Shankar - Dev
|
||||
- [@mantaionut](https://github.com/mantaionut) - Ionut Manta - Dev
|
||||
- [@donlaci](https://github.com/donlaci) - Laszlo Nemeth - Dev
|
||||
- [@SeraphimaZykova](https://github.com/SeraphimaZykova) - Seraphima Zykova - Dev
|
||||
- [@stefansjfw](https://github.com/stefansjfw) - Stefan Markovic - Dev
|
||||
- [@lei9444](https://github.com/lei9444) - Leilei Zhang - Dev
|
||||
- [@shuaiyuanxx](https://github.com/shuaiyuanxx) - Shawn Yuan - Dev
|
||||
- [@moooyo](https://github.com/moooyo) - Yu Leng - Dev
|
||||
@@ -206,7 +205,7 @@ ZoomIt source code was originally implemented by [Sysinternals](https://sysinter
|
||||
- [@wang563681252](https://github.com/wang563681252) - Zhaopeng Wang - Dev
|
||||
- [@vanzue](https://github.com/vanzue) - Kai Tao - Dev
|
||||
|
||||
# Former PowerToys core team members
|
||||
## Former PowerToys core team members
|
||||
|
||||
- [@indierawk2k2](https://github.com/indierawk2k2) - Mike Harsh - Product Manager
|
||||
- [@ethanfangg](https://github.com/ethanfangg) - Ethan Fang - Product Manager
|
||||
@@ -219,3 +218,9 @@ ZoomIt source code was originally implemented by [Sysinternals](https://sysinter
|
||||
- [@taras-janea](https://github.com/taras-janea) - Taras Sich - Dev
|
||||
- [@yuyoyuppe](https://github.com/yuyoyuppe) - Andrey Nekrasov - Dev
|
||||
- [@gokcekantarci](https://github.com/gokcekantarci) - Gokce Kantarci - Dev
|
||||
- [@drawbyperpetual](https://github.com/drawbyperpetual) - Anirudha Shankar - Dev
|
||||
- [@mantaionut](https://github.com/mantaionut) - Ionut Manta - Dev
|
||||
- [@donlaci](https://github.com/donlaci) - Laszlo Nemeth - Dev
|
||||
- [@SeraphimaZykova](https://github.com/SeraphimaZykova) - Seraphima Zykova - Dev
|
||||
- [@stefansjfw](https://github.com/stefansjfw) - Stefan Markovic - Dev
|
||||
- [@jaimecbernardo](https://github.com/jaimecbernardo) - Jaime Bernardo - Dev lead
|
||||
|
||||
@@ -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.250402" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Collections" Version="8.2.250402" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Primitives" Version="8.2.250402" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.2.250402" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Segmented" Version="8.2.250402" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Sizers" Version="8.2.250402" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Converters" Version="8.2.250402" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Extensions" Version="8.2.250402" />
|
||||
<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" />
|
||||
@@ -25,38 +29,39 @@
|
||||
<PackageVersion Include="Mages" Version="3.0.0" />
|
||||
<PackageVersion Include="Markdig.Signed" Version="0.34.0" />
|
||||
<!-- 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="MessagePack" Version="3.1.3" />
|
||||
<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.5" />
|
||||
<!-- 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.5" />
|
||||
<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.5" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.5" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.5" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.5" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.5" />
|
||||
<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.5" />
|
||||
<PackageVersion Include="Microsoft.WindowsPackageManager.ComInterop" Version="1.10.340" />
|
||||
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="9.0.5" />
|
||||
<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.7.250401001" />
|
||||
<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" />
|
||||
<!-- Moq to stay below v4.20 due to behavior change. need to be sure fixed -->
|
||||
<PackageVersion Include="Moq" Version="4.18.4" />
|
||||
<PackageVersion Include="MSTest" Version="3.6.3" />
|
||||
<PackageVersion Include="MSTest" Version="3.8.3" />
|
||||
<PackageVersion Include="NLog" Version="5.0.4" />
|
||||
<PackageVersion Include="NLog.Extensions.Logging" Version="5.3.8" />
|
||||
<PackageVersion Include="NLog.Schema" Version="5.2.8" />
|
||||
@@ -64,38 +69,42 @@
|
||||
<PackageVersion Include="ReverseMarkdown" Version="4.1.0" />
|
||||
<PackageVersion Include="ScipBe.Common.Office.OneNote" Version="3.0.1" />
|
||||
<PackageVersion Include="SharpCompress" Version="0.37.2" />
|
||||
<PackageVersion Include="StreamJsonRpc" Version="2.19.27" />
|
||||
<PackageVersion Include="StreamJsonRpc" Version="2.21.69" />
|
||||
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
|
||||
<!-- Package System.CodeDom added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Management but the 8.0.1 version wasn't published to nuget. -->
|
||||
<PackageVersion Include="System.CodeDom" Version="9.0.2" />
|
||||
<PackageVersion Include="System.CodeDom" Version="9.0.5" />
|
||||
<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.5" />
|
||||
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="9.0.5" />
|
||||
<PackageVersion Include="System.Data.OleDb" Version="9.0.5" />
|
||||
<!-- 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.5" />
|
||||
<!-- 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.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.Diagnostics.PerformanceCounter" Version="9.0.5" />
|
||||
<PackageVersion Include="System.Drawing.Common" Version="9.0.5" />
|
||||
<PackageVersion Include="System.IO.Abstractions" Version="22.0.13" />
|
||||
<PackageVersion Include="System.IO.Abstractions.TestingHelpers" Version="22.0.13" />
|
||||
<PackageVersion Include="System.Management" Version="9.0.5" />
|
||||
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
|
||||
<PackageVersion Include="System.Private.Uri" Version="4.3.2" />
|
||||
<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.5" />
|
||||
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="9.0.5" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.5" />
|
||||
<PackageVersion Include="System.Text.Json" Version="9.0.5" />
|
||||
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
|
||||
<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>
|
||||
217
NOTICE.md
217
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,75 @@ 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: Command Palette Built-in Extensions
|
||||
|
||||
### Calculator
|
||||
|
||||
#### Mages
|
||||
|
||||
We use the Mages NuGet package for calculating the result of expression.
|
||||
|
||||
**Source**: [https://github.com/FlorianRappl/Mages](https://github.com/FlorianRappl/Mages)
|
||||
|
||||
```
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 - 2025 Florian Rappl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
## Utility: File Explorer Add-ins
|
||||
|
||||
### Monaco Editor
|
||||
@@ -788,6 +859,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 +1393,55 @@ 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.250402
|
||||
- CommunityToolkit.WinUI.Collections 8.2.250402
|
||||
- CommunityToolkit.WinUI.Controls.Primitives 8.2.250402
|
||||
- CommunityToolkit.WinUI.Controls.Segmented 8.2.250402
|
||||
- CommunityToolkit.WinUI.Controls.SettingsControls 8.2.250402
|
||||
- CommunityToolkit.WinUI.Controls.Sizers 8.2.250402
|
||||
- CommunityToolkit.WinUI.Converters 8.2.250402
|
||||
- CommunityToolkit.WinUI.Extensions 8.2.250402
|
||||
- CommunityToolkit.WinUI.UI.Controls.DataGrid 7.1.2
|
||||
- CommunityToolkit.WinUI.UI.Controls.Markdown 7.1.2
|
||||
- ControlzEx 6.0.0
|
||||
@@ -1317,59 +1452,65 @@ EXHIBIT A -Mozilla Public License.
|
||||
- LazyCache 2.4.0
|
||||
- Mages 3.0.0
|
||||
- Markdig.Signed 0.34.0
|
||||
- MessagePack 2.5.187
|
||||
- Microsoft.Bcl.AsyncInterfaces 9.0.2
|
||||
- MessagePack 3.1.3
|
||||
- Microsoft.Bcl.AsyncInterfaces 9.0.5
|
||||
- Microsoft.CodeAnalysis.NetAnalyzers 9.0.0
|
||||
- Microsoft.Data.Sqlite 9.0.2
|
||||
- Microsoft.Data.Sqlite 9.0.5
|
||||
- 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.5
|
||||
- Microsoft.Extensions.Hosting 9.0.5
|
||||
- Microsoft.Extensions.Hosting.WindowsServices 9.0.5
|
||||
- Microsoft.Extensions.Logging 9.0.5
|
||||
- Microsoft.Extensions.Logging.Abstractions 9.0.5
|
||||
- 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.5
|
||||
- Microsoft.Windows.Compatibility 9.0.5
|
||||
- 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.7.250401001
|
||||
- Microsoft.WindowsPackageManager.ComInterop 1.10.340
|
||||
- Microsoft.Xaml.Behaviors.WinUI.Managed 2.0.9
|
||||
- Microsoft.Xaml.Behaviors.Wpf 1.1.39
|
||||
- ModernWpfUI 0.9.4
|
||||
- Moq 4.18.4
|
||||
- MSTest 3.6.3
|
||||
- MSTest 3.8.3
|
||||
- NLog.Extensions.Logging 5.3.8
|
||||
- NLog.Schema 5.2.8
|
||||
- OpenAI 2.0.0
|
||||
- ReverseMarkdown 4.1.0
|
||||
- ScipBe.Common.Office.OneNote 3.0.1
|
||||
- SharpCompress 0.37.2
|
||||
- StreamJsonRpc 2.19.27
|
||||
- StreamJsonRpc 2.21.69
|
||||
- StyleCop.Analyzers 1.2.0-beta.556
|
||||
- System.CodeDom 9.0.2
|
||||
- System.CodeDom 9.0.5
|
||||
- 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.5
|
||||
- System.Configuration.ConfigurationManager 9.0.5
|
||||
- System.Data.OleDb 9.0.5
|
||||
- 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.IO.Abstractions 21.0.29
|
||||
- System.IO.Abstractions.TestingHelpers 21.0.29
|
||||
- System.Management 9.0.2
|
||||
- System.Diagnostics.EventLog 9.0.5
|
||||
- System.Diagnostics.PerformanceCounter 9.0.5
|
||||
- System.Drawing.Common 9.0.5
|
||||
- System.IO.Abstractions 22.0.13
|
||||
- System.IO.Abstractions.TestingHelpers 22.0.13
|
||||
- System.Management 9.0.5
|
||||
- System.Net.Http 4.3.4
|
||||
- System.Private.Uri 4.3.2
|
||||
- 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.5
|
||||
- System.ServiceProcess.ServiceController 9.0.5
|
||||
- System.Text.Encoding.CodePages 9.0.5
|
||||
- System.Text.Json 9.0.5
|
||||
- System.Text.RegularExpressions 4.3.1
|
||||
- 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
|
||||
|
||||
|
||||
358
PowerToys.sln
358
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\ext\Microsoft.CmdPal.Ext.Apps\Microsoft.CmdPal.Ext.Apps.csproj", "{6CE438DF-C245-4997-A360-0A0939E4BA34}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Bookmarks", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.Bookmark\Microsoft.CmdPal.Ext.Bookmarks.csproj", "{E09AA983-C755-474F-83D6-A5CDF528C070}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Calc", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.Calc\Microsoft.CmdPal.Ext.Calc.csproj", "{6D56B64D-FF1F-488F-AFED-9B9854A5D399}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Registry", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.Registry\Microsoft.CmdPal.Ext.Registry.csproj", "{92EC89E4-9972-453A-8A1A-3A9E230C146A}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowsServices", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WindowsServices\Microsoft.CmdPal.Ext.WindowsServices.csproj", "{51939B4F-1F62-4BFF-A6A2-C08646E5BE95}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowsSettings", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WindowsSettings\Microsoft.CmdPal.Ext.WindowsSettings.csproj", "{D1160404-D3D1-497A-883A-4059C07C2273}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowsTerminal", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WindowsTerminal\Microsoft.CmdPal.Ext.WindowsTerminal.csproj", "{40F6D69D-E321-400F-A767-5628C7AE453D}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extension SDK", "Extension SDK", "{F3D09629-59A2-4924-A4B9-D6BFAA2C1B49}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.CommandPalette.Extensions", "src\modules\cmdpal\extensionsdk\Microsoft.CommandPalette.Extensions\Microsoft.CommandPalette.Extensions.vcxproj", "{305DD37E-C85D-4B08-AAFE-7381FA890463}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CommandPalette.Extensions.Toolkit", "src\modules\cmdpal\extensionsdk\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj", "{CA4D810F-C8F4-4B61-9DA9-71807E0B9F24}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.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\ext\ProcessMonitorExtension\ProcessMonitorExtension.csproj", "{C846F7A7-792A-47D9-B0CB-417C900EE03D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SamplePagesExtension", "src\modules\cmdpal\ext\SamplePagesExtension\SamplePagesExtension.csproj", "{C831231F-891C-4572-9694-45062534B42A}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UI", "UI", "{7520A2FE-00A2-49B8-83ED-DB216E874C04}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.UI", "src\modules\cmdpal\Microsoft.CmdPal.UI\Microsoft.CmdPal.UI.csproj", "{8FBDABA4-40EE-4C0E-9BC8-2F6444A6EF90}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.UI.ViewModels", "src\modules\cmdpal\Microsoft.CmdPal.UI.ViewModels\Microsoft.CmdPal.UI.ViewModels.csproj", "{C66020D1-CB10-4CF7-8715-84C97FD5E5E2}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.ClipboardHistory", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.ClipboardHistory\Microsoft.CmdPal.Ext.ClipboardHistory.csproj", "{79775343-7A3D-445D-9104-3DD5B2893DF9}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CmdPalModuleInterface", "src\modules\cmdpal\CmdPalModuleInterface\CmdPalModuleInterface.vcxproj", "{0ADEB797-C8C7-4FFA-ACD5-2AF6CAD7ECD8}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkspacesCsharpLibrary", "src\modules\Workspaces\WorkspacesCsharpLibrary\WorkspacesCsharpLibrary.csproj", "{89D0E199-B17A-418C-B2F8-7375B6708357}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NewPlus.ShellExtension.win10", "src\modules\NewPlus\NewShellExtensionContextMenu.win10\NewPlus.ShellExtension.win10.vcxproj", "{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.Indexer", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.Indexer\Microsoft.CmdPal.Ext.Indexer.csproj", "{453CBB73-A3CB-4D0B-8D24-6940B86FE21D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Shell", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.Shell\Microsoft.CmdPal.Ext.Shell.csproj", "{C0CE3B5E-16D3-495D-B335-CA791B660162}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowWalker", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WindowWalker\Microsoft.CmdPal.Ext.WindowWalker.csproj", "{3A9A7297-92C4-4F16-B6F9-8D4AB652C86C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.WebSearch", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WebSearch\Microsoft.CmdPal.Ext.WebSearch.csproj", "{605E914B-7232-4789-AF46-BF5D3DDFC14E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.WinGet", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WinGet\Microsoft.CmdPal.Ext.WinGet.csproj", "{E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9}"
|
||||
EndProject
|
||||
Project("{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\ext\Microsoft.CmdPal.Ext.TimeDate\Microsoft.CmdPal.Ext.TimeDate.csproj", "{DCC6BD67-17BB-47AA-B507-FB0FE43A7449}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UITestAutomation", "src\common\UITestAutomation\UITestAutomation.csproj", "{A558C25D-2007-498E-8B6F-43405AFAE9E2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeyboardManagerEditorUI", "src\modules\keyboardmanager\KeyboardManagerEditorUI\KeyboardManagerEditorUI.csproj", "{08F9155D-B6DC-46E5-9C83-AF60B655898B}"
|
||||
@@ -646,6 +702,18 @@ 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\ext\Microsoft.CmdPal.Ext.System\Microsoft.CmdPal.Ext.System.csproj", "{64B88F02-CD88-4ED8-9624-989A800230F9}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CmdPalKeyboardService", "src\modules\cmdpal\CmdPalKeyboardService\CmdPalKeyboardService.vcxproj", "{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRename.FuzzingTest", "src\modules\powerrename\PowerRename.FuzzingTest\PowerRename.FuzzingTest.vcxproj", "{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MouseUtils.UITests", "src\modules\MouseUtils\MouseUtils.UITests\MouseUtils.UITests.csproj", "{4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkspacesEditorUITest", "src\modules\Workspaces\WorkspacesEditorUITest\WorkspacesEditorUITest.csproj", "{43E779F3-D83C-48B1-BA8D-1912DBD76FC9}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
@@ -2198,6 +2266,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 +2430,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 +2518,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 +2570,52 @@ 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}.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
|
||||
{4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Debug|x64.Build.0 = Debug|x64
|
||||
{4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Release|x64.ActiveCfg = Release|x64
|
||||
{4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}.Release|x64.Build.0 = Release|x64
|
||||
{43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Debug|x64.Build.0 = Debug|x64
|
||||
{43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Release|x64.ActiveCfg = Release|x64
|
||||
{43E779F3-D83C-48B1-BA8D-1912DBD76FC9}.Release|x64.Build.0 = Release|x64
|
||||
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Debug|x64.Build.0 = Debug|x64
|
||||
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Release|x64.ActiveCfg = Release|x64
|
||||
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Release|x64.Build.0 = Release|x64
|
||||
{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}.Debug|x64.Build.0 = Debug|x64
|
||||
{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}.Release|x64.ActiveCfg = Release|x64
|
||||
{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -2433,7 +2755,7 @@ Global
|
||||
{25C91A4E-BA4E-467A-85CD-8B62545BF674} = {A50C70A6-2DA0-4027-B90E-B1A40755A8A5}
|
||||
{6AB6A2D6-F859-4A82-9184-0BD29C9F07D1} = {A50C70A6-2DA0-4027-B90E-B1A40755A8A5}
|
||||
{212AD910-8488-4036-BE20-326931B75FB2} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
|
||||
{7AC943C9-52E8-44CF-9083-744D8049667B} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
|
||||
{7AC943C9-52E8-44CF-9083-744D8049667B} = {322566EF-20DC-43A6-B9F8-616AF942579A}
|
||||
{54A93AF7-60C7-4F6C-99D2-FBB1F75F853A} = {7AC943C9-52E8-44CF-9083-744D8049667B}
|
||||
{92C39820-9F84-4529-BC7D-22AAE514D63B} = {7AC943C9-52E8-44CF-9083-744D8049667B}
|
||||
{515554D1-D004-4F7F-A107-2211FC0F6B2C} = {7AC943C9-52E8-44CF-9083-744D8049667B}
|
||||
@@ -2521,19 +2843,53 @@ 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}
|
||||
{4E0AE3A4-2EE0-44D7-A2D0-8769977254A1} = {322566EF-20DC-43A6-B9F8-616AF942579A}
|
||||
{43E779F3-D83C-48B1-BA8D-1912DBD76FC9} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
|
||||
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2} = {3846508C-77EB-4034-A702-F8BB263C4F79}
|
||||
{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
|
||||
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), [@michael-hawker](https://github.com/michael-hawker), [@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), [@michael-hawker](https://github.com/michael-hawker), [@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
|
||||
|
||||
|
||||
117
doc/Fuzzing/CppFuzzingGuide.md
Normal file
117
doc/Fuzzing/CppFuzzingGuide.md
Normal file
@@ -0,0 +1,117 @@
|
||||
# 🧪 C++ Project Fuzzing Test Guide
|
||||
|
||||
This guide walks you through setting up a **fuzzing test** project for a C++ module using [libFuzzer](https://llvm.org/docs/LibFuzzer.html).
|
||||
.
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ Step-by-Step Setup
|
||||
|
||||
### 1. Create a New C++ Project
|
||||
|
||||
- Use **Empty Project** template.
|
||||
- Name it `<ModuleName>.FuzzingTest`.
|
||||
|
||||
---
|
||||
|
||||
### 2. Update Build Configuration
|
||||
|
||||
- In **Configuration Manager**, Uncheck Build for both Release|ARM64, Debug|ARM64 and Debug|x64 configurations.
|
||||
- Note: ARM64 is not supported in this case, so leave ARM64 configurations build disabled.
|
||||
---
|
||||
|
||||
### 3. Enable ASan and libFuzzer in `.vcxproj`
|
||||
|
||||
Edit the project file to enable fuzzing:
|
||||
|
||||
```xml
|
||||
<PropertyGroup>
|
||||
<EnableASAN>true</EnableASAN>
|
||||
<EnableFuzzer>true</EnableFuzzer>
|
||||
</PropertyGroup>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. Add Fuzzing Compiler Flags
|
||||
|
||||
Add this to `AdditionalOptions` under the `Fuzzing` configuration:
|
||||
|
||||
```xml
|
||||
/fsanitize=address
|
||||
/fsanitize-coverage=inline-8bit-counters
|
||||
/fsanitize-coverage=edge
|
||||
/fsanitize-coverage=trace-cmp
|
||||
/fsanitize-coverage=trace-div
|
||||
%(AdditionalOptions)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5. Link the Sanitizer Coverage Runtime
|
||||
|
||||
In `Linker → Input → Additional Dependencies`, add:
|
||||
|
||||
```text
|
||||
$(VCToolsInstallDir)lib\$(Platform)\libsancov.lib
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6. Copy Required Runtime DLL
|
||||
|
||||
Add a `PostBuildEvent` to copy the ASAN DLL:
|
||||
|
||||
```xml
|
||||
<Command>
|
||||
xcopy /y "$(VCToolsInstallDir)bin\Hostx64\x64\clang_rt.asan_dynamic-x86_64.dll" "$(OutDir)"
|
||||
</Command>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 7. Add Preprocessor Definitions
|
||||
|
||||
To avoid annotation issues, add these to the `Preprocessor Definitions`:
|
||||
|
||||
```text
|
||||
_DISABLE_VECTOR_ANNOTATION;_DISABLE_STRING_ANNOTATION
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧬 Required Code
|
||||
|
||||
### `LLVMFuzzerTestOneInput` Entry Point
|
||||
|
||||
Every fuzzing project must expose this function:
|
||||
|
||||
```cpp
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
|
||||
{
|
||||
std::string input(reinterpret_cast<const char*>(data), size);
|
||||
|
||||
try
|
||||
{
|
||||
// Call your module with the input here.
|
||||
}
|
||||
catch (...) {}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ [Test run in the cloud](https://eng.ms/docs/cloud-ai-platform/azure-edge-platform-aep/aep-security/epsf-edge-and-platform-security-fundamentals/the-onefuzz-service/onefuzz/faq/notwindows/walkthrough)
|
||||
|
||||
To submit a job to the cloud you can run with this command:
|
||||
|
||||
```
|
||||
oip submit --config .\OneFuzzConfig.json --drop-path <your_submission_directory> --platform windows --do-not-file-bugs --duration 1
|
||||
```
|
||||
You want to run with --do-not-file-bugs because if there is an issue with running the parser in the cloud (which is very possible), you don't want bugs to be created if there is an issue. The --duration task is the number of hours you want the task to run. I recommend just running for 1 hour to make sure things work initially. If you don't specify this parameter, it will default to 48 hours. You can find more about submitting a test job here.
|
||||
|
||||
OneFuzz will send you an email when the job has started.
|
||||
|
||||
---
|
||||
@@ -21,71 +21,78 @@
|
||||
|
||||
- Create a new project and add the following references to the project file. Change the OutputPath to your own module's path.
|
||||
```
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<!-- This is a UI test, so don't run as part of MSBuild -->
|
||||
<RunVSTest>false</RunVSTest>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\tests\KeyboardManagerUITests\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MSTest" />
|
||||
<ProjectReference Include="..\..\..\common\UITestAutomation\UITestAutomation.csproj" />
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<!-- Look at Directory.Build.props in root for common stuff as well -->
|
||||
<Import Project="..\..\..\Common.Dotnet.CsWinRT.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{4E0AE3A4-2EE0-44D7-A2D0-8769977254A0}</ProjectGuid>
|
||||
<RootNamespace>PowerToys.Hosts.UITests</RootNamespace>
|
||||
<AssemblyName>PowerToys.Hosts.UITests</AssemblyName>
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
<Nullable>enable</Nullable>
|
||||
<OutputType>Library</OutputType>
|
||||
|
||||
<!-- This is a UI test, so don't run as part of MSBuild -->
|
||||
<RunVSTest>false</RunVSTest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\tests\Hosts.UITests\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MSTest" />
|
||||
<ProjectReference Include="..\..\..\common\UITestAutomation\UITestAutomation.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
```
|
||||
- Inherit your test class from UITestBase.
|
||||
>Set Scope: The default scope starts from the PowerToys settings UI. If you want to start from your own module, set the constructor as shown below:
|
||||
|
||||
>Specify Scope:
|
||||
```
|
||||
[TestClass]
|
||||
public class RunFancyZonesTest : UITestBase
|
||||
{
|
||||
public RunFancyZonesTest()
|
||||
: base(PowerToysModule.FancyZone)
|
||||
{
|
||||
}
|
||||
}
|
||||
[TestClass]
|
||||
public class HostModuleTests : UITestBase
|
||||
{
|
||||
public HostModuleTests()
|
||||
: base(PowerToysModule.Hosts, WindowSize.Small_Vertical)
|
||||
{
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- Then you can start using session to perform the UI operations.
|
||||
- Then you can start performing the UI operations.
|
||||
|
||||
**Example**
|
||||
```
|
||||
using Microsoft.PowerToys.UITest;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace UITests_KeyboardManager
|
||||
[TestMethod("Hosts.Basic.EmptyViewShouldWork")]
|
||||
[TestCategory("Hosts File Editor #4")]
|
||||
public void TestEmptyView()
|
||||
{
|
||||
[TestClass]
|
||||
public class RunKeyboardManagerUITests : UITestBase
|
||||
{
|
||||
[TestMethod]
|
||||
public void OpenKeyboardManagerEditor()
|
||||
{
|
||||
// Open KeyboardManagerEditor
|
||||
this.Session.Find<Button>(By.Name("Remap a key")).Click();
|
||||
this.Session.Attach("Remap keys");
|
||||
this.CloseWarningDialog();
|
||||
this.RemoveAllEntries();
|
||||
|
||||
// Maximize window
|
||||
var window = Session.Find<Window>(By.Name("Remap keys")).Maximize();
|
||||
// 'Add an entry' button (only show-up when list is empty) should be visible
|
||||
Assert.IsTrue(this.HasOne<HyperlinkButton>("Add an entry"), "'Add an entry' button should be visible in the empty view");
|
||||
|
||||
// Add Key Remapping
|
||||
this.Session.Find<Button>(By.Name("Add key remapping")).Click();
|
||||
window.Close();
|
||||
VisualAssert.AreEqual(this.TestContext, this.Find("Entries"), "EmptyView");
|
||||
|
||||
// Back to Settings
|
||||
this.Session.Attach(PowerToysModule.PowerToysSettings);
|
||||
}
|
||||
}
|
||||
// Click 'Add an entry' from empty-view for adding Host override rule
|
||||
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.Has<Button>("Delete"), "Should have one row now");
|
||||
Assert.IsFalse(this.Has<HyperlinkButton>("Add an entry"), "'Add an entry' button should be invisible if not empty view");
|
||||
|
||||
VisualAssert.AreEqual(this.TestContext, this.Find("Entries"), "NonEmptyView");
|
||||
}
|
||||
```
|
||||
|
||||
## Extra tools and information
|
||||
|
||||
**Accessibility Tools**:
|
||||
While working on tests, you may need a tool that helps you to view the element's accessibility data, e.g. for finding the button to click. For this purpose, you could use [AccessibilityInsights](https://accessibilityinsights.io/docs/windows/overview)
|
||||
While working on tests, you may need a tool that helps you to view the element's accessibility data, e.g. for finding the button to click. For this purpose, you could use [AccessibilityInsights](https://accessibilityinsights.io/docs/windows/overview).
|
||||
|
||||
@@ -16,49 +16,70 @@ The 'Time and Date' plugin shows the date and time in different formats. For the
|
||||
### Available formats
|
||||
|
||||
**Remarks**
|
||||
- The following formats requires a prefix in the query:
|
||||
- The following formats requires a prefix in the query when using them as date input:
|
||||
- Unix Timestamp: `u`
|
||||
- Unix Timestamp in milliseconds: `ums`
|
||||
- Windows file time: `ft`
|
||||
- OLE Automation date: `oa`
|
||||
- Excel 1900 date value: `exc`
|
||||
- Excel 1904 date value: `exf`
|
||||
- On invalid number inputs we show a warning that tells the user which prefixes are allowed/required.
|
||||
|
||||
**List of available formats**
|
||||
|
||||
The following formats are currently available:
|
||||
|
||||
| Format | Example (Based on default settings) | As result | As input |
|
||||
| Format | Example (Based on default settings) | As result | As input | Result as custom format only
|
||||
|--------------|-----------|------------|------------|
|
||||
| Time | 5:10 PM | x | x |
|
||||
| Date | 3/5/2022 | x | x |
|
||||
| Now | 3/5/2022 5:10 PM | x | x |
|
||||
| Time UTC | 4:10 PM | x | x |
|
||||
| Now UTC | 3/5/2022 4:10 PM | x | x |
|
||||
| Unix Timestamp | 1646496622 | x | x |
|
||||
| Unix Timestamp in milliseconds | 1646496622500 | x | x |
|
||||
| Hour | 10 | x | |
|
||||
| Minute | 30 | x | |
|
||||
| Second | 45 | x | |
|
||||
| Millisecond | 678 | x | |
|
||||
| Day (Week day) | Saturday | x | |
|
||||
| Day of the week | 6 | x | |
|
||||
| Day of the month | 5 | x | |
|
||||
| Day of the year | 64 | x | |
|
||||
| Week of the month | 1 | x | |
|
||||
| Week of the year (Calendar week, Week number) | 10 | x | |
|
||||
| Month | March | x | |
|
||||
| Month of the year | 3 | x | |
|
||||
| Month and day | March 7 | x | x |
|
||||
| Year | 2022 | x | |
|
||||
| Era | AD | x | |
|
||||
| Era abbreviation | A | x | |
|
||||
| Month and year | March 2022 | x | x |
|
||||
| Windows file time (Int64 number) | 637820976123938199 | x | x |
|
||||
| Universal time format: YYYY-MM-DD hh:mm:ss| 2022-03-05 16:20:12Z | x | x |
|
||||
| ISO 8601 | 2022-03-05T17:23:04 | x | x |
|
||||
| ISO 8601 UTC | 2022-03-05T16:23:04 | x | x |
|
||||
| ISO 8601 with time zone | 2022-03-05T17:23:04+01:00 | x | x |
|
||||
| ISO 8601 UTC with time zone | 2022-03-05T16:23:04Z | x | x |
|
||||
| RFC1123 | Sat, 05 Mar 2022 16:23:04 GMT | x | x |
|
||||
| Time | 5:10 PM | x | x | |
|
||||
| Date | 3/5/2022 | x | x | |
|
||||
| Now | 3/5/2022 5:10 PM | x | x | |
|
||||
| Time UTC | 4:10 PM | x | x | |
|
||||
| Now UTC | 3/5/2022 4:10 PM | x | x | |
|
||||
| Unix Timestamp | 1646496622 | x | x | |
|
||||
| Unix Timestamp in milliseconds | 1646496622500 | x | x | |
|
||||
| Hour | 10 | x | | |
|
||||
| Minute | 30 | x | | |
|
||||
| Second | 45 | x | | |
|
||||
| Millisecond | 678 | x | | |
|
||||
| Day (Week day) | Saturday | x | | |
|
||||
| Day of the week | 6 | x | | |
|
||||
| Day of the month | 5 | x | | |
|
||||
| Day of the year | 64 | x | | |
|
||||
| Week of the month | 1 | x | | |
|
||||
| Week of the year (Calendar week, Week number) | 10 | x | | |
|
||||
| Month | March | x | | |
|
||||
| Month of the year | 3 | x | | |
|
||||
| Month and day | March 7 | x | x | |
|
||||
| Year | 2022 | x | | |
|
||||
| Era | AD | x | | |
|
||||
| Era abbreviation | A | x | | |
|
||||
| Month and year | March 2022 | x | x | |
|
||||
| Windows file time (Int64 number) | 637820976123938199 | x | x | |
|
||||
| Universal time format: YYYY-MM-DD hh:mm:ss| 2022-03-05 16:20:12Z | x | x | |
|
||||
| ISO 8601 | 2022-03-05T17:23:04 | x | x | |
|
||||
| ISO 8601 UTC | 2022-03-05T16:23:04 | x | x | |
|
||||
| ISO 8601 with time zone | 2022-03-05T17:23:04+01:00 | x | x | |
|
||||
| ISO 8601 UTC with time zone | 2022-03-05T16:23:04Z | x | x | |
|
||||
| RFC1123 | Sat, 05 Mar 2022 16:23:04 GMT | x | x | |
|
||||
| OLE Automation date | 45723.44143763889 | | x | x |
|
||||
| Excel's 1900 date value | 45723.44143763889 | | x | x |
|
||||
| Excel's 1904 date value | 44261.44143763889 | | x | x |
|
||||
|
||||
**Custom format definition**
|
||||
The user can create its own formats. One per line in the settings text box. The format of each line is `<name>=<syntax pattern>`.
|
||||
If the syntax pattern starting with `UTC:` then we use the UTC time instead of the local time.
|
||||
As syntax pattern the pattern from `DateTime.ToString()` and the following custom pattern are available:
|
||||
- DOW: Number of the day in the week.
|
||||
- WOM: Number of week in the month.
|
||||
- WOY: Number of the week in the year.
|
||||
- EAB: Era abbreviation.
|
||||
- WFT: Windows file time.
|
||||
- UXT: Unix time stamp.
|
||||
- UMS: Unix time stamp in milliseconds.
|
||||
- OAD: OLE Automation date.
|
||||
- EXC: Excel's 1900 based date value.
|
||||
- EXF: Excel's 1904 based date value.
|
||||
|
||||
### Add new formats
|
||||
- To add a new formats you have to add them to the method `GetList()` of the [`AvailableResultsList`](/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate/Components/AvailableResultsList.cs) class.
|
||||
@@ -73,13 +94,13 @@ The following formats are currently available:
|
||||
|
||||
| Key | Type | Default value | Name | Description |
|
||||
|--------------|--------------|-----------|------------|------------|
|
||||
| `CalendarFirstWeekRule` | Combo box | `-1` (Use system settings) | First week of the year | Configure the calendar rule for the first week of the year. |
|
||||
| `FirstDayOfWeek` | Combo box | `-1` (Use system settings) | First day of the week | |
|
||||
| `OnlyDateTimeNowGlobal` | Checkbox | `true` | Show only 'Time', 'Date', and 'Now' result for system time on global queries | Regardless of this setting, for global queries the first word of the query has to be a complete match. |
|
||||
| `TimeWithSeconds` | Checkbox | `false` | Show time with seconds | This setting applies to the 'Time' and 'Now' result. |
|
||||
| `DateWithWeekday` | Checkbox | `false` | Show date with weekday and name of month | This setting applies to the 'Date' and 'Now' result. |
|
||||
| `HideNumberMessageOnGlobalQuery` | Checkbox | `false` | Hide 'Invalid number input' error message on global queries | |
|
||||
|
||||
| `CalendarFirstWeekRule` | Combo box | `-1` (Use system settings) | First week of the year | Configure the calendar rule for the first week of the year. |
|
||||
| `FirstDayOfWeek` | Combo box | `-1` (Use system settings) | First day of the week | |
|
||||
| `CustomFormats` | Multiline text box | `string.Empty` | Custom formats | Use date and time string format syntax and DOW (Day of Week), WOM (Week of Month), WOY (Week of the year), EAB (Era abbreviation), WFT (Windows File Time), UXT (Unix Time), UMS (Unix Time in milliseconds), OAD (OLE Automation date), EXC (Excel's 1900 based date value), EXF (Excel's 1904 based date value). If the format starts with UTC:, then Universal Time (UTC) is used. (Use a backslash to escape format sequences and the backslash character as text.) |
|
||||
|
||||
## Classes
|
||||
|
||||
|
||||
@@ -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,10 @@ 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. |
|
||||
| [QuickNotes](https://github.com/ruslanlap/CommunityPowerToysRunPlugin-QuickNotes) | [ruslanlap](https://github.com/ruslanlap) | Create, manage, and search notes directly from PowerToys Run. |
|
||||
| [Weather](https://github.com/ruslanlap/PowerToysRun-Weather) | [ruslanlap](https://github.com/ruslanlap) | Get real-time weather information directly from PowerToys Run. |
|
||||
| [Pomodoro](https://github.com/ruslanlap/PowerToysRun-Pomodoro) | [ruslanlap](https://github.com/ruslanlap) | Manage Pomodoro productivity sessions directly from PowerToys Run. |
|
||||
|
||||
## Extending software plugins
|
||||
|
||||
@@ -63,3 +67,5 @@ 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 |
|
||||
[Linear](https://github.com/vednig/powertoys-linear) | [vednig](https://github.com/vednig) | Create Linear Issues directly from Powertoys Run |
|
||||
|
||||
74
installer/PowerToysSetup/CmdPal.wxs
Normal file
74
installer/PowerToysSetup/CmdPal.wxs
Normal file
@@ -0,0 +1,74 @@
|
||||
<?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" />
|
||||
</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" />
|
||||
</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,7 @@
|
||||
<ComponentGroupRef Id="ToolComponentGroup" />
|
||||
<ComponentGroupRef Id="MonacoSRCHeatGenerated" />
|
||||
<ComponentGroupRef Id="WorkspacesComponentGroup" />
|
||||
<ComponentGroupRef Id="CmdPalComponentGroup" />
|
||||
</Feature>
|
||||
|
||||
<SetProperty Id="ARPINSTALLLOCATION" Value="[INSTALLFOLDER]" After="CostFinalize" />
|
||||
@@ -135,6 +136,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 +152,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 +176,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 +212,10 @@
|
||||
Property="LaunchPowerToys"
|
||||
Value="[INSTALLFOLDER]" />
|
||||
|
||||
<CustomAction Id="SetInstallCmdPalPackageParam"
|
||||
Property="InstallCmdPalPackage"
|
||||
Value="[INSTALLFOLDER]" />
|
||||
|
||||
<CustomAction
|
||||
Id="LaunchPowerToys"
|
||||
Return="ignore"
|
||||
@@ -427,6 +439,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 +454,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>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Some items may be set in Directory.Build.props in root -->
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project=".\Common.Dotnet.PrepareGeneratedFolder.targets" />
|
||||
|
||||
<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 +16,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'">
|
||||
|
||||
10
src/Common.Dotnet.FuzzTest.props
Normal file
10
src/Common.Dotnet.FuzzTest.props
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Some items may be set in Directory.Build.props in root -->
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<!-- OneFuzz does not currently support testing with .NET 9.
|
||||
As a temporary workaround, create a .NET 8 project and use file links
|
||||
to include the code that needs testing. -->
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
16
src/Common.Dotnet.PrepareGeneratedFolder.targets
Normal file
16
src/Common.Dotnet.PrepareGeneratedFolder.targets
Normal file
@@ -0,0 +1,16 @@
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<Target Name="EnsureGeneratedBaseFolder" BeforeTargets="XamlPreCompile">
|
||||
<PropertyGroup>
|
||||
<!-- Only create the base 'generated' folder -->
|
||||
<CompilerGeneratedFilesOutputPath>$(ProjectDir)obj\g</CompilerGeneratedFilesOutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Create 'generated' folder if missing -->
|
||||
<MakeDir Directories="$(CompilerGeneratedFilesOutputPath)" />
|
||||
|
||||
<!-- Optional logging for debugging -->
|
||||
<Message Text="Ensured: $(GeneratedBasePath)" Importance="Low" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// 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.
|
||||
|
||||
@@ -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,17 @@ 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 MVVMTK0045
|
||||
[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 = "AdvancedPaste.ViewModels")]
|
||||
[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 = "EnvironmentVariablesUILib")]
|
||||
[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.FilePreviewer")]
|
||||
[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.ObservablePropertyGenerator", "MVVMTK0045:Using [ObservableProperty] on fields is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib")]
|
||||
|
||||
// AOT MVVMTK0049
|
||||
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0049:Using [INotifyPropertyChanged] is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "Peek.FilePreviewer")]
|
||||
[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")]
|
||||
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0049:Using [INotifyPropertyChanged] is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib")]
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace AllExperiments
|
||||
}
|
||||
|
||||
// Using InvariantCulture since this is used for a log file name
|
||||
var logFilePath = Path.Combine(ApplicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".txt");
|
||||
var logFilePath = Path.Combine(ApplicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".log");
|
||||
|
||||
Trace.Listeners.Add(new TextWriterTraceListener(logFilePath));
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<!-- Look at Directory.Build.props in root for common stuff as well -->
|
||||
<Import Project="..\..\Common.Dotnet.CsWinRT.props" />
|
||||
<Import Project="..\..\Common.Dotnet.AotCompatibility.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<UseWPF>true</UseWPF>
|
||||
|
||||
@@ -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:
|
||||
@@ -91,20 +94,20 @@ namespace Common.UI
|
||||
{
|
||||
try
|
||||
{
|
||||
var assemblyPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
|
||||
var fullPath = new DirectoryInfo(assemblyPath).FullName;
|
||||
var directoryPath = System.AppContext.BaseDirectory;
|
||||
if (mainExecutableIsOnTheParentFolder)
|
||||
{
|
||||
// Need to go into parent folder for PowerToys.exe. Likely a WinUI3 App SDK application.
|
||||
fullPath = fullPath + "\\..\\PowerToys.exe";
|
||||
directoryPath = Path.Combine(directoryPath, "..");
|
||||
directoryPath = Path.Combine(directoryPath, "PowerToys.exe");
|
||||
}
|
||||
else
|
||||
{
|
||||
// PowerToys.exe is in the same path as the application.
|
||||
fullPath = fullPath + "\\PowerToys.exe";
|
||||
directoryPath = Path.Combine(directoryPath, "PowerToys.exe");
|
||||
}
|
||||
|
||||
Process.Start(new ProcessStartInfo(fullPath) { Arguments = "--open-settings=" + SettingsWindowNameToString(window) });
|
||||
Process.Start(new ProcessStartInfo(directoryPath) { Arguments = "--open-settings=" + SettingsWindowNameToString(window) });
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@ using Microsoft.Win32;
|
||||
|
||||
namespace Common.UI
|
||||
{
|
||||
public class ThemeManager : IDisposable
|
||||
public partial class ThemeManager : IDisposable
|
||||
{
|
||||
private readonly Application _app;
|
||||
private const string LightTheme = "Light.Accent1";
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,6 +141,40 @@ namespace ManagedCommon
|
||||
return lab;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a given <see cref="Color"/> to a Oklab color
|
||||
/// </summary>
|
||||
/// <param name="color">The <see cref="Color"/> to convert</param>
|
||||
/// <returns>The perceptual lightness [0..1] and two chromaticities [-0.5..0.5]</returns>
|
||||
public static (double Lightness, double ChromaticityA, double ChromaticityB) ConvertToOklabColor(Color color)
|
||||
{
|
||||
var linear = ConvertSRGBToLinearRGB(color.R / 255d, color.G / 255d, color.B / 255d);
|
||||
var oklab = GetOklabColorFromLinearRGB(linear.R, linear.G, linear.B);
|
||||
return oklab;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a given <see cref="Color"/> to a Oklch color
|
||||
/// </summary>
|
||||
/// <param name="color">The <see cref="Color"/> to convert</param>
|
||||
/// <returns>The perceptual lightness [0..1], the chroma [0..0.5], and the hue angle [0°..360°]</returns>
|
||||
public static (double Lightness, double Chroma, double Hue) ConvertToOklchColor(Color color)
|
||||
{
|
||||
var oklab = ConvertToOklabColor(color);
|
||||
var oklch = GetOklchColorFromOklab(oklab.Lightness, oklab.ChromaticityA, oklab.ChromaticityB);
|
||||
|
||||
return oklch;
|
||||
}
|
||||
|
||||
public static (double R, double G, double B) ConvertSRGBToLinearRGB(double r, double g, double b)
|
||||
{
|
||||
// inverse companding, gamma correction must be undone
|
||||
double rLinear = (r > 0.04045) ? Math.Pow((r + 0.055) / 1.055, 2.4) : (r / 12.92);
|
||||
double gLinear = (g > 0.04045) ? Math.Pow((g + 0.055) / 1.055, 2.4) : (g / 12.92);
|
||||
double bLinear = (b > 0.04045) ? Math.Pow((b + 0.055) / 1.055, 2.4) : (b / 12.92);
|
||||
return (rLinear, gLinear, bLinear);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a given <see cref="Color"/> to a CIE XYZ color (XYZ)
|
||||
/// The constants of the formula matches this Wikipedia page, but at a higher precision:
|
||||
@@ -156,10 +190,7 @@ namespace ManagedCommon
|
||||
double g = color.G / 255d;
|
||||
double b = color.B / 255d;
|
||||
|
||||
// inverse companding, gamma correction must be undone
|
||||
double rLinear = (r > 0.04045) ? Math.Pow((r + 0.055) / 1.055, 2.4) : (r / 12.92);
|
||||
double gLinear = (g > 0.04045) ? Math.Pow((g + 0.055) / 1.055, 2.4) : (g / 12.92);
|
||||
double bLinear = (b > 0.04045) ? Math.Pow((b + 0.055) / 1.055, 2.4) : (b / 12.92);
|
||||
(double rLinear, double gLinear, double bLinear) = ConvertSRGBToLinearRGB(r, g, b);
|
||||
|
||||
return (
|
||||
(rLinear * 0.41239079926595948) + (gLinear * 0.35758433938387796) + (bLinear * 0.18048078840183429),
|
||||
@@ -210,6 +241,63 @@ namespace ManagedCommon
|
||||
return (l, a, b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a linear RGB color <see cref="double"/> to an Oklab color.
|
||||
/// The constants of this formula come from https://github.com/Evercoder/culori/blob/2bedb8f0507116e75f844a705d0b45cf279b15d0/src/oklab/convertLrgbToOklab.js
|
||||
/// and the implementation is based on https://bottosson.github.io/posts/oklab/
|
||||
/// </summary>
|
||||
/// <param name="r">Linear R value</param>
|
||||
/// <param name="g">Linear G value</param>
|
||||
/// <param name="b">Linear B value</param>
|
||||
/// <returns>The perceptual lightness [0..1] and two chromaticities [-0.5..0.5]</returns>
|
||||
private static (double Lightness, double ChromaticityA, double ChromaticityB)
|
||||
GetOklabColorFromLinearRGB(double r, double g, double b)
|
||||
{
|
||||
double l = (0.41222147079999993 * r) + (0.5363325363 * g) + (0.0514459929 * b);
|
||||
double m = (0.2119034981999999 * r) + (0.6806995450999999 * g) + (0.1073969566 * b);
|
||||
double s = (0.08830246189999998 * r) + (0.2817188376 * g) + (0.6299787005000002 * b);
|
||||
|
||||
double l_ = Math.Cbrt(l);
|
||||
double m_ = Math.Cbrt(m);
|
||||
double s_ = Math.Cbrt(s);
|
||||
|
||||
return (
|
||||
(0.2104542553 * l_) + (0.793617785 * m_) - (0.0040720468 * s_),
|
||||
(1.9779984951 * l_) - (2.428592205 * m_) + (0.4505937099 * s_),
|
||||
(0.0259040371 * l_) + (0.7827717662 * m_) - (0.808675766 * s_)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert an Oklab color <see cref="double"/> from Cartesian form to its polar form Oklch
|
||||
/// https://bottosson.github.io/posts/oklab/#the-oklab-color-space
|
||||
/// </summary>
|
||||
/// <param name="lightness">The <see cref="lightness"/></param>
|
||||
/// <param name="chromaticity_a">The <see cref="chromaticity_a"/></param>
|
||||
/// <param name="chromaticity_b">The <see cref="chromaticity_b"/></param>
|
||||
/// <returns>The perceptual lightness [0..1], the chroma [0..0.5], and the hue angle [0°..360°]</returns>
|
||||
private static (double Lightness, double Chroma, double Hue)
|
||||
GetOklchColorFromOklab(double lightness, double chromaticity_a, double chromaticity_b)
|
||||
{
|
||||
return GetLCHColorFromLAB(lightness, chromaticity_a, chromaticity_b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a color in Cartesian form (Lab) to its polar form (LCh)
|
||||
/// </summary>
|
||||
/// <param name="lightness">The <see cref="lightness"/></param>
|
||||
/// <param name="chromaticity_a">The <see cref="chromaticity_a"/></param>
|
||||
/// <param name="chromaticity_b">The <see cref="chromaticity_b"/></param>
|
||||
/// <returns>The lightness, chroma, and hue angle</returns>
|
||||
private static (double Lightness, double Chroma, double Hue)
|
||||
GetLCHColorFromLAB(double lightness, double chromaticity_a, double chromaticity_b)
|
||||
{
|
||||
// Lab to LCh transformation
|
||||
double chroma = Math.Sqrt(Math.Pow(chromaticity_a, 2) + Math.Pow(chromaticity_b, 2));
|
||||
double hue = Math.Round(chroma, 3) == 0 ? 0.0 : ((Math.Atan2(chromaticity_b, chromaticity_a) * 180d / Math.PI) + 360d) % 360d;
|
||||
return (lightness, chroma, hue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a given <see cref="Color"/> to a natural color (hue, whiteness, blackness)
|
||||
/// </summary>
|
||||
@@ -276,12 +364,17 @@ namespace ManagedCommon
|
||||
{ "Br", 'p' }, // brightness percent
|
||||
{ "In", 'p' }, // intensity percent
|
||||
{ "Ll", 'p' }, // lightness (HSL) percent
|
||||
{ "Lc", 'p' }, // lightness(CIELAB)percent
|
||||
{ "Va", 'p' }, // value percent
|
||||
{ "Wh", 'p' }, // whiteness percent
|
||||
{ "Bn", 'p' }, // blackness percent
|
||||
{ "Ca", 'p' }, // chromaticityA percent
|
||||
{ "Cb", 'p' }, // chromaticityB percent
|
||||
{ "Lc", 'p' }, // lightness (CIE) percent
|
||||
{ "Ca", 'p' }, // chromaticityA (CIELAB) percent
|
||||
{ "Cb", 'p' }, // chromaticityB (CIELAB) percent
|
||||
{ "Lo", 'p' }, // lightness (Oklab/Oklch) percent
|
||||
{ "Oa", 'p' }, // chromaticityA (Oklab) percent
|
||||
{ "Ob", 'p' }, // chromaticityB (Oklab) percent
|
||||
{ "Oc", 'p' }, // chroma (Oklch) percent
|
||||
{ "Oh", 'p' }, // hue angle (Oklch) percent
|
||||
{ "Xv", 'i' }, // X value int
|
||||
{ "Yv", 'i' }, // Y value int
|
||||
{ "Zv", 'i' }, // Z value int
|
||||
@@ -424,6 +517,10 @@ namespace ManagedCommon
|
||||
var (lightnessC, _, _) = ConvertToCIELABColor(color);
|
||||
lightnessC = Math.Round(lightnessC, 2);
|
||||
return lightnessC.ToString(CultureInfo.InvariantCulture);
|
||||
case "Lo":
|
||||
var (lightnessO, _, _) = ConvertToOklabColor(color);
|
||||
lightnessO = Math.Round(lightnessO, 2);
|
||||
return lightnessO.ToString(CultureInfo.InvariantCulture);
|
||||
case "Wh":
|
||||
var (_, whiteness, _) = ConvertToHWBColor(color);
|
||||
whiteness = Math.Round(whiteness * 100);
|
||||
@@ -440,6 +537,22 @@ namespace ManagedCommon
|
||||
var (_, _, chromaticityB) = ConvertToCIELABColor(color);
|
||||
chromaticityB = Math.Round(chromaticityB, 2);
|
||||
return chromaticityB.ToString(CultureInfo.InvariantCulture);
|
||||
case "Oa":
|
||||
var (_, chromaticityAOklab, _) = ConvertToOklabColor(color);
|
||||
chromaticityAOklab = Math.Round(chromaticityAOklab, 2);
|
||||
return chromaticityAOklab.ToString(CultureInfo.InvariantCulture);
|
||||
case "Ob":
|
||||
var (_, _, chromaticityBOklab) = ConvertToOklabColor(color);
|
||||
chromaticityBOklab = Math.Round(chromaticityBOklab, 2);
|
||||
return chromaticityBOklab.ToString(CultureInfo.InvariantCulture);
|
||||
case "Oc":
|
||||
var (_, chromaOklch, _) = ConvertToOklchColor(color);
|
||||
chromaOklch = Math.Round(chromaOklch, 2);
|
||||
return chromaOklch.ToString(CultureInfo.InvariantCulture);
|
||||
case "Oh":
|
||||
var (_, _, hueOklch) = ConvertToOklchColor(color);
|
||||
hueOklch = Math.Round(hueOklch, 2);
|
||||
return hueOklch.ToString(CultureInfo.InvariantCulture);
|
||||
case "Xv":
|
||||
var (x, _, _) = ConvertToCIEXYZColor(color);
|
||||
x = Math.Round(x * 100, 4);
|
||||
@@ -495,8 +608,10 @@ namespace ManagedCommon
|
||||
case "HSI": return "hsi(%Hu, %Si%, %In%)";
|
||||
case "HWB": return "hwb(%Hu, %Wh%, %Bn%)";
|
||||
case "NCol": return "%Hn, %Wh%, %Bn%";
|
||||
case "CIELAB": return "CIELab(%Lc, %Ca, %Cb)";
|
||||
case "CIEXYZ": return "XYZ(%Xv, %Yv, %Zv)";
|
||||
case "CIELAB": return "CIELab(%Lc, %Ca, %Cb)";
|
||||
case "Oklab": return "oklab(%Lo, %Oa, %Ob)";
|
||||
case "Oklch": return "oklch(%Lo, %Oc, %Oh)";
|
||||
case "VEC4": return "(%Reff, %Grff, %Blff, 1f)";
|
||||
case "Decimal": return "%Dv";
|
||||
case "HEX Int": return "0xFF%ReX%GrX%BlX";
|
||||
|
||||
51
src/common/ManagedCommon/IdRecoveryHelper.cs
Normal file
51
src/common/ManagedCommon/IdRecoveryHelper.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
// 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.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ManagedCommon
|
||||
{
|
||||
public static class IdRecoveryHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Fixes invalid IDs in the given list by assigning unique values.
|
||||
/// It ensures that all IDs are non-empty and unique, correcting any duplicates or empty IDs.
|
||||
/// </summary>
|
||||
/// <param name="items">The list of items that may contain invalid IDs.</param>
|
||||
public static void RecoverInvalidIds<T>(IEnumerable<T> items)
|
||||
where T : class, IHasId
|
||||
{
|
||||
var idSet = new HashSet<int>();
|
||||
int newId = 0;
|
||||
var sortedItems = items.OrderBy(i => i.Id).ToList(); // Sort items by ID for consistent processing
|
||||
|
||||
// Iterate through the list and fix invalid IDs
|
||||
foreach (var item in sortedItems)
|
||||
{
|
||||
// If the ID is invalid or already exists in the set (duplicate), assign a new unique ID
|
||||
if (!idSet.Add(item.Id))
|
||||
{
|
||||
// Find the next available unique ID
|
||||
while (idSet.Contains(newId))
|
||||
{
|
||||
newId++;
|
||||
}
|
||||
|
||||
item.Id = newId;
|
||||
idSet.Add(newId); // Add the newly assigned ID to the set
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface IHasId
|
||||
{
|
||||
int Id { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ using System;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using ManagedCommon.Serialization;
|
||||
|
||||
namespace ManagedCommon
|
||||
{
|
||||
@@ -35,7 +36,7 @@ namespace ManagedCommon
|
||||
inputStream.Close();
|
||||
reader.Dispose();
|
||||
|
||||
return JsonSerializer.Deserialize<OutGoingLanguageSettings>(data).LanguageTag;
|
||||
return JsonSerializer.Deserialize<OutGoingLanguageSettings>(data, SourceGenerationContext.Default.OutGoingLanguageSettings).LanguageTag;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
@@ -15,15 +15,23 @@ namespace ManagedCommon
|
||||
{
|
||||
public static class Logger
|
||||
{
|
||||
private static readonly Assembly Assembly = Assembly.GetExecutingAssembly();
|
||||
private static readonly string Version = FileVersionInfo.GetVersionInfo(Assembly.Location).ProductVersion;
|
||||
|
||||
private static readonly string Error = "Error";
|
||||
private static readonly string Warning = "Warning";
|
||||
private static readonly string Info = "Info";
|
||||
private static readonly string Debug = "Debug";
|
||||
private static readonly string TraceFlag = "Trace";
|
||||
|
||||
private static readonly Assembly Assembly = Assembly.GetExecutingAssembly();
|
||||
|
||||
/*
|
||||
* Please pay more attention!
|
||||
* If you want to publish it with Native AOT enabled (or publish as a single file).
|
||||
* You need to find another way to remove Assembly.Location usage.
|
||||
*/
|
||||
#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file
|
||||
private static readonly string Version = FileVersionInfo.GetVersionInfo(Assembly.Location).ProductVersion;
|
||||
#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the logger and sets the path for logging.
|
||||
/// </summary>
|
||||
@@ -46,25 +54,23 @@ namespace ManagedCommon
|
||||
Directory.CreateDirectory(applicationLogPath);
|
||||
}
|
||||
|
||||
var logFilePath = Path.Combine(applicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".txt");
|
||||
var logFilePath = Path.Combine(applicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".log");
|
||||
|
||||
Trace.Listeners.Add(new TextWriterTraceListener(logFilePath));
|
||||
|
||||
Trace.AutoFlush = true;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static void LogError(string message)
|
||||
public static void LogError(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
|
||||
{
|
||||
Log(message, Error);
|
||||
Log(message, Error, memberName, sourceFilePath, sourceLineNumber);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static void LogError(string message, Exception ex)
|
||||
public static void LogError(string message, Exception ex, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
|
||||
{
|
||||
if (ex == null)
|
||||
{
|
||||
Log(message, Error);
|
||||
Log(message, Error, memberName, sourceFilePath, sourceLineNumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -83,38 +89,33 @@ namespace ManagedCommon
|
||||
"Stack trace: " + Environment.NewLine +
|
||||
ex.StackTrace;
|
||||
|
||||
Log(exMessage, Error);
|
||||
Log(exMessage, Error, memberName, sourceFilePath, sourceLineNumber);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static void LogWarning(string message)
|
||||
public static void LogWarning(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
|
||||
{
|
||||
Log(message, Warning);
|
||||
Log(message, Warning, memberName, sourceFilePath, sourceLineNumber);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static void LogInfo(string message)
|
||||
public static void LogInfo(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
|
||||
{
|
||||
Log(message, Info);
|
||||
Log(message, Info, memberName, sourceFilePath, sourceLineNumber);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static void LogDebug(string message)
|
||||
public static void LogDebug(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
|
||||
{
|
||||
Log(message, Debug);
|
||||
Log(message, Debug, memberName, sourceFilePath, sourceLineNumber);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static void LogTrace()
|
||||
public static void LogTrace([System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
|
||||
{
|
||||
Log(string.Empty, TraceFlag);
|
||||
Log(string.Empty, TraceFlag, memberName, sourceFilePath, sourceLineNumber);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static void Log(string message, string type)
|
||||
private static void Log(string message, string type, string memberName, string sourceFilePath, int sourceLineNumber)
|
||||
{
|
||||
Trace.WriteLine("[" + DateTime.Now.TimeOfDay + "] [" + type + "] " + GetCallerInfo());
|
||||
Trace.WriteLine("[" + DateTime.Now.TimeOfDay + "] [" + type + "] " + GetCallerInfo(memberName, sourceFilePath, sourceLineNumber));
|
||||
Trace.Indent();
|
||||
if (message != string.Empty)
|
||||
{
|
||||
@@ -124,49 +125,27 @@ namespace ManagedCommon
|
||||
Trace.Unindent();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static string GetCallerInfo()
|
||||
private static string GetCallerInfo(string memberName, string sourceFilePath, int sourceLineNumber)
|
||||
{
|
||||
StackTrace stackTrace = new();
|
||||
|
||||
var callerMethod = GetCallerMethod(stackTrace);
|
||||
|
||||
return $"{callerMethod?.DeclaringType?.Name}::{callerMethod.Name}";
|
||||
}
|
||||
|
||||
private static MethodBase GetCallerMethod(StackTrace stackTrace)
|
||||
{
|
||||
const int topFrame = 3;
|
||||
|
||||
var topMethod = stackTrace.GetFrame(topFrame)?.GetMethod();
|
||||
string callerFileName = "Unknown";
|
||||
|
||||
try
|
||||
{
|
||||
if (topMethod?.Name == nameof(IAsyncStateMachine.MoveNext) && typeof(IAsyncStateMachine).IsAssignableFrom(topMethod?.DeclaringType))
|
||||
string fileName = Path.GetFileName(sourceFilePath);
|
||||
if (!string.IsNullOrEmpty(fileName))
|
||||
{
|
||||
// Async method; return actual method as determined by heuristic:
|
||||
// "Nearest method on stack to async state-machine's MoveNext() in same namespace but in a different type".
|
||||
// There are tighter ways of determining the actual method, but this is good enough and probably faster.
|
||||
for (int deepFrame = topFrame + 1; deepFrame < stackTrace.FrameCount; deepFrame++)
|
||||
{
|
||||
var deepMethod = stackTrace.GetFrame(deepFrame)?.GetMethod();
|
||||
|
||||
if (deepMethod?.DeclaringType != topMethod?.DeclaringType && deepMethod?.DeclaringType?.Namespace == topMethod?.DeclaringType?.Namespace)
|
||||
{
|
||||
return deepMethod;
|
||||
}
|
||||
}
|
||||
callerFileName = fileName;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Ignore exceptions in Release. The code above won't throw, but if it does, we don't want to crash the app.
|
||||
callerFileName = "Unknown";
|
||||
#if DEBUG
|
||||
throw;
|
||||
#endif
|
||||
}
|
||||
|
||||
return topMethod;
|
||||
return $"{callerFileName}::{memberName}::{sourceLineNumber}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<!-- Look at Directory.Build.props in root for common stuff as well -->
|
||||
<Import Project="..\..\Common.Dotnet.CsWinRT.props" />
|
||||
<Import Project="..\..\Common.Dotnet.AotCompatibility.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>PowerToys ManagedCommon</Description>
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace ManagedCommon
|
||||
AlwaysOnTop,
|
||||
Awake,
|
||||
ColorPicker,
|
||||
CmdPal,
|
||||
CropAndLock,
|
||||
EnvironmentVariables,
|
||||
FancyZones,
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace ManagedCommon
|
||||
|
||||
internal static int Size
|
||||
{
|
||||
get { return Marshal.SizeOf(typeof(INPUT)); }
|
||||
get { return Marshal.SizeOf<INPUT>(); }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,12 +14,11 @@ namespace ManagedCommon
|
||||
{
|
||||
public static class RunnerHelper
|
||||
{
|
||||
public static void WaitForPowerToysRunner(int powerToysPID, Action act)
|
||||
public static void WaitForPowerToysRunner(int powerToysPID, Action act, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "")
|
||||
{
|
||||
var stackTrace = new StackTrace();
|
||||
var assembly = Assembly.GetCallingAssembly().GetName();
|
||||
var callingMethod = stackTrace.GetFrame(1).GetMethod().Name;
|
||||
PowerToysTelemetry.Log.WriteEvent(new DebugEvent() { Message = $"[{assembly}][{callingMethod}]WaitForPowerToysRunner waiting for Event powerToysPID={powerToysPID}" });
|
||||
PowerToysTelemetry.Log.WriteEvent(new DebugEvent() { Message = $"[{assembly}][{memberName}]WaitForPowerToysRunner waiting for Event powerToysPID={powerToysPID}" });
|
||||
Task.Run(() =>
|
||||
{
|
||||
const uint INFINITE = 0xFFFFFFFF;
|
||||
@@ -29,7 +28,7 @@ namespace ManagedCommon
|
||||
IntPtr powerToysProcHandle = NativeMethods.OpenProcess(SYNCHRONIZE, false, powerToysPID);
|
||||
if (NativeMethods.WaitForSingleObject(powerToysProcHandle, INFINITE) == WAIT_OBJECT_0)
|
||||
{
|
||||
PowerToysTelemetry.Log.WriteEvent(new DebugEvent() { Message = $"[{assembly}][{callingMethod}]WaitForPowerToysRunner Event Notified powerToysPID={powerToysPID}" });
|
||||
PowerToysTelemetry.Log.WriteEvent(new DebugEvent() { Message = $"[{assembly}][{memberName}]WaitForPowerToysRunner Event Notified powerToysPID={powerToysPID}" });
|
||||
act.Invoke();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Text.Json.Serialization;
|
||||
using static ManagedCommon.LanguageHelper;
|
||||
|
||||
namespace ManagedCommon.Serialization;
|
||||
|
||||
[JsonSerializable(typeof(OutGoingLanguageSettings))]
|
||||
internal sealed partial class SourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
@@ -14,7 +14,7 @@ namespace ManagedCommon
|
||||
/// <param name="sender">Sender ThemeListener</param>
|
||||
public delegate void ThemeChangedEvent(ThemeListener sender);
|
||||
|
||||
public class ThemeListener : IDisposable
|
||||
public partial class ThemeListener : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the App Theme.
|
||||
|
||||
1105
src/common/UITestAutomation/Doc/ui-automation-cover-list.md
Normal file
1105
src/common/UITestAutomation/Doc/ui-automation-cover-list.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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!;
|
||||
}
|
||||
}
|
||||
|
||||
53
src/common/UITestAutomation/Element/CheckBox.cs
Normal file
53
src/common/UITestAutomation/Element/CheckBox.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
// 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
|
||||
{
|
||||
public class CheckBox : Element
|
||||
{
|
||||
private static readonly string ExpectedControlType = "ControlType.CheckBox";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CheckBox"/> class.
|
||||
/// </summary>
|
||||
public CheckBox()
|
||||
{
|
||||
this.TargetControlType = CheckBox.ExpectedControlType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Select the item of the ComboBox.
|
||||
/// </summary>
|
||||
/// <param name="value">The text to select from the list view.</param>
|
||||
public void Select(string value)
|
||||
{
|
||||
this.Find<NavigationViewItem>(value).Click();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the CheckBox is checked.
|
||||
/// </summary>
|
||||
public bool IsChecked => this.Selected;
|
||||
|
||||
public CheckBox SetCheck(bool value = true, int msPreAction = 500, int msPostAction = 500)
|
||||
{
|
||||
if (this.IsChecked != value)
|
||||
{
|
||||
if (msPreAction > 0)
|
||||
{
|
||||
Task.Delay(msPreAction).Wait();
|
||||
}
|
||||
|
||||
// Toggle the switch
|
||||
this.Click();
|
||||
if (msPostAction > 0)
|
||||
{
|
||||
Task.Delay(msPostAction).Wait();
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
28
src/common/UITestAutomation/Element/ComboBox.cs
Normal file
28
src/common/UITestAutomation/Element/ComboBox.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
public class ComboBox : Element
|
||||
{
|
||||
private static readonly string ExpectedControlType = "ControlType.ComboBox";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ComboBox"/> class.
|
||||
/// </summary>
|
||||
public ComboBox()
|
||||
{
|
||||
this.TargetControlType = ComboBox.ExpectedControlType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Select the item of the ComboBox.
|
||||
/// </summary>
|
||||
/// <param name="value">The text to select from the list view.</param>
|
||||
public void Select(string value)
|
||||
{
|
||||
this.Find<NavigationViewItem>(value).Click();
|
||||
}
|
||||
}
|
||||
}
|
||||
74
src/common/UITestAutomation/Element/Custom.cs
Normal file
74
src/common/UITestAutomation/Element/Custom.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
public class Custom : Element
|
||||
{
|
||||
private static readonly string ExpectedControlType = "ControlType.Custom";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Custom"/> class.
|
||||
/// </summary>
|
||||
public Custom()
|
||||
{
|
||||
this.TargetControlType = Custom.ExpectedControlType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a combination of keys.
|
||||
/// </summary>
|
||||
/// <param name="keys">The keys to send.</param>
|
||||
public void SendKeys(params Key[] keys)
|
||||
{
|
||||
PerformAction((actions, windowElement) =>
|
||||
{
|
||||
KeyboardHelper.SendKeys(keys);
|
||||
});
|
||||
}
|
||||
|
||||
/// <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();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,14 @@
|
||||
// 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.PowerToys.UITest;
|
||||
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;
|
||||
@@ -16,12 +22,32 @@ namespace Microsoft.PowerToys.UITest
|
||||
/// <summary>
|
||||
/// Represents a basic UI element in the application.
|
||||
/// </summary>
|
||||
public abstract class Element
|
||||
public class Element
|
||||
{
|
||||
private WindowsElement? windowsElement;
|
||||
|
||||
protected internal WindowsElement? WindowsElement
|
||||
{
|
||||
get => windowsElement;
|
||||
set => windowsElement = value;
|
||||
}
|
||||
|
||||
private WindowsDriver<WindowsElement>? driver;
|
||||
|
||||
protected internal WindowsDriver<WindowsElement>? Driver
|
||||
{
|
||||
get => driver;
|
||||
set => driver = value;
|
||||
}
|
||||
|
||||
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 +81,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,9 +125,10 @@ 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, int msPreAction = 500, int msPostAction = 500)
|
||||
{
|
||||
PerformAction((actions, windowElement) =>
|
||||
PerformAction(
|
||||
(actions, windowElement) =>
|
||||
{
|
||||
actions.MoveToElement(windowElement);
|
||||
|
||||
@@ -110,13 +145,15 @@ namespace Microsoft.PowerToys.UITest
|
||||
}
|
||||
|
||||
actions.Build().Perform();
|
||||
});
|
||||
},
|
||||
msPreAction,
|
||||
msPostAction);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Double Click the UI element.
|
||||
/// </summary>
|
||||
public void DoubleClick()
|
||||
public virtual void DoubleClick()
|
||||
{
|
||||
PerformAction((actions, windowElement) =>
|
||||
{
|
||||
@@ -130,6 +167,23 @@ namespace Microsoft.PowerToys.UITest
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Release action
|
||||
/// </summary>
|
||||
public void ReleaseAction()
|
||||
{
|
||||
var releaseAction = new Actions(driver);
|
||||
releaseAction.Release().Perform();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Release key
|
||||
/// </summary>
|
||||
public void ReleaseKey(Key key)
|
||||
{
|
||||
KeyboardHelper.ReleaseKey(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the attribute value of the UI element.
|
||||
/// </summary>
|
||||
@@ -139,7 +193,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;
|
||||
}
|
||||
|
||||
@@ -150,21 +203,55 @@ namespace Microsoft.PowerToys.UITest
|
||||
/// <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 T Find<T>(By by, int timeoutMS = 3000)
|
||||
public T Find<T>(By by, int timeoutMS = 5000)
|
||||
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, $"UI-Element({typeof(T).Name}) 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 = 5000)
|
||||
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 = 5000)
|
||||
{
|
||||
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 = 5000)
|
||||
{
|
||||
return this.Find<Element>(By.Name(name), timeoutMS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -174,30 +261,87 @@ 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 = 5000)
|
||||
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 = 5000)
|
||||
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 = 5000)
|
||||
{
|
||||
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 = 5000)
|
||||
{
|
||||
return this.FindAll<Element>(By.Name(name), timeoutMS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send Key of the element.
|
||||
/// </summary>
|
||||
/// <param name="key">The Key to Send.</param>
|
||||
protected void SendKeys(string key)
|
||||
{
|
||||
PerformAction((actions, windowElement) =>
|
||||
{
|
||||
windowElement.SendKeys(key);
|
||||
});
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
@@ -213,5 +357,15 @@ namespace Microsoft.PowerToys.UITest
|
||||
Task.Delay(msPostAction).Wait();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save UI Element to a PNG file.
|
||||
/// </summary>
|
||||
/// <param name="path">the full path</param>
|
||||
internal void SaveToPngFile(string path)
|
||||
{
|
||||
Assert.IsNotNull(this.windowsElement, $"WindowsElement is null in method SaveToFile with parameter: path = {path}");
|
||||
this.windowsElement.GetScreenshot().SaveAsFile(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
25
src/common/UITestAutomation/Element/Group.cs
Normal file
25
src/common/UITestAutomation/Element/Group.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
public class Group : Element
|
||||
{
|
||||
private static readonly string ExpectedControlType = "ControlType.Group";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Group"/> class.
|
||||
/// </summary>
|
||||
public Group()
|
||||
{
|
||||
this.TargetControlType = Group.ExpectedControlType;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
91
src/common/UITestAutomation/Element/NavigationViewItem.cs
Normal file
91
src/common/UITestAutomation/Element/NavigationViewItem.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
// 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>
|
||||
/// <param name="msPreAction">Pre action delay in milliseconds. Default value is 500</param>
|
||||
/// <param name="msPostAction">Post action delay in milliseconds. Default value is 500</param>
|
||||
public override void Click(bool rightClick = false, int msPreAction = 500, int msPostAction = 500)
|
||||
{
|
||||
PerformAction(
|
||||
(actions, windowElement) =>
|
||||
{
|
||||
actions.MoveToElement(windowElement, 10, 10);
|
||||
|
||||
if (rightClick)
|
||||
{
|
||||
actions.ContextClick();
|
||||
}
|
||||
else
|
||||
{
|
||||
actions.Click();
|
||||
}
|
||||
|
||||
actions.Build().Perform();
|
||||
},
|
||||
msPreAction,
|
||||
msPostAction);
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// <param name="msPreAction">Pre action delay in milliseconds. Default value is 500</param>
|
||||
/// <param name="msPostAction">Post action delay in milliseconds. Default value is 500</param>
|
||||
public void ClickCenter(bool rightClick = false, int msPreAction = 500, int msPostAction = 500)
|
||||
{
|
||||
PerformAction(
|
||||
(actions, windowElement) =>
|
||||
{
|
||||
actions.MoveToElement(windowElement);
|
||||
if (rightClick)
|
||||
{
|
||||
actions.ContextClick();
|
||||
}
|
||||
else
|
||||
{
|
||||
actions.Click();
|
||||
}
|
||||
|
||||
actions.Build().Perform();
|
||||
},
|
||||
msPreAction,
|
||||
msPostAction);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Double Click the ListItem element.
|
||||
/// </summary>
|
||||
public override void DoubleClick()
|
||||
{
|
||||
PerformAction((actions, windowElement) =>
|
||||
{
|
||||
actions.MoveToElement(windowElement, 10, 10);
|
||||
actions.DoubleClick();
|
||||
actions.Build().Perform();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
101
src/common/UITestAutomation/Element/Pane.cs
Normal file
101
src/common/UITestAutomation/Element/Pane.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
using OpenQA.Selenium.Interactions;
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
public class Pane : Element
|
||||
{
|
||||
private static readonly string ExpectedControlType = "ControlType.Pane";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Pane"/> class.
|
||||
/// </summary>
|
||||
public Pane()
|
||||
{
|
||||
this.TargetControlType = Pane.ExpectedControlType;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// Simulates holding when dragging to target position.
|
||||
/// </summary>
|
||||
/// <param name="offsetX">The offsetX to move.</param>
|
||||
/// <param name="offsetY">The offsetY to move.</param>
|
||||
public void DragAndHold(int offsetX, int offsetY)
|
||||
{
|
||||
PerformAction((actions, windowElement) =>
|
||||
{
|
||||
actions.MoveToElement(windowElement).MoveByOffset(10, 10).ClickAndHold(windowElement).MoveByOffset(offsetX, offsetY);
|
||||
actions.Build().Perform();
|
||||
});
|
||||
}
|
||||
|
||||
public void ReleaseDrag()
|
||||
{
|
||||
var releaseAction = new Actions(this.Driver);
|
||||
releaseAction.Release().Perform();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulates holding a key, clicking and dragging a UI element to the specified screen coordinates.
|
||||
/// </summary>
|
||||
/// <param name="key">The keyboard key to press and hold during the drag operation.</param>
|
||||
/// <param name="targetX">The target X-coordinate to drag the element to.</param>
|
||||
/// <param name="targetY">The target Y-coordinate to drag the element to.</param>
|
||||
public void KeyDownAndDrag(Key key, int targetX, int targetY)
|
||||
{
|
||||
HoldShiftToDrag(key, targetX, targetY);
|
||||
ReleaseAction();
|
||||
ReleaseKey(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulates holding a key, clicking and dragging a UI element to the specified screen coordinates.
|
||||
/// </summary>
|
||||
/// <param name="key">The keyboard key to press and hold during the drag operation.</param>
|
||||
/// <param name="targetX">The target X-coordinate to drag the element to.</param>
|
||||
/// <param name="targetY">The target Y-coordinate to drag the element to.</param>
|
||||
public void HoldShiftToDrag(Key key, int targetX, int targetY)
|
||||
{
|
||||
PerformAction((actions, windowElement) =>
|
||||
{
|
||||
KeyboardHelper.PressKey(key);
|
||||
|
||||
actions.MoveToElement(WindowsElement)
|
||||
.ClickAndHold()
|
||||
.Perform();
|
||||
|
||||
int dx = targetX - windowElement.Rect.X;
|
||||
int dy = targetY - windowElement.Rect.Y;
|
||||
|
||||
int stepCount = 10;
|
||||
int stepX = dx / stepCount;
|
||||
int stepY = dy / stepCount;
|
||||
|
||||
for (int i = 0; i < stepCount; i++)
|
||||
{
|
||||
var stepAction = new Actions(Driver);
|
||||
stepAction.MoveByOffset(stepX, stepY).Perform();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
131
src/common/UITestAutomation/Element/Slider.cs
Normal file
131
src/common/UITestAutomation/Element/Slider.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
public class Slider : Element
|
||||
{
|
||||
private static readonly string ExpectedControlType = "ControlType.Slider";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Slider"/> class.
|
||||
/// </summary>
|
||||
public Slider()
|
||||
{
|
||||
this.TargetControlType = Slider.ExpectedControlType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of a Slider (WindowsElement)
|
||||
/// </summary>
|
||||
/// <returns>The integer value of the slider</returns>
|
||||
public int GetValue()
|
||||
{
|
||||
return this.Text == string.Empty ? 0 : int.Parse(this.Text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a combination of keys.
|
||||
/// </summary>
|
||||
/// <param name="keys">The keys to send.</param>
|
||||
public void SendKeys(params Key[] keys)
|
||||
{
|
||||
PerformAction((actions, windowElement) =>
|
||||
{
|
||||
KeyboardHelper.SendKeys(keys);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of a Slider (WindowsElement) to the specified integer value.
|
||||
/// Throws an exception if the value is out of the slider's valid range.
|
||||
/// </summary>
|
||||
/// <param name="targetValue">The target integer value to set</param>
|
||||
public void SetValue(int targetValue)
|
||||
{
|
||||
// Read range and current value
|
||||
int min = int.Parse(this.GetAttribute("RangeValue.Minimum"));
|
||||
int max = int.Parse(this.GetAttribute("RangeValue.Maximum"));
|
||||
int current = int.Parse(this.Text);
|
||||
|
||||
// Use Assert to check if the target value is within the valid range
|
||||
Assert.IsTrue(
|
||||
targetValue >= min && targetValue <= max,
|
||||
$"Target value {targetValue} is out of range (min: {min}, max: {max}).");
|
||||
|
||||
// Compute difference
|
||||
int diff = targetValue - current;
|
||||
if (diff == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string key = diff > 0 ? OpenQA.Selenium.Keys.Right : OpenQA.Selenium.Keys.Left;
|
||||
int steps = Math.Abs(diff);
|
||||
|
||||
for (int i = 0; i < steps; i++)
|
||||
{
|
||||
this.SendKeys(key);
|
||||
|
||||
// Thread.Sleep(2);
|
||||
}
|
||||
|
||||
// Final check
|
||||
int finalValue = int.Parse(this.Text);
|
||||
Assert.AreEqual(
|
||||
targetValue, finalValue, $"Slider value mismatch: expected {targetValue}, but got {finalValue}.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of a Slider (WindowsElement) to the specified integer value.
|
||||
/// Throws an exception if the value is out of the slider's valid range.
|
||||
/// </summary>
|
||||
/// <param name="targetValue">The target integer value to set</param>
|
||||
public void QuickSetValue(int targetValue)
|
||||
{
|
||||
// Read range and current value
|
||||
int min = int.Parse(this.GetAttribute("RangeValue.Minimum"));
|
||||
int max = int.Parse(this.GetAttribute("RangeValue.Maximum"));
|
||||
int current = int.Parse(this.Text);
|
||||
|
||||
// Use Assert to check if the target value is within the valid range
|
||||
Assert.IsTrue(
|
||||
targetValue >= min && targetValue <= max,
|
||||
$"Target value {targetValue} is out of range (min: {min}, max: {max}).");
|
||||
|
||||
// Compute difference
|
||||
int diff = targetValue - current;
|
||||
if (diff == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string key = diff > 0 ? OpenQA.Selenium.Keys.Right : OpenQA.Selenium.Keys.Left;
|
||||
int steps = Math.Abs(diff);
|
||||
|
||||
int maxKeysPerSend = 50;
|
||||
int fullChunks = steps / maxKeysPerSend;
|
||||
int remainder = steps % maxKeysPerSend;
|
||||
for (int i = 0; i < fullChunks; i++)
|
||||
{
|
||||
SendKeys(new string(key[0], maxKeysPerSend));
|
||||
Thread.Sleep(2);
|
||||
}
|
||||
|
||||
if (remainder > 0)
|
||||
{
|
||||
SendKeys(new string(key[0], remainder));
|
||||
Thread.Sleep(2);
|
||||
}
|
||||
|
||||
// Final check
|
||||
int finalValue = int.Parse(this.Text);
|
||||
Assert.AreEqual(
|
||||
targetValue, finalValue, $"Slider value mismatch: expected {targetValue}, but got {finalValue}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
67
src/common/UITestAutomation/Element/Tab.cs
Normal file
67
src/common/UITestAutomation/Element/Tab.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
using OpenQA.Selenium.Interactions;
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
public class Tab : Element
|
||||
{
|
||||
private static readonly string ExpectedControlType = "ControlType.Tab";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Tab"/> class.
|
||||
/// </summary>
|
||||
public Tab()
|
||||
{
|
||||
this.TargetControlType = Tab.ExpectedControlType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulates holding a key, clicking and dragging a UI element to the specified screen coordinates.
|
||||
/// </summary>
|
||||
/// <param name="key">The keyboard key to press and hold during the drag operation.</param>
|
||||
/// <param name="targetX">The target X-coordinate to drag the element to.</param>
|
||||
/// <param name="targetY">The target Y-coordinate to drag the element to.</param>
|
||||
public void KeyDownAndDrag(Key key, int targetX, int targetY)
|
||||
{
|
||||
HoldShiftToDrag(key, targetX, targetY);
|
||||
ReleaseAction();
|
||||
ReleaseKey(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulates holding a key, clicking and dragging a UI element to the specified screen coordinates.
|
||||
/// </summary>
|
||||
/// <param name="key">The keyboard key to press and hold during the drag operation.</param>
|
||||
/// <param name="targetX">The target X-coordinate to drag the element to.</param>
|
||||
/// <param name="targetY">The target Y-coordinate to drag the element to.</param>
|
||||
public void HoldShiftToDrag(Key key, int targetX, int targetY)
|
||||
{
|
||||
PerformAction((actions, windowElement) =>
|
||||
{
|
||||
KeyboardHelper.PressKey(key);
|
||||
|
||||
actions.MoveToElement(WindowsElement)
|
||||
.ClickAndHold()
|
||||
.Perform();
|
||||
|
||||
int dx = targetX - windowElement.Rect.X;
|
||||
int dy = targetY - windowElement.Rect.Y;
|
||||
|
||||
int stepCount = 10;
|
||||
int stepX = dx / stepCount;
|
||||
int stepY = dy / stepCount;
|
||||
|
||||
for (int i = 0; i < stepCount; i++)
|
||||
{
|
||||
var stepAction = new Actions(Driver);
|
||||
stepAction.MoveByOffset(stepX, stepY).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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,15 +2,24 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
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>
|
||||
@@ -24,9 +33,10 @@ namespace Microsoft.PowerToys.UITest
|
||||
PerformAction((actions, windowElement) =>
|
||||
{
|
||||
// select all text and delete it
|
||||
windowElement.SendKeys(Keys.Control + "a");
|
||||
windowElement.SendKeys(Keys.Delete);
|
||||
windowElement.SendKeys(OpenQA.Selenium.Keys.Control + "a");
|
||||
windowElement.SendKeys(OpenQA.Selenium.Keys.Delete);
|
||||
});
|
||||
Task.Delay(500).Wait();
|
||||
}
|
||||
|
||||
PerformAction((actions, windowElement) =>
|
||||
|
||||
36
src/common/UITestAutomation/Element/Thumb.cs
Normal file
36
src/common/UITestAutomation/Element/Thumb.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
public class Thumb : Element
|
||||
{
|
||||
private static readonly string ExpectedControlType = "ControlType.Thumb";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Thumb"/> class.
|
||||
/// </summary>
|
||||
public Thumb()
|
||||
{
|
||||
this.TargetControlType = Thumb.ExpectedControlType;
|
||||
}
|
||||
|
||||
/// <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();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,14 +17,7 @@ namespace Microsoft.PowerToys.UITest
|
||||
/// </summary>
|
||||
internal static class FindHelper
|
||||
{
|
||||
public static T Find<T, TW>(Func<TW> findElementFunc, WindowsDriver<WindowsElement>? driver, int timeoutMS)
|
||||
where T : Element, new()
|
||||
{
|
||||
var item = findElementFunc() as WindowsElement;
|
||||
return NewElement<T>(item, driver, timeoutMS);
|
||||
}
|
||||
|
||||
public static ReadOnlyCollection<T>? FindAll<T, TW>(Func<ReadOnlyCollection<TW>> findElementsFunc, 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 items = findElementsFunc();
|
||||
@@ -32,11 +25,45 @@ 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);
|
||||
}
|
||||
|
||||
public static ReadOnlyCollection<T>? FindAll<T, TW>(Func<ReadOnlyCollection<TW>> findElementsFunc, WindowsDriver<WindowsElement>? driver, int timeoutMS)
|
||||
where T : Element, new()
|
||||
{
|
||||
var items = FindElementsWithRetry(findElementsFunc, timeoutMS);
|
||||
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);
|
||||
}
|
||||
|
||||
private static ReadOnlyCollection<TW> FindElementsWithRetry<TW>(Func<ReadOnlyCollection<TW>> findElementsFunc, int timeoutMS)
|
||||
{
|
||||
int retryIntervalMS = 500;
|
||||
timeoutMS = 1;
|
||||
int elapsedTime = 0;
|
||||
|
||||
while (elapsedTime < timeoutMS)
|
||||
{
|
||||
var items = findElementsFunc();
|
||||
if (items.Count > 0)
|
||||
{
|
||||
return items;
|
||||
}
|
||||
|
||||
Task.Delay(retryIntervalMS).Wait();
|
||||
elapsedTime += retryIntervalMS;
|
||||
}
|
||||
|
||||
return new ReadOnlyCollection<TW>(new List<TW>());
|
||||
}
|
||||
|
||||
public static T NewElement<T>(WindowsElement? element, WindowsDriver<WindowsElement>? driver, int timeoutMS)
|
||||
where T : Element, new()
|
||||
{
|
||||
@@ -44,11 +71,6 @@ namespace Microsoft.PowerToys.UITest
|
||||
Assert.IsNotNull(element, $"New Element {typeof(T).Name} error: element is null.");
|
||||
|
||||
T newElement = new T();
|
||||
if (timeoutMS > 0)
|
||||
{
|
||||
// Only set timeout if it is positive value
|
||||
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromMilliseconds(timeoutMS);
|
||||
}
|
||||
|
||||
newElement.SetSession(driver);
|
||||
newElement.SetWindowsElement(element);
|
||||
|
||||
475
src/common/UITestAutomation/KeyboardHelper.cs
Normal file
475
src/common/UITestAutomation/KeyboardHelper.cs
Normal file
@@ -0,0 +1,475 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents keyboard keys.
|
||||
/// </summary>
|
||||
public enum Key
|
||||
{
|
||||
Ctrl,
|
||||
LCtrl,
|
||||
RCtrl,
|
||||
Alt,
|
||||
Shift,
|
||||
Tab,
|
||||
Esc,
|
||||
Enter,
|
||||
Win,
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
E,
|
||||
F,
|
||||
G,
|
||||
H,
|
||||
I,
|
||||
J,
|
||||
K,
|
||||
L,
|
||||
M,
|
||||
N,
|
||||
O,
|
||||
P,
|
||||
Q,
|
||||
R,
|
||||
S,
|
||||
T,
|
||||
U,
|
||||
V,
|
||||
W,
|
||||
X,
|
||||
Y,
|
||||
Z,
|
||||
Num0,
|
||||
Num1,
|
||||
Num2,
|
||||
Num3,
|
||||
Num4,
|
||||
Num5,
|
||||
Num6,
|
||||
Num7,
|
||||
Num8,
|
||||
Num9,
|
||||
F1,
|
||||
F2,
|
||||
F3,
|
||||
F4,
|
||||
F5,
|
||||
F6,
|
||||
F7,
|
||||
F8,
|
||||
F9,
|
||||
F10,
|
||||
F11,
|
||||
F12,
|
||||
Space,
|
||||
Backspace,
|
||||
Delete,
|
||||
Insert,
|
||||
Home,
|
||||
End,
|
||||
PageUp,
|
||||
PageDown,
|
||||
Up,
|
||||
Down,
|
||||
Left,
|
||||
Right,
|
||||
Other,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides methods for simulating keyboard input.
|
||||
/// </summary>
|
||||
internal static class KeyboardHelper
|
||||
{
|
||||
[DllImport("user32.dll")]
|
||||
#pragma warning disable SA1300 // Element should begin with upper-case letter
|
||||
private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);
|
||||
#pragma warning restore SA1300 // Element should begin with upper-case letter
|
||||
|
||||
#pragma warning disable SA1310 // Field names should not contain underscore
|
||||
private const byte VK_LWIN = 0x5B;
|
||||
private const uint KEYEVENTF_KEYDOWN = 0x0000;
|
||||
private const uint KEYEVENTF_KEYUP = 0x0002;
|
||||
#pragma warning restore SA1310 // Field names should not contain underscore
|
||||
|
||||
/// <summary>
|
||||
/// Sends a combination of keys.
|
||||
/// </summary>
|
||||
/// <param name="keys">The keys to send.</param>
|
||||
public static void SendKeys(params Key[] keys)
|
||||
{
|
||||
string keysToSend = string.Join(string.Empty, keys.Select(TranslateKey));
|
||||
SendWinKeyCombination(keysToSend);
|
||||
}
|
||||
|
||||
public static void PressKey(Key key)
|
||||
{
|
||||
PressVirtualKey(TranslateKeyHex(key));
|
||||
}
|
||||
|
||||
public static void ReleaseKey(Key key)
|
||||
{
|
||||
ReleaseVirtualKey(TranslateKeyHex(key));
|
||||
}
|
||||
|
||||
public static void SendKey(Key key)
|
||||
{
|
||||
PressVirtualKey(TranslateKeyHex(key));
|
||||
ReleaseVirtualKey(TranslateKeyHex(key));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Translates a key to its corresponding SendKeys representation.
|
||||
/// </summary>
|
||||
/// <param name="key">The key to translate.</param>
|
||||
/// <returns>The SendKeys representation of the key.</returns>
|
||||
private static string TranslateKey(Key key)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case Key.Ctrl:
|
||||
return "^";
|
||||
case Key.LCtrl:
|
||||
return "^";
|
||||
case Key.RCtrl:
|
||||
return "^";
|
||||
case Key.Alt:
|
||||
return "%";
|
||||
case Key.Shift:
|
||||
return "+";
|
||||
case Key.Tab:
|
||||
return "{TAB}";
|
||||
case Key.Esc:
|
||||
return "{ESC}";
|
||||
case Key.Enter:
|
||||
return "{ENTER}";
|
||||
case Key.Win:
|
||||
return "{WIN}";
|
||||
case Key.Space:
|
||||
return " ";
|
||||
case Key.Backspace:
|
||||
return "{BACKSPACE}";
|
||||
case Key.Delete:
|
||||
return "{DELETE}";
|
||||
case Key.Insert:
|
||||
return "{INSERT}";
|
||||
case Key.Home:
|
||||
return "{HOME}";
|
||||
case Key.End:
|
||||
return "{END}";
|
||||
case Key.PageUp:
|
||||
return "{PGUP}";
|
||||
case Key.PageDown:
|
||||
return "{PGDN}";
|
||||
case Key.Up:
|
||||
return "{UP}";
|
||||
case Key.Down:
|
||||
return "{DOWN}";
|
||||
case Key.Left:
|
||||
return "{LEFT}";
|
||||
case Key.Right:
|
||||
return "{RIGHT}";
|
||||
case Key.F1:
|
||||
return "{F1}";
|
||||
case Key.F2:
|
||||
return "{F2}";
|
||||
case Key.F3:
|
||||
return "{F3}";
|
||||
case Key.F4:
|
||||
return "{F4}";
|
||||
case Key.F5:
|
||||
return "{F5}";
|
||||
case Key.F6:
|
||||
return "{F6}";
|
||||
case Key.F7:
|
||||
return "{F7}";
|
||||
case Key.F8:
|
||||
return "{F8}";
|
||||
case Key.F9:
|
||||
return "{F9}";
|
||||
case Key.F10:
|
||||
return "{F10}";
|
||||
case Key.F11:
|
||||
return "{F11}";
|
||||
case Key.F12:
|
||||
return "{F12}";
|
||||
case Key.A:
|
||||
return "a";
|
||||
case Key.B:
|
||||
return "b";
|
||||
case Key.C:
|
||||
return "c";
|
||||
case Key.D:
|
||||
return "d";
|
||||
case Key.E:
|
||||
return "e";
|
||||
case Key.F:
|
||||
return "f";
|
||||
case Key.G:
|
||||
return "g";
|
||||
case Key.H:
|
||||
return "h";
|
||||
case Key.I:
|
||||
return "i";
|
||||
case Key.J:
|
||||
return "j";
|
||||
case Key.K:
|
||||
return "k";
|
||||
case Key.L:
|
||||
return "l";
|
||||
case Key.M:
|
||||
return "m";
|
||||
case Key.N:
|
||||
return "n";
|
||||
case Key.O:
|
||||
return "o";
|
||||
case Key.P:
|
||||
return "p";
|
||||
case Key.Q:
|
||||
return "q";
|
||||
case Key.R:
|
||||
return "r";
|
||||
case Key.S:
|
||||
return "s";
|
||||
case Key.T:
|
||||
return "t";
|
||||
case Key.U:
|
||||
return "u";
|
||||
case Key.V:
|
||||
return "v";
|
||||
case Key.W:
|
||||
return "w";
|
||||
case Key.X:
|
||||
return "x";
|
||||
case Key.Y:
|
||||
return "y";
|
||||
case Key.Z:
|
||||
return "z";
|
||||
case Key.Num0:
|
||||
return "0";
|
||||
case Key.Num1:
|
||||
return "1";
|
||||
case Key.Num2:
|
||||
return "2";
|
||||
case Key.Num3:
|
||||
return "3";
|
||||
case Key.Num4:
|
||||
return "4";
|
||||
case Key.Num5:
|
||||
return "5";
|
||||
case Key.Num6:
|
||||
return "6";
|
||||
case Key.Num7:
|
||||
return "7";
|
||||
case Key.Num8:
|
||||
return "8";
|
||||
case Key.Num9:
|
||||
return "9";
|
||||
default:
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// map the virtual key codes to the corresponding keys.
|
||||
/// </summary>
|
||||
private static byte TranslateKeyHex(Key key)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case Key.Win:
|
||||
return 0x5B; // Windows Key - 0x5B in hex
|
||||
case Key.Ctrl:
|
||||
return 0x11; // Ctrl Key - 0x11 in hex
|
||||
case Key.Alt:
|
||||
return 0x12; // Alt Key - 0x12 in hex
|
||||
case Key.Shift:
|
||||
return 0x10; // Shift Key - 0x10 in hex
|
||||
case Key.LCtrl:
|
||||
return 0xA2; // Left Ctrl Key - 0xA2 in hex
|
||||
case Key.RCtrl:
|
||||
return 0xA3; // Right Ctrl Key - 0xA3 in hex
|
||||
case Key.A:
|
||||
return 0x41; // A Key - 0x41 in hex
|
||||
case Key.B:
|
||||
return 0x42; // B Key - 0x42 in hex
|
||||
case Key.C:
|
||||
return 0x43; // C Key - 0x43 in hex
|
||||
case Key.D:
|
||||
return 0x44; // D Key - 0x44 in hex
|
||||
case Key.E:
|
||||
return 0x45; // E Key - 0x45 in hex
|
||||
case Key.F:
|
||||
return 0x46; // F Key - 0x46 in hex
|
||||
case Key.G:
|
||||
return 0x47; // G Key - 0x47 in hex
|
||||
case Key.H:
|
||||
return 0x48; // H Key - 0x48 in hex
|
||||
case Key.I:
|
||||
return 0x49; // I Key - 0x49 in hex
|
||||
case Key.J:
|
||||
return 0x4A; // J Key - 0x4A in hex
|
||||
case Key.K:
|
||||
return 0x4B; // K Key - 0x4B in hex
|
||||
case Key.L:
|
||||
return 0x4C; // L Key - 0x4C in hex
|
||||
case Key.M:
|
||||
return 0x4D; // M Key - 0x4D in hex
|
||||
case Key.N:
|
||||
return 0x4E; // N Key - 0x4E in hex
|
||||
case Key.O:
|
||||
return 0x4F; // O Key - 0x4F in hex
|
||||
case Key.P:
|
||||
return 0x50; // P Key - 0x50 in hex
|
||||
case Key.Q:
|
||||
return 0x51; // Q Key - 0x51 in hex
|
||||
case Key.R:
|
||||
return 0x52; // R Key - 0x52 in hex
|
||||
case Key.S:
|
||||
return 0x53; // S Key - 0x53 in hex
|
||||
case Key.T:
|
||||
return 0x54; // T Key - 0x54 in hex
|
||||
case Key.U:
|
||||
return 0x55; // U Key - 0x55 in hex
|
||||
case Key.V:
|
||||
return 0x56; // V Key - 0x56 in hex
|
||||
case Key.W:
|
||||
return 0x57; // W Key - 0x57 in hex
|
||||
case Key.X:
|
||||
return 0x58; // X Key - 0x58 in hex
|
||||
case Key.Y:
|
||||
return 0x59; // Y Key - 0x59 in hex
|
||||
case Key.Z:
|
||||
return 0x5A; // Z Key - 0x5A in hex
|
||||
case Key.Num0:
|
||||
return 0x30; // 0 Key - 0x30 in hex
|
||||
case Key.Num1:
|
||||
return 0x31; // 1 Key - 0x31 in hex
|
||||
case Key.Num2:
|
||||
return 0x32; // 2 Key - 0x32 in hex
|
||||
case Key.Num3:
|
||||
return 0x33; // 3 Key - 0x33 in hex
|
||||
case Key.Num4:
|
||||
return 0x34; // 4 Key - 0x34 in hex
|
||||
case Key.Num5:
|
||||
return 0x35; // 5 Key - 0x35 in hex
|
||||
case Key.Num6:
|
||||
return 0x36; // 6 Key - 0x36 in hex
|
||||
case Key.Num7:
|
||||
return 0x37; // 7 Key - 0x37 in hex
|
||||
case Key.Num8:
|
||||
return 0x38; // 8 Key - 0x38 in hex
|
||||
case Key.Num9:
|
||||
return 0x39; // 9 Key - 0x39 in hex
|
||||
case Key.F1:
|
||||
return 0x70; // F1 Key - 0x70 in hex
|
||||
case Key.F2:
|
||||
return 0x71; // F2 Key - 0x71 in hex
|
||||
case Key.F3:
|
||||
return 0x72; // F3 Key - 0x72 in hex
|
||||
case Key.F4:
|
||||
return 0x73; // F4 Key - 0x73 in hex
|
||||
case Key.F5:
|
||||
return 0x74; // F5 Key - 0x74 in hex
|
||||
case Key.F6:
|
||||
return 0x75; // F6 Key - 0x75 in hex
|
||||
case Key.F7:
|
||||
return 0x76; // F7 Key - 0x76 in hex
|
||||
case Key.F8:
|
||||
return 0x77; // F8 Key - 0x77 in hex
|
||||
case Key.F9:
|
||||
return 0x78; // F9 Key - 0x78 in hex
|
||||
case Key.F10:
|
||||
return 0x79; // F10 Key - 0x79 in hex
|
||||
case Key.F11:
|
||||
return 0x7A; // F11 Key - 0x7A in hex
|
||||
case Key.F12:
|
||||
return 0x7B; // F12 Key - 0x7B in hex
|
||||
case Key.Up:
|
||||
return 0x26; // Up Arrow Key - 0x26 in hex
|
||||
case Key.Down:
|
||||
return 0x28; // Down Arrow Key - 0x28 in hex
|
||||
case Key.Left:
|
||||
return 0x25; // Left Arrow Key - 0x25 in hex
|
||||
case Key.Right:
|
||||
return 0x27; // Right Arrow Key - 0x27 in hex
|
||||
case Key.Home:
|
||||
return 0x24; // Home Key - 0x24 in hex
|
||||
case Key.End:
|
||||
return 0x23; // End Key - 0x23 in hex
|
||||
case Key.PageUp:
|
||||
return 0x21; // Page Up Key - 0x21 in hex
|
||||
case Key.PageDown:
|
||||
return 0x22; // Page Down Key - 0x22 in hex
|
||||
case Key.Space:
|
||||
return 0x20; // Space Key - 0x20 in hex
|
||||
case Key.Enter:
|
||||
return 0x0D; // Enter Key - 0x0D in hex
|
||||
case Key.Backspace:
|
||||
return 0x08; // Backspace Key - 0x08 in hex
|
||||
case Key.Tab:
|
||||
return 0x09; // Tab Key - 0x09 in hex
|
||||
case Key.Esc:
|
||||
return 0x1B; // Escape Key - 0x1B in hex
|
||||
case Key.Insert:
|
||||
return 0x2D; // Insert Key - 0x2D in hex
|
||||
case Key.Delete:
|
||||
return 0x2E; // Delete Key - 0x2E in hex
|
||||
default:
|
||||
throw new ArgumentException($"Key {key} is not supported, Please add your key at TranslateKeyHex for translation to hex.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a combination of keys, including the Windows key, to the system.
|
||||
/// </summary>
|
||||
/// <param name="keys">The keys to send.</param>
|
||||
private static void SendWinKeyCombination(string keys)
|
||||
{
|
||||
bool winKeyDown = false;
|
||||
|
||||
if (keys.Contains("{WIN}"))
|
||||
{
|
||||
keybd_event(VK_LWIN, 0, KEYEVENTF_KEYDOWN, UIntPtr.Zero);
|
||||
winKeyDown = true;
|
||||
keys = keys.Replace("{WIN}", string.Empty); // Remove {WIN} from the string
|
||||
}
|
||||
|
||||
System.Windows.Forms.SendKeys.SendWait(keys);
|
||||
|
||||
// Release Windows key
|
||||
if (winKeyDown)
|
||||
{
|
||||
keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, UIntPtr.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Just press the key.(no release)
|
||||
/// </summary>
|
||||
private static void PressVirtualKey(byte key)
|
||||
{
|
||||
keybd_event(key, 0, KEYEVENTF_KEYDOWN, UIntPtr.Zero);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Release only the button (if pressed first)
|
||||
/// </summary>
|
||||
private static void ReleaseVirtualKey(byte key)
|
||||
{
|
||||
keybd_event(key, 0, KEYEVENTF_KEYUP, UIntPtr.Zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,49 @@ namespace Microsoft.PowerToys.UITest
|
||||
PowerToysSettings,
|
||||
FancyZone,
|
||||
Hosts,
|
||||
Runner,
|
||||
Workspaces,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the window size for the UI test.
|
||||
/// </summary>
|
||||
public enum WindowSize
|
||||
{
|
||||
/// <summary>
|
||||
/// Unspecified window size, won't make any size change
|
||||
/// </summary>
|
||||
UnSpecified,
|
||||
|
||||
/// <summary>
|
||||
/// Small window size, 640 * 480
|
||||
/// </summary>
|
||||
Small,
|
||||
|
||||
/// <summary>
|
||||
/// Small window size, 480 * 640
|
||||
/// </summary>
|
||||
Small_Vertical,
|
||||
|
||||
/// <summary>
|
||||
/// Medium window size, 1024 * 768
|
||||
/// </summary>
|
||||
Medium,
|
||||
|
||||
/// <summary>
|
||||
/// Medium window size, 768 * 1024
|
||||
/// </summary>
|
||||
Medium_Vertical,
|
||||
|
||||
/// <summary>
|
||||
/// Large window size, 1920 * 1080
|
||||
/// </summary>
|
||||
Large,
|
||||
|
||||
/// <summary>
|
||||
/// Large window size, 1080 * 1920
|
||||
/// </summary>
|
||||
Large_Vertical,
|
||||
}
|
||||
|
||||
internal class ModuleConfigData
|
||||
@@ -52,6 +95,8 @@ namespace Microsoft.PowerToys.UITest
|
||||
[PowerToysModule.PowerToysSettings] = "PowerToys Settings",
|
||||
[PowerToysModule.FancyZone] = "FancyZones Layout",
|
||||
[PowerToysModule.Hosts] = "Hosts File Editor",
|
||||
[PowerToysModule.Runner] = "PowerToys",
|
||||
[PowerToysModule.Workspaces] = "Workspaces Editor",
|
||||
};
|
||||
|
||||
// Exe start path for the module if it exists.
|
||||
@@ -60,6 +105,8 @@ namespace Microsoft.PowerToys.UITest
|
||||
[PowerToysModule.PowerToysSettings] = @"\..\..\..\WinUI3Apps\PowerToys.Settings.exe",
|
||||
[PowerToysModule.FancyZone] = @"\..\..\..\PowerToys.FancyZonesEditor.exe",
|
||||
[PowerToysModule.Hosts] = @"\..\..\..\WinUI3Apps\PowerToys.Hosts.exe",
|
||||
[PowerToysModule.Runner] = @"\..\..\..\PowerToys.exe",
|
||||
[PowerToysModule.Workspaces] = @"\..\..\..\PowerToys.WorkspacesEditor.exe",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
37
src/common/UITestAutomation/MonitorInfoData.cs
Normal file
37
src/common/UITestAutomation/MonitorInfoData.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
public class MonitorInfoData
|
||||
{
|
||||
public MonitorInfoData()
|
||||
{
|
||||
}
|
||||
|
||||
public struct MonitorInfoDataWrapper
|
||||
{
|
||||
public string DeviceName { get; set; }
|
||||
|
||||
public string DeviceString { get; set; }
|
||||
|
||||
public string DeviceID { get; set; }
|
||||
|
||||
public string DeviceKey { get; set; }
|
||||
|
||||
public int PelsWidth { get; set; }
|
||||
|
||||
public int PelsHeight { get; set; }
|
||||
|
||||
public int DisplayFrequency { get; set; }
|
||||
}
|
||||
|
||||
public struct ParamsWrapper
|
||||
{
|
||||
public List<MonitorInfoDataWrapper> Monitors { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
217
src/common/UITestAutomation/MouseHelper.cs
Normal file
217
src/common/UITestAutomation/MouseHelper.cs
Normal file
@@ -0,0 +1,217 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
public enum MouseActionType
|
||||
{
|
||||
LeftClick,
|
||||
RightClick,
|
||||
MiddleClick,
|
||||
LeftDoubleClick,
|
||||
RightDoubleClick,
|
||||
LeftDown,
|
||||
LeftUp,
|
||||
RightDown,
|
||||
RightUp,
|
||||
MiddleDown,
|
||||
MiddleUp,
|
||||
ScrollUp,
|
||||
ScrollDown,
|
||||
}
|
||||
|
||||
internal static class MouseHelper
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct POINT
|
||||
{
|
||||
public int X;
|
||||
public int Y;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum MouseEvent
|
||||
{
|
||||
LeftDown = 0x0002,
|
||||
LeftUp = 0x0004,
|
||||
RightDown = 0x0008,
|
||||
RightUp = 0x0010,
|
||||
MiddleDown = 0x0020,
|
||||
MiddleUp = 0x0040,
|
||||
Wheel = 0x0800,
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool GetCursorPos(out POINT lpPoint);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool SetCursorPos(int x, int y);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
#pragma warning disable SA1300 // Element should begin with upper-case letter
|
||||
private static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, UIntPtr dwExtraInfo);
|
||||
#pragma warning restore SA1300 // Element should begin with upper-case letter
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current position of the mouse cursor as a tuple.
|
||||
/// </summary>
|
||||
/// <returns>A tuple containing the X and Y coordinates of the cursor.</returns>
|
||||
public static Tuple<int, int> GetMousePosition()
|
||||
{
|
||||
GetCursorPos(out POINT point);
|
||||
return Tuple.Create(point.X, point.Y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves the mouse cursor to the specified screen coordinates.
|
||||
/// </summary>
|
||||
/// <param name="x">The new x-coordinate of the cursor.</param>
|
||||
/// <param name="y">The new y-coordinate of the cursor.</param
|
||||
public static void MoveMouseTo(int x, int y)
|
||||
{
|
||||
SetCursorPos(x, y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The delay in milliseconds between mouse down and up events to simulate a click.
|
||||
/// </summary>
|
||||
private const int ClickDelay = 100;
|
||||
|
||||
/// <summary>
|
||||
/// The amount of scroll units to simulate a single mouse wheel tick.
|
||||
/// </summary>
|
||||
private const int ScrollAmount = 120;
|
||||
|
||||
/// <summary>
|
||||
/// Simulates a left mouse click (press and release).
|
||||
/// </summary>
|
||||
public static void LeftClick()
|
||||
{
|
||||
LeftDown();
|
||||
Thread.Sleep(ClickDelay);
|
||||
LeftUp();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulates a right mouse click (press and release).
|
||||
/// </summary>
|
||||
public static void RightClick()
|
||||
{
|
||||
RightDown();
|
||||
Thread.Sleep(ClickDelay);
|
||||
RightUp();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulates a middle mouse click (press and release).
|
||||
/// </summary>
|
||||
public static void MiddleClick()
|
||||
{
|
||||
MiddleDown();
|
||||
Thread.Sleep(ClickDelay);
|
||||
MiddleUp();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulates a left mouse double-click.
|
||||
/// </summary>
|
||||
public static void LeftDoubleClick()
|
||||
{
|
||||
LeftClick();
|
||||
Thread.Sleep(ClickDelay);
|
||||
LeftClick();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulates a right mouse double-click.
|
||||
/// </summary>
|
||||
public static void RightDoubleClick()
|
||||
{
|
||||
RightClick();
|
||||
Thread.Sleep(ClickDelay);
|
||||
RightClick();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulates pressing the left mouse button down.
|
||||
/// </summary>
|
||||
public static void LeftDown()
|
||||
{
|
||||
mouse_event((uint)MouseEvent.LeftDown, 0, 0, 0, UIntPtr.Zero);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulates pressing the right mouse button down.
|
||||
/// </summary>
|
||||
public static void RightDown()
|
||||
{
|
||||
mouse_event((uint)MouseEvent.RightDown, 0, 0, 0, UIntPtr.Zero);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulates pressing the middle mouse button down.
|
||||
/// </summary>
|
||||
public static void MiddleDown()
|
||||
{
|
||||
mouse_event((uint)MouseEvent.MiddleDown, 0, 0, 0, UIntPtr.Zero);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulates releasing the left mouse button.
|
||||
/// </summary>
|
||||
public static void LeftUp()
|
||||
{
|
||||
mouse_event((uint)MouseEvent.LeftUp, 0, 0, 0, UIntPtr.Zero);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulates releasing the right mouse button.
|
||||
/// </summary>
|
||||
public static void RightUp()
|
||||
{
|
||||
mouse_event((uint)MouseEvent.RightUp, 0, 0, 0, UIntPtr.Zero);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulates releasing the middle mouse button.
|
||||
/// </summary>
|
||||
public static void MiddleUp()
|
||||
{
|
||||
mouse_event((uint)MouseEvent.MiddleUp, 0, 0, 0, UIntPtr.Zero);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulates a mouse scroll wheel action by a specified amount.
|
||||
/// Positive values scroll up, negative values scroll down.
|
||||
/// </summary>
|
||||
/// <param name="amount">The scroll amount. Typically 120 or -120 per tick.</param>
|
||||
public static void ScrollWheel(int amount)
|
||||
{
|
||||
mouse_event((uint)MouseEvent.Wheel, 0, 0, (uint)amount, UIntPtr.Zero);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulates scrolling the mouse wheel up by one tick.
|
||||
/// </summary>
|
||||
public static void ScrollUp()
|
||||
{
|
||||
ScrollWheel(ScrollAmount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulates scrolling the mouse wheel down by one tick.
|
||||
/// </summary>
|
||||
public static void ScrollDown()
|
||||
{
|
||||
ScrollWheel(-ScrollAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
133
src/common/UITestAutomation/ScreenCapture.cs
Normal file
133
src/common/UITestAutomation/ScreenCapture.cs
Normal file
@@ -0,0 +1,133 @@
|
||||
// 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.Drawing.Imaging;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides methods for capturing the screen with the mouse cursor.
|
||||
/// </summary>
|
||||
internal static class ScreenCapture
|
||||
{
|
||||
[DllImport("user32.dll")]
|
||||
private static extern IntPtr GetDC(IntPtr hWnd);
|
||||
|
||||
[DllImport("gdi32.dll")]
|
||||
private static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool GetCursorInfo(out CURSORINFO pci);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool DrawIconEx(IntPtr hdc, int x, int y, IntPtr hIcon, int cx, int cy, int istepIfAniCur, IntPtr hbrFlickerFreeDraw, int diFlags);
|
||||
|
||||
/// <summary>
|
||||
/// Represents a point with X and Y coordinates.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct POINT
|
||||
{
|
||||
public int X;
|
||||
public int Y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains information about the cursor.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct CURSORINFO
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the size of the structure.
|
||||
/// </summary>
|
||||
public int CbSize;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the cursor state.
|
||||
/// </summary>
|
||||
public int Flags;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the handle to the cursor.
|
||||
/// </summary>
|
||||
public IntPtr HCursor;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the screen position of the cursor.
|
||||
/// </summary>
|
||||
public POINT PTScreenPos;
|
||||
}
|
||||
|
||||
private const int CURSORSHOWING = 0x00000001;
|
||||
private const int DESKTOPHORZRES = 118;
|
||||
private const int DESKTOPVERTRES = 117;
|
||||
private const int DINORMAL = 0x0003;
|
||||
|
||||
/// <summary>
|
||||
/// Captures the screen with the mouse cursor and saves it to the specified file path.
|
||||
/// </summary>
|
||||
/// <param name="filePath">The file path to save the captured image.</param>
|
||||
private static void CaptureScreenWithMouse(string filePath)
|
||||
{
|
||||
IntPtr hdc = GetDC(IntPtr.Zero);
|
||||
int screenWidth = GetDeviceCaps(hdc, DESKTOPHORZRES);
|
||||
int screenHeight = GetDeviceCaps(hdc, DESKTOPVERTRES);
|
||||
ReleaseDC(IntPtr.Zero, hdc);
|
||||
|
||||
Rectangle bounds = new Rectangle(0, 0, screenWidth, screenHeight);
|
||||
using (Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height))
|
||||
{
|
||||
using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmap))
|
||||
{
|
||||
g.CopyFromScreen(bounds.Location, Point.Empty, bounds.Size);
|
||||
|
||||
CURSORINFO cursorInfo;
|
||||
cursorInfo.CbSize = Marshal.SizeOf<CURSORINFO>();
|
||||
if (GetCursorInfo(out cursorInfo) && cursorInfo.Flags == CURSORSHOWING)
|
||||
{
|
||||
using (System.Drawing.Graphics gIcon = System.Drawing.Graphics.FromImage(bitmap))
|
||||
{
|
||||
IntPtr hdcDest = gIcon.GetHdc();
|
||||
DrawIconEx(hdcDest, cursorInfo.PTScreenPos.X, cursorInfo.PTScreenPos.Y, cursorInfo.HCursor, 0, 0, 0, IntPtr.Zero, DINORMAL);
|
||||
gIcon.ReleaseHdc(hdcDest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bitmap.Save(filePath, ImageFormat.Png);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Captures a screenshot and saves it to the specified directory.
|
||||
/// </summary>
|
||||
/// <param name="directory">The directory to save the screenshot.</param>
|
||||
private static void CaptureScreenshot(string directory)
|
||||
{
|
||||
string filePath = Path.Combine(directory, $"screenshot_{DateTime.Now:yyyyMMdd_HHmmssfff}.png");
|
||||
CaptureScreenWithMouse(filePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Timer callback method to capture a screenshot.
|
||||
/// </summary>
|
||||
/// <param name="state">The state object passed to the callback method.</param>
|
||||
public static void TimerCallback(object? state)
|
||||
{
|
||||
string directory = (string)state!;
|
||||
CaptureScreenshot(directory);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,17 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OpenQA.Selenium.Appium;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
using OpenQA.Selenium.Interactions;
|
||||
using static Microsoft.PowerToys.UITest.WindowHelper;
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
@@ -15,75 +20,449 @@ namespace Microsoft.PowerToys.UITest
|
||||
/// </summary>
|
||||
public class Session
|
||||
{
|
||||
private WindowsDriver<WindowsElement> Root { get; set; }
|
||||
public WindowsDriver<WindowsElement> Root { get; set; }
|
||||
|
||||
private WindowsDriver<WindowsElement> WindowsDriver { get; set; }
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool SetForegroundWindow(nint hWnd);
|
||||
private List<IntPtr> windowHandlers = new List<IntPtr>();
|
||||
|
||||
public Session(WindowsDriver<WindowsElement> root, WindowsDriver<WindowsElement> windowsDriver)
|
||||
private Window? MainWindow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets Main Window Handler
|
||||
/// </summary>
|
||||
public IntPtr MainWindowHandler { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets Init Scope
|
||||
/// </summary>
|
||||
public PowerToysModule InitScope { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the RunAsAdmin flag.
|
||||
/// If true, the session is running as admin.
|
||||
/// If false, the session is not running as admin.
|
||||
/// If null, no information is available.
|
||||
/// </summary>
|
||||
public bool? IsElevated { get; private set; }
|
||||
|
||||
public Session(WindowsDriver<WindowsElement> root, WindowsDriver<WindowsElement> windowsDriver, PowerToysModule scope, WindowSize size)
|
||||
{
|
||||
this.MainWindowHandler = IntPtr.Zero;
|
||||
this.Root = root;
|
||||
this.WindowsDriver = windowsDriver;
|
||||
this.InitScope = scope;
|
||||
|
||||
if (size != WindowSize.UnSpecified)
|
||||
{
|
||||
// Attach to the scope & reset MainWindowHandler
|
||||
this.Attach(scope, size);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds an element by selector.
|
||||
/// Cleans up the Session Exe.
|
||||
/// </summary>
|
||||
public void Cleanup()
|
||||
{
|
||||
windowHandlers.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds an Element or its derived class by selector.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The class of the element, should be Element or its derived class.</typeparam>
|
||||
/// <param name="by">The selector to find the element.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 3000).</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 5000).</param>
|
||||
/// <returns>The found element.</returns>
|
||||
public T Find<T>(By by, int timeoutMS = 3000)
|
||||
public T Find<T>(By by, int timeoutMS = 5000, bool global = false)
|
||||
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>(
|
||||
|
||||
// leverage findAll to filter out mismatched elements
|
||||
var collection = this.FindAll<T>(by, timeoutMS, global);
|
||||
|
||||
Assert.IsTrue(collection.Count > 0, $"UI-Element({typeof(T).Name}) 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 5000).</param>
|
||||
/// <returns>The found element.</returns>
|
||||
public T Find<T>(string name, int timeoutMS = 5000, bool global = false)
|
||||
where T : Element, new()
|
||||
{
|
||||
return this.Find<T>(By.Name(name), timeoutMS, global);
|
||||
}
|
||||
|
||||
/// <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 5000).</param>
|
||||
/// <returns>The found element.</returns>
|
||||
public Element Find(By by, int timeoutMS = 5000, bool global = false)
|
||||
{
|
||||
return this.Find<Element>(by, timeoutMS, global);
|
||||
}
|
||||
|
||||
/// <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 5000).</param>
|
||||
/// <returns>The found element.</returns>
|
||||
public Element Find(string name, int timeoutMS = 5000, bool global = false)
|
||||
{
|
||||
return this.Find<Element>(By.Name(name), timeoutMS, global);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Has only one Element or its derived class by selector.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The class of the element, should be Element or its derived class.</typeparam>
|
||||
/// <param name="by">The name of the element.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 5000).</param>
|
||||
/// <returns>True if only has one element, otherwise false.</returns>
|
||||
public bool HasOne<T>(By by, int timeoutMS = 5000, bool global = false)
|
||||
where T : Element, new()
|
||||
{
|
||||
return this.FindAll<T>(by, timeoutMS, global).Count == 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shortcut for this.HasOne<Element>(by, timeoutMS)
|
||||
/// </summary>
|
||||
/// <param name="by">The name of the element.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 5000).</param>
|
||||
/// <returns>True if only has one element, otherwise false.</returns>
|
||||
public bool HasOne(By by, int timeoutMS = 5000, bool global = false)
|
||||
{
|
||||
return this.HasOne<Element>(by, timeoutMS, global);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shortcut for this.HasOne<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 5000).</param>
|
||||
/// <returns>True if only has one element, otherwise false.</returns>
|
||||
public bool HasOne<T>(string name, int timeoutMS = 5000, bool global = false)
|
||||
where T : Element, new()
|
||||
{
|
||||
return this.HasOne<T>(By.Name(name), timeoutMS, global);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shortcut for this.HasOne<Element>(name, timeoutMS)
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the element.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 5000).</param>
|
||||
/// <returns>True if only has one element, otherwise false.</returns>
|
||||
public bool HasOne(string name, int timeoutMS = 5000, bool global = false)
|
||||
{
|
||||
return this.HasOne<Element>(By.Name(name), timeoutMS, global);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Has one or more Element or its derived class by selector.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The class of the element, should be Element or its derived class.</typeparam>
|
||||
/// <param name="by">The selector to find the element.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 5000).</param>
|
||||
/// <returns>True if has one or more element, otherwise false.</returns>
|
||||
public bool Has<T>(By by, int timeoutMS = 5000, bool global = false)
|
||||
where T : Element, new()
|
||||
{
|
||||
return this.FindAll<T>(by, timeoutMS, global).Count >= 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shortcut for this.Has<Element>(by, timeoutMS)
|
||||
/// </summary>
|
||||
/// <param name="by">The selector to find the element.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 5000).</param>
|
||||
/// <returns>True if has one or more element, otherwise false.</returns>
|
||||
public bool Has(By by, int timeoutMS = 5000, bool global = false)
|
||||
{
|
||||
return this.Has<Element>(by, timeoutMS, global);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shortcut for this.Has<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 5000).</param>
|
||||
/// <returns>True if has one or more element, otherwise false.</returns>
|
||||
public bool Has<T>(string name, int timeoutMS = 5000, bool global = false)
|
||||
where T : Element, new()
|
||||
{
|
||||
return this.Has<T>(By.Name(name), timeoutMS, global);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shortcut for this.Has<Element>(name, timeoutMS)
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the element.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 5000).</param>
|
||||
/// <returns>True if has one or more element, otherwise false.</returns>
|
||||
public bool Has(string name, int timeoutMS = 5000, bool global = false)
|
||||
{
|
||||
return this.Has<Element>(name, timeoutMS, global);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds all Element or its derived class by selector.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The class of the elements, should be Element or its derived class.</typeparam>
|
||||
/// <param name="by">The selector to find the elements.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 5000).</param>
|
||||
/// <returns>A read-only collection of the found elements.</returns>
|
||||
public ReadOnlyCollection<T> FindAll<T>(By by, int timeoutMS = 5000, bool global = false)
|
||||
where T : Element, new()
|
||||
{
|
||||
var driver = global ? this.Root : this.WindowsDriver;
|
||||
Assert.IsNotNull(driver, $"WindowsElement is null in method FindAll<{typeof(T).Name}> with parameters: by = {by}, timeoutMS = {timeoutMS}");
|
||||
var foundElements = FindHelper.FindAll<T, WindowsElement>(
|
||||
() =>
|
||||
{
|
||||
var element = this.WindowsDriver.FindElement(by.ToSeleniumBy());
|
||||
Assert.IsNotNull(element, $"Element not found using selector: {by}");
|
||||
return element;
|
||||
if (by.GetIsAccessibilityId())
|
||||
{
|
||||
var elements = driver.FindElementsByAccessibilityId(by.GetAccessibilityId());
|
||||
return elements;
|
||||
}
|
||||
else
|
||||
{
|
||||
var elements = driver.FindElements(by.ToSeleniumBy());
|
||||
return elements;
|
||||
}
|
||||
},
|
||||
this.WindowsDriver,
|
||||
driver,
|
||||
timeoutMS);
|
||||
|
||||
return foundElement;
|
||||
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="by">The selector to find the elements.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 3000).</param>
|
||||
/// <param name="name">The name to find the elements.</param>
|
||||
/// <param name="timeoutMS">The timeout in milliseconds (default is 5000).</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>(string name, int timeoutMS = 5000, bool global = false)
|
||||
where T : Element, new()
|
||||
{
|
||||
Assert.IsNotNull(this.WindowsDriver, $"WindowsElement is null in method FindAll<{typeof(T).Name}> with parameters: by = {by}, timeoutMS = {timeoutMS}");
|
||||
var foundElements = FindHelper.FindAll<T, WindowsElement>(
|
||||
() =>
|
||||
{
|
||||
var elements = this.WindowsDriver.FindElements(by.ToSeleniumBy());
|
||||
return elements;
|
||||
},
|
||||
this.WindowsDriver,
|
||||
timeoutMS);
|
||||
return this.FindAll<T>(By.Name(name), timeoutMS, global);
|
||||
}
|
||||
|
||||
return foundElements ?? new ReadOnlyCollection<T>(new List<T>());
|
||||
/// <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 5000).</param>
|
||||
/// <returns>A read-only collection of the found elements.</returns>
|
||||
public ReadOnlyCollection<Element> FindAll(By by, int timeoutMS = 5000, bool global = false)
|
||||
{
|
||||
return this.FindAll<Element>(by, timeoutMS, global);
|
||||
}
|
||||
|
||||
/// <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 5000).</param>
|
||||
/// <returns>A read-only collection of the found elements.</returns>
|
||||
public ReadOnlyCollection<Element> FindAll(string name, int timeoutMS = 5000, bool global = false)
|
||||
{
|
||||
return this.FindAll<Element>(By.Name(name), timeoutMS, global);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Close the main window.
|
||||
/// </summary>
|
||||
public void CloseMainWindow()
|
||||
{
|
||||
if (MainWindow != null)
|
||||
{
|
||||
MainWindow.Close();
|
||||
MainWindow = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a combination of keys.
|
||||
/// </summary>
|
||||
/// <param name="keys">The keys to send.</param>
|
||||
public void SendKeys(params Key[] keys)
|
||||
{
|
||||
PerformAction(() =>
|
||||
{
|
||||
KeyboardHelper.SendKeys(keys);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// release the key (after the hold key and drag is completed.)
|
||||
/// </summary>
|
||||
/// <param name="key">The key release.</param>
|
||||
public void PressKey(Key key)
|
||||
{
|
||||
PerformAction(() =>
|
||||
{
|
||||
KeyboardHelper.PressKey(key);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// press and hold the specified key.
|
||||
/// </summary>
|
||||
/// <param name="key">The key to press and hold .</param>
|
||||
public void ReleaseKey(Key key)
|
||||
{
|
||||
PerformAction(() =>
|
||||
{
|
||||
KeyboardHelper.ReleaseKey(key);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// press and hold the specified key.
|
||||
/// </summary>
|
||||
/// <param name="key">The key to press and release .</param>
|
||||
public void SendKey(Key key, int msPreAction = 500, int msPostAction = 500)
|
||||
{
|
||||
PerformAction(
|
||||
() =>
|
||||
{
|
||||
KeyboardHelper.SendKey(key);
|
||||
},
|
||||
msPreAction,
|
||||
msPostAction);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a sequence of keys.
|
||||
/// </summary>
|
||||
/// <param name="keys">An array of keys to send.</param>
|
||||
public void SendKeySequence(params Key[] keys)
|
||||
{
|
||||
PerformAction(() =>
|
||||
{
|
||||
foreach (var key in keys)
|
||||
{
|
||||
KeyboardHelper.SendKeys(key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current position of the mouse cursor as a tuple.
|
||||
/// </summary>
|
||||
/// <returns>A tuple containing the X and Y coordinates of the cursor.</returns>
|
||||
public Tuple<int, int> GetMousePosition()
|
||||
{
|
||||
return MouseHelper.GetMousePosition();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves the mouse cursor to the specified screen coordinates.
|
||||
/// </summary>
|
||||
/// <param name="x">The new x-coordinate of the cursor.</param>
|
||||
/// <param name="y">The new y-coordinate of the cursor.</param
|
||||
public void MoveMouseTo(int x, int y, int msPreAction = 500, int msPostAction = 500)
|
||||
{
|
||||
PerformAction(
|
||||
() =>
|
||||
{
|
||||
MouseHelper.MoveMouseTo(x, y);
|
||||
},
|
||||
msPreAction,
|
||||
msPostAction);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a mouse action based on the specified action type.
|
||||
/// </summary>
|
||||
/// <param name="action">The mouse action to perform.</param>
|
||||
/// <param name="msPreAction">Pre-action delay in milliseconds.</param>
|
||||
/// <param name="msPostAction">Post-action delay in milliseconds.</param>
|
||||
public void PerformMouseAction(MouseActionType action, int msPreAction = 500, int msPostAction = 500)
|
||||
{
|
||||
PerformAction(
|
||||
() =>
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case MouseActionType.LeftClick:
|
||||
MouseHelper.LeftClick();
|
||||
break;
|
||||
case MouseActionType.RightClick:
|
||||
MouseHelper.RightClick();
|
||||
break;
|
||||
case MouseActionType.MiddleClick:
|
||||
MouseHelper.MiddleClick();
|
||||
break;
|
||||
case MouseActionType.LeftDoubleClick:
|
||||
MouseHelper.LeftDoubleClick();
|
||||
break;
|
||||
case MouseActionType.RightDoubleClick:
|
||||
MouseHelper.RightDoubleClick();
|
||||
break;
|
||||
case MouseActionType.LeftDown:
|
||||
MouseHelper.LeftDown();
|
||||
break;
|
||||
case MouseActionType.LeftUp:
|
||||
MouseHelper.LeftUp();
|
||||
break;
|
||||
case MouseActionType.RightDown:
|
||||
MouseHelper.RightDown();
|
||||
break;
|
||||
case MouseActionType.RightUp:
|
||||
MouseHelper.RightUp();
|
||||
break;
|
||||
case MouseActionType.MiddleDown:
|
||||
MouseHelper.MiddleDown();
|
||||
break;
|
||||
case MouseActionType.MiddleUp:
|
||||
MouseHelper.MiddleUp();
|
||||
break;
|
||||
case MouseActionType.ScrollUp:
|
||||
MouseHelper.ScrollUp();
|
||||
break;
|
||||
case MouseActionType.ScrollDown:
|
||||
MouseHelper.ScrollDown();
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("Unsupported mouse action.", nameof(action));
|
||||
throw new ArgumentException("Unsupported mouse action.", nameof(action));
|
||||
}
|
||||
},
|
||||
msPreAction,
|
||||
msPostAction);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attaches to an existing PowerToys module.
|
||||
/// </summary>
|
||||
/// <param name="module">The PowerToys module to attach to.</param>
|
||||
/// <param name="size">The window size to set. Default is no change to window size</param>
|
||||
/// <returns>The attached session.</returns>
|
||||
public Session Attach(PowerToysModule module)
|
||||
public Session Attach(PowerToysModule module, WindowSize size = WindowSize.UnSpecified)
|
||||
{
|
||||
string windowName = ModuleConfigData.Instance.GetModuleWindowName(module);
|
||||
return this.Attach(windowName);
|
||||
return this.Attach(windowName, size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -91,26 +470,44 @@ namespace Microsoft.PowerToys.UITest
|
||||
/// The session should be attached when a new app is started.
|
||||
/// </summary>
|
||||
/// <param name="windowName">The window name to attach to.</param>
|
||||
/// <param name="size">The window size to set. Default is no change to window size</param>
|
||||
/// <returns>The attached session.</returns>
|
||||
public Session Attach(string windowName)
|
||||
public Session Attach(string windowName, WindowSize size = WindowSize.UnSpecified)
|
||||
{
|
||||
this.IsElevated = null;
|
||||
this.MainWindowHandler = IntPtr.Zero;
|
||||
|
||||
if (this.Root != null)
|
||||
{
|
||||
var window = this.Root.FindElementByName(windowName);
|
||||
Assert.IsNotNull(window, $"Failed to attach. Window '{windowName}' not found");
|
||||
// search window handler by window title (admin and non-admin titles)
|
||||
var matchingWindows = WindowHelper.ApiHelper.FindDesktopWindowHandler([windowName, WindowHelper.AdministratorPrefix + windowName]);
|
||||
if (matchingWindows.Count == 0 || matchingWindows[0].HWnd == IntPtr.Zero)
|
||||
{
|
||||
Assert.Fail($"Failed to attach. Window '{windowName}' not found");
|
||||
}
|
||||
|
||||
// pick one from matching windows
|
||||
this.MainWindowHandler = matchingWindows[0].HWnd;
|
||||
this.IsElevated = matchingWindows[0].Title.StartsWith(WindowHelper.AdministratorPrefix);
|
||||
|
||||
ApiHelper.SetForegroundWindow(this.MainWindowHandler);
|
||||
|
||||
var hexWindowHandle = this.MainWindowHandler.ToInt64().ToString("x");
|
||||
|
||||
var windowHandle = new nint(int.Parse(window.GetAttribute("NativeWindowHandle")));
|
||||
SetForegroundWindow(windowHandle);
|
||||
var hexWindowHandle = windowHandle.ToString("x");
|
||||
var appCapabilities = new AppiumOptions();
|
||||
|
||||
appCapabilities.AddAdditionalCapability("appTopLevelWindow", hexWindowHandle);
|
||||
appCapabilities.AddAdditionalCapability("deviceName", "WindowsPC");
|
||||
this.WindowsDriver = new WindowsDriver<WindowsElement>(new Uri(ModuleConfigData.Instance.GetWindowsApplicationDriverUrl()), appCapabilities);
|
||||
Assert.IsNotNull(this.WindowsDriver, "Attach WindowsDriver is null");
|
||||
|
||||
// Set implicit timeout to make element search retry every 500 ms
|
||||
this.WindowsDriver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(3);
|
||||
this.windowHandlers.Add(this.MainWindowHandler);
|
||||
|
||||
if (size != WindowSize.UnSpecified)
|
||||
{
|
||||
WindowHelper.SetWindowSize(this.MainWindowHandler, size);
|
||||
}
|
||||
|
||||
// Set MainWindow
|
||||
MainWindow = Find<Window>(matchingWindows[0].Title);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -119,5 +516,125 @@ namespace Microsoft.PowerToys.UITest
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the main window size.
|
||||
/// </summary>
|
||||
/// <param name="size">WindowSize enum</param>
|
||||
public void SetMainWindowSize(WindowSize size)
|
||||
{
|
||||
if (this.MainWindowHandler == IntPtr.Zero)
|
||||
{
|
||||
// Attach to the scope & reset MainWindowHandler
|
||||
this.Attach(this.InitScope);
|
||||
}
|
||||
|
||||
WindowHelper.SetWindowSize(this.MainWindowHandler, size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the main window center coordinates.
|
||||
/// </summary>
|
||||
/// <returns>(x, y)</returns>
|
||||
public (int CenterX, int CenterY) GetMainWindowCenter()
|
||||
{
|
||||
return WindowHelper.GetWindowCenter(this.MainWindowHandler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the main window center coordinates.
|
||||
/// </summary>
|
||||
/// <returns>(int Left, int Top, int Right, int Bottom)</returns>
|
||||
public (int Left, int Top, int Right, int Bottom) GetMainWindowRect()
|
||||
{
|
||||
return WindowHelper.GetWindowRect(this.MainWindowHandler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Launches the specified executable with optional arguments and simulates a delay before and after execution.
|
||||
/// </summary>
|
||||
/// <param name="executablePath">The full path to the executable to launch.</param>
|
||||
/// <param name="arguments">Optional command-line arguments to pass to the executable.</param>
|
||||
/// <param name="msPreAction">The number of milliseconds to wait before launching the executable. Default is 0 ms.</param>
|
||||
/// <param name="msPostAction">The number of milliseconds to wait after launching the executable. Default is 2000 ms.</param>
|
||||
public void StartExe(string executablePath, string arguments = "", int msPreAction = 0, int msPostAction = 2000)
|
||||
{
|
||||
PerformAction(
|
||||
() =>
|
||||
{
|
||||
StartExeInternal(executablePath, arguments);
|
||||
},
|
||||
msPreAction,
|
||||
msPostAction);
|
||||
}
|
||||
|
||||
private void StartExeInternal(string executablePath, string arguments = "")
|
||||
{
|
||||
var processInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = executablePath,
|
||||
Arguments = arguments,
|
||||
UseShellExecute = true,
|
||||
};
|
||||
Process.Start(processInfo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Terminates all running processes that match the specified process name.
|
||||
/// Waits for each process to exit after sending the kill signal.
|
||||
/// </summary>
|
||||
/// <param name="processName">The name of the process to terminate (without extension, e.g., "notepad").</param>
|
||||
public void KillAllProcessesByName(string processName)
|
||||
{
|
||||
foreach (var process in Process.GetProcessesByName(processName))
|
||||
{
|
||||
process.Kill();
|
||||
process.WaitForExit();
|
||||
}
|
||||
}
|
||||
|
||||
/// <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();
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 action, int msPreAction = 500, int msPostAction = 500)
|
||||
{
|
||||
if (msPreAction > 0)
|
||||
{
|
||||
Task.Delay(msPreAction).Wait();
|
||||
}
|
||||
|
||||
action();
|
||||
|
||||
if (msPostAction > 0)
|
||||
{
|
||||
Task.Delay(msPostAction).Wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user