Compare commits
149 Commits
copilot/ad
...
feature/ru
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe421abe0a | ||
|
|
a8bf8da0f4 | ||
|
|
e5b0667397 | ||
|
|
8536d7b1cd | ||
|
|
7ac16118c8 | ||
|
|
7508e6e794 | ||
|
|
2d9dfff444 | ||
|
|
9de2e5298a | ||
|
|
07beeca9b9 | ||
|
|
234933f6fa | ||
|
|
f8a10550f3 | ||
|
|
ca1ffebc26 | ||
|
|
2e5c7d2ee6 | ||
|
|
949e42c5c7 | ||
|
|
a65266fcad | ||
|
|
656ea91580 | ||
|
|
d9bfc42229 | ||
|
|
11bfb40ec6 | ||
|
|
1eecf46c51 | ||
|
|
eeaf89e481 | ||
|
|
bfc5fea11e | ||
|
|
98c5b45a30 | ||
|
|
5509628f51 | ||
|
|
a255493c68 | ||
|
|
5c15a63846 | ||
|
|
2c95a61bb3 | ||
|
|
dbc390ab0d | ||
|
|
c6a79360f3 | ||
|
|
b0ccc2394a | ||
|
|
c8ffcb73c3 | ||
|
|
fcfbf83b55 | ||
|
|
de6ba922fd | ||
|
|
71cb9bc54e | ||
|
|
8ad571dcde | ||
|
|
bf00c1b94f | ||
|
|
7a89220a91 | ||
|
|
3a541bb3eb | ||
|
|
f4d23c85a6 | ||
|
|
5e302bed79 | ||
|
|
520037e128 | ||
|
|
d80d216bef | ||
|
|
b310c55835 | ||
|
|
989c2eab23 | ||
|
|
03017e4703 | ||
|
|
88dd87f830 | ||
|
|
8fcba2d49d | ||
|
|
e499395b18 | ||
|
|
8f9cf7c4cb | ||
|
|
828c47c646 | ||
|
|
40e9bbd98d | ||
|
|
3d1a7e184b | ||
|
|
25847a3689 | ||
|
|
69d07e3033 | ||
|
|
b1f950b2dd | ||
|
|
5f941ca2e9 | ||
|
|
de03ce47fd | ||
|
|
f732cdfd4f | ||
|
|
07dee36eb3 | ||
|
|
b9755dc0c2 | ||
|
|
fc1195dc9c | ||
|
|
c6e7dfd5cd | ||
|
|
e2b8790220 | ||
|
|
7e7a9d23b8 | ||
|
|
b1bfa4bdc6 | ||
|
|
02f7a965b4 | ||
|
|
cbf485180c | ||
|
|
f903dcca33 | ||
|
|
33ce801a56 | ||
|
|
0c4b30eb44 | ||
|
|
16937cf2af | ||
|
|
032e3d5dee | ||
|
|
54801f09f1 | ||
|
|
29587e48e7 | ||
|
|
c2fe908e18 | ||
|
|
d55fc53884 | ||
|
|
cf0a0d7ca9 | ||
|
|
139815ceb3 | ||
|
|
9311ac2579 | ||
|
|
b27e1081ae | ||
|
|
39869bcaae | ||
|
|
fb17678b01 | ||
|
|
315824f4ef | ||
|
|
36907ad6f2 | ||
|
|
8bacded9c4 | ||
|
|
5a3ccb3b60 | ||
|
|
00529713fd | ||
|
|
e0868b099a | ||
|
|
182e521730 | ||
|
|
797bd4cb35 | ||
|
|
297c7f0cbc | ||
|
|
7df1c2f002 | ||
|
|
8727a72a83 | ||
|
|
a2e81dbc3f | ||
|
|
7c870d48ea | ||
|
|
3006cbf42d | ||
|
|
a7ea40749e | ||
|
|
94ea7597be | ||
|
|
3f6b41fc80 | ||
|
|
aede049596 | ||
|
|
5440699250 | ||
|
|
57957d5dbf | ||
|
|
6e882b9cb2 | ||
|
|
ce24d9d951 | ||
|
|
3ee8a78178 | ||
|
|
d0b46a98eb | ||
|
|
3c08019190 | ||
|
|
25badc45a4 | ||
|
|
6b8a2064ab | ||
|
|
14d8c36768 | ||
|
|
23500371b5 | ||
|
|
f932679911 | ||
|
|
81494b23bf | ||
|
|
1ad1c98c98 | ||
|
|
ec9071bc4f | ||
|
|
180d4a21aa | ||
|
|
9a77b8e9cb | ||
|
|
b1935ca1eb | ||
|
|
a1c34b1503 | ||
|
|
5368c82154 | ||
|
|
c21ab5bc30 | ||
|
|
b3a084db0a | ||
|
|
4fe880cc1e | ||
|
|
e9cf9113a4 | ||
|
|
2752054b14 | ||
|
|
f7a30212d9 | ||
|
|
9b36bb9ddd | ||
|
|
79515f0d6b | ||
|
|
99523fe317 | ||
|
|
5398c16456 | ||
|
|
123d318d6a | ||
|
|
09a79ab692 | ||
|
|
9cd23666d3 | ||
|
|
bf99a2a0e5 | ||
|
|
261381f2f7 | ||
|
|
b971d8799a | ||
|
|
0155bb3b63 | ||
|
|
43e9959df4 | ||
|
|
231f59c7a9 | ||
|
|
1532dd5b38 | ||
|
|
9afa3a1ecc | ||
|
|
17af826408 | ||
|
|
b9c9ade9d9 | ||
|
|
18c335397f | ||
|
|
6d1f533af4 | ||
|
|
6dd9617538 | ||
|
|
d1564b0572 | ||
|
|
2ddf561f57 | ||
|
|
6fea4d9c5d | ||
|
|
77a8555fd4 |
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -57,6 +57,7 @@ body:
|
||||
- Environment Variables
|
||||
- FancyZones
|
||||
- FancyZones Editor
|
||||
- Grab And Move
|
||||
- File Locksmith
|
||||
- "File Explorer: Preview Pane"
|
||||
- "File Explorer: Thumbnail preview"
|
||||
@@ -69,6 +70,7 @@ body:
|
||||
- Mouse Without Borders
|
||||
- New+
|
||||
- Peek
|
||||
- Power Display
|
||||
- PowerRename
|
||||
- PowerToys Run
|
||||
- Quick Accent
|
||||
|
||||
3
.github/actions/spell-check/allow/code.txt
vendored
@@ -127,6 +127,7 @@ HOLDSPACE
|
||||
HOLDBACKSPACE
|
||||
IDIGNORE
|
||||
KBDLLHOOKSTRUCT
|
||||
keydowns
|
||||
keyevent
|
||||
LAlt
|
||||
LBUTTON
|
||||
@@ -335,8 +336,10 @@ ABE
|
||||
Mdt
|
||||
HTCAPTION
|
||||
POSCHANGED
|
||||
QPC
|
||||
QUERYPOS
|
||||
SETAUTOHIDEBAR
|
||||
ULW
|
||||
WINDOWPOS
|
||||
WINEVENTPROC
|
||||
WORKERW
|
||||
|
||||
73
.github/actions/spell-check/candidate.patterns
vendored
@@ -1,6 +1,3 @@
|
||||
# D2D
|
||||
#D?2D
|
||||
|
||||
# Repeated letters
|
||||
\b([a-z])\g{-1}{2,}\b
|
||||
|
||||
@@ -14,7 +11,7 @@
|
||||
^.*\b[Cc][Ss][Pp][Ee][Ll]{2}:\s*[Dd][Ii][Ss][Aa][Bb][Ll][Ee]-[Ll][Ii][Nn][Ee]\b
|
||||
|
||||
# copyright
|
||||
Copyright (?:\([Cc]\)|)(?:[-\d, ]|and)+(?: [A-Z][a-z]+ [A-Z][a-z]+,?)+
|
||||
Copyright (?:\([Cc]\)|©|)(?:[-\d, ]|and)+(?: [A-Z][a-z]+ [A-Z][a-z]+,?)+
|
||||
|
||||
# patch hunk comments
|
||||
^@@ -\d+(?:,\d+|) \+\d+(?:,\d+|) @@ .*
|
||||
@@ -22,10 +19,10 @@ Copyright (?:\([Cc]\)|)(?:[-\d, ]|and)+(?: [A-Z][a-z]+ [A-Z][a-z]+,?)+
|
||||
index (?:[0-9a-z]{7,40},|)[0-9a-z]{7,40}\.\.[0-9a-z]{7,40}
|
||||
|
||||
# file permissions
|
||||
['"`\s][-bcdLlpsw](?:[-r][-w][-Ssx]){2}[-r][-w][-SsTtx]\+?['"`\s]
|
||||
(?:^|['"`\s])(?!-+\s)[-bcdLlpsw](?:[-r][-w][-Ssx]){2}[-r][-w][-SsTtx]\+?['"`\s]
|
||||
|
||||
# css fonts
|
||||
\bfont(?:-family|):[^;}]+
|
||||
\bfont(?:-family(?:[-\w+]*)|):[^;}]+
|
||||
|
||||
# css url wrappings
|
||||
\burl\([^)]+\)
|
||||
@@ -90,6 +87,9 @@ arn:aws:[-/:\w]+
|
||||
# AWS VPC
|
||||
vpc-\w+
|
||||
|
||||
# Azure AD
|
||||
\baad\.\w{48}\b
|
||||
|
||||
# While you could try to match `http://` and `https://` by using `s?` in `https?://`, sometimes there
|
||||
# YouTube url
|
||||
\b(?:(?:www\.|)youtube\.com|youtu.be)/(?:channel/|embed/|user/|playlist\?list=|watch\?v=|v/|)[-a-zA-Z0-9?&=_%]*
|
||||
@@ -171,7 +171,7 @@ themes\.googleusercontent\.com/static/fonts/[^/\s"]+/v\d+/[^.]+.
|
||||
GHSA(?:-[0-9a-z]{4}){3}
|
||||
|
||||
# GitHub actions
|
||||
\buses:\s+[-\w.]+/[-\w./]+@[-\w.]+
|
||||
\buses:\s+(['"]?)[-\w.]+/[-\w./]+@[-\w.]+\g{-1}
|
||||
|
||||
# GitLab commit
|
||||
\bgitlab\.[^/\s"]*/\S+/\S+/commit/[0-9a-f]{7,16}#[0-9a-f]{40}\b
|
||||
@@ -240,7 +240,7 @@ accounts\.binance\.com/[a-z/]*oauth/authorize\?[-0-9a-zA-Z&%]*
|
||||
\bmedium\.com/@?[^/\s"]+/[-\w]+
|
||||
|
||||
# microsoft
|
||||
\b(?:https?://|)(?:(?:(?:blogs|download\.visualstudio|docs|msdn2?|research)\.|)microsoft|blogs\.msdn)\.co(?:m|\.\w\w)/[-_a-zA-Z0-9()=./%]*
|
||||
\b(?:https?://|)(?:(?:(?:blogs|download\.visualstudio|docs|msdn2?|research)\.|)microsoft|blogs\.msdn)\.co(?:m|\.\w\w)/[-_a-zA-Z0-9()=./%?#]*
|
||||
# powerbi
|
||||
\bapp\.powerbi\.com/reportEmbed/[^"' ]*
|
||||
# vs devops
|
||||
@@ -414,7 +414,7 @@ ipfs://[0-9a-zA-Z]{3,}
|
||||
\bgetopts\s+(?:"[^"]+"|'[^']+')
|
||||
|
||||
# ANSI color codes
|
||||
(?:\\(?:u00|x)1[Bb]|\\03[1-7]|\x1b|\\u\{1[Bb]\})\[\d+(?:;\d+)*m
|
||||
(?:\\(?:u00|x)1[Bb]|\\03[1-7]|\x1b|\\u\{1[Bb]\})\[(?:\d+(?:;\d+)*|)m
|
||||
|
||||
# URL escaped characters
|
||||
%[0-9A-F][A-F](?=[A-Za-z])
|
||||
@@ -431,7 +431,7 @@ sha\d+:[0-9a-f]*?[a-f]{3,}[0-9a-f]*
|
||||
# sha-... -- uses a fancy capture
|
||||
(\\?['"]|")[0-9a-f]{40,}\g{-1}
|
||||
# hex runs
|
||||
\b[0-9a-fA-F]{16,}\b
|
||||
\b(?=(?:[a-fA-F]{0,2}\d)*[a-fA-F]{3})[0-9a-fA-F]{16,}\b
|
||||
# hex in url queries
|
||||
=[0-9a-fA-F]*?(?:[A-F]{3,}|[a-f]{3,})[0-9a-fA-F]*?&
|
||||
# ssh
|
||||
@@ -455,7 +455,11 @@ LS0tLS1CRUdJT.*
|
||||
|
||||
# uuid:
|
||||
\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b
|
||||
# hex digits including css/html color classes:
|
||||
|
||||
# unicode escaped characters (4)
|
||||
\\u[0-9a-fA-F]{4}
|
||||
|
||||
# hex digits including css/html color classes
|
||||
(?:[\\0][xX]|\\u\{?|[uU]\+|#x?|%23|&H)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|[iu]\d+)\b
|
||||
|
||||
# integrity
|
||||
@@ -478,7 +482,7 @@ Name\[[^\]]+\]=.*
|
||||
(?:(?:\b|_|(?<=[a-z]))I|(?:\b|_)(?:nsI|isA))(?=(?:[A-Z][a-z]{2,})+(?:[A-Z\d]|\b))
|
||||
|
||||
# python
|
||||
#\b(?i)py(?!gments|gmy|lon|ramid|ro|th)(?=[a-z]{2,})
|
||||
#\b(?i)py(?!gment|gmy|lon|ramid|ro|th)(?=[a-z]{2,})
|
||||
|
||||
# crypt
|
||||
(['"])\$2[ayb]\$.{56}\g{-1}
|
||||
@@ -498,12 +502,21 @@ Name\[[^\]]+\]=.*
|
||||
# go.sum
|
||||
\bh1:\S+
|
||||
|
||||
# golang print-f-style functions
|
||||
#(?i)(?<=append|comma|debug|equal|err|error|exit|fatal|format|info|log|name|panic|print|skip|scan|string|trace|true|warn|warning|wrap|write)(?:f|ln)(?:[ (]|$)
|
||||
|
||||
# golang regular expression
|
||||
(?<!")\br".+?"
|
||||
|
||||
# imports
|
||||
^import\s+(?:(?:static|type)\s+|)(?:[\w.]|\{\s*\w*?(?:,\s*(?:\w*|\*))+\s*\})+
|
||||
^import\s+(?:(?:static|type)\s+|)(?:[\w.]|\{\s*\w*?(?:,\s*(?:\w*|\*))+\s*\})+(?:\s+from (['"]).*?\g{-1}|)
|
||||
|
||||
# scala modules
|
||||
#("[^"]+"\s*%%?\s*){2,3}"[^"]+"
|
||||
|
||||
# Dataframes / NumPy
|
||||
#\b(?:df|np)\.\w{3,}
|
||||
|
||||
# container images
|
||||
image: [-\w./:@]+
|
||||
|
||||
@@ -533,12 +546,18 @@ content: (['"])[-a-zA-Z=;:/0-9+]*=\g{-1}
|
||||
# Note that there's a high false positive rate, remove the `?=` and search for the regex to see if the matches seem like reasonable strings
|
||||
(?<!['"])\b(?:B|BR|Br|F|FR|Fr|R|RB|RF|Rb|Rf|U|UR|Ur|b|bR|br|f|fR|fr|r|rB|rF|rb|rf|u|uR|ur)['"](?=[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})
|
||||
|
||||
# Regular expression for word breaks
|
||||
#\\b(?=[a-z]{2})
|
||||
|
||||
# Regular expressions for (P|p)assword
|
||||
\([A-Z]\|[a-z]\)[a-z]+
|
||||
|
||||
# Java regular expressions
|
||||
Pattern\.(?:compile|matches)\(".*"
|
||||
|
||||
# JavaScript regular expressions
|
||||
# javascript test regex
|
||||
/.{3,}/[gim]*\.test\(
|
||||
# javascript exec/test regex
|
||||
/.{3,}?/[gim]*\.(?:exec|test)\(
|
||||
# javascript match regex
|
||||
\.match\(/[^/\s"]{3,}/[gim]*\s*
|
||||
# javascript match regex
|
||||
@@ -565,7 +584,7 @@ perl(?:\s+-[a-zA-Z]\w*)+
|
||||
regexp?\.MustCompile\((?:`[^`]*`|".*"|'.*')\)
|
||||
|
||||
# regex choice
|
||||
# \(\?:[^)]+\|[^)]+\)
|
||||
#\((?:\?:|)[^)|]+(?<! )\|(?!(?:jq|xargs)\b)[^)| ][^)]*\)
|
||||
|
||||
# proto
|
||||
^\s*(\w+)\s\g{-1} =
|
||||
@@ -588,6 +607,9 @@ urn:shemas-jetbrains-com
|
||||
# Debian changelog severity
|
||||
[-\w]+ \(.*\) (?:\w+|baseline|unstable|experimental); urgency=(?:low|medium|high|emergency|critical)\b
|
||||
|
||||
# Red Hat Package management spec file dependencies
|
||||
^(?:Build|)Requires: [-.\w]+
|
||||
|
||||
# kubernetes pod status lists
|
||||
# https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase
|
||||
\w+(?:-\w+)+\s+\d+/\d+\s+(?:Running|Pending|Succeeded|Failed|Unknown)\s+
|
||||
@@ -642,6 +664,8 @@ PrependWithABINamepsace
|
||||
>[-a-zA-Z=;:/0-9+]{3,}=</
|
||||
# base64 encoded content, possibly wrapped in mime
|
||||
#(?:^|[\s=;:?])[-a-zA-Z=;:/0-9+]{50,}(?:[\s=;:?]|$)
|
||||
# jwt
|
||||
(?:\be[wy][-a-zA-Z=;:/0-9+]+\.){2}[-_\w]+
|
||||
# base64 encoded json
|
||||
\beyJ[-a-zA-Z=;:/0-9+]+
|
||||
# base64 encoded pkcs
|
||||
@@ -679,9 +703,9 @@ systemd.*?running in system mode \([-+].*\)$
|
||||
|
||||
# Non-English
|
||||
# Even repositories expecting pure English content can unintentionally have Non-English content... People will occasionally mistakenly enter [homoglyphs](https://en.wikipedia.org/wiki/Homoglyph) which are essentially typos, and using this pattern will mean check-spelling will not complain about them.
|
||||
#
|
||||
# .
|
||||
# If the content to be checked should be written in English and the only Non-English items will be people's names, then you can consider adding this.
|
||||
#
|
||||
# .
|
||||
# Alternatively, if you're using check-spelling v0.0.25+, and you would like to _check_ the Non-English content for spelling errors, you can. For information on how to do so, see:
|
||||
# https://docs.check-spelling.dev/Feature:-Configurable-word-characters.html#unicode
|
||||
[a-zA-Z]*[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*|[a-zA-Z]{3,}[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]|[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3,}
|
||||
@@ -693,7 +717,7 @@ systemd.*?running in system mode \([-+].*\)$
|
||||
# This corpus only had capital letters, but you probably want lowercase ones as well.
|
||||
\b[LN]'+[a-z]{2,}\b
|
||||
|
||||
# latex (check-spelling >= 0.0.22)
|
||||
# LaTeX
|
||||
\\\w{2,}\{
|
||||
|
||||
# American Mathematical Society (AMS) / Doxygen
|
||||
@@ -720,7 +744,6 @@ nolint:\s*[\w,]+
|
||||
# cygwin paths
|
||||
/cygdrive/[a-zA-Z]/(?:Program Files(?: \(.*?\)| ?)(?:/[-+.~\\/()\w ]+)*|[-+.~\\/()\w])+
|
||||
|
||||
# in check-spelling@v0.0.22+, printf markers aren't automatically consumed
|
||||
# printf markers
|
||||
#(?<!\\)\\[nrt](?=[a-z]{2,})
|
||||
# alternate printf markers if you run into latex and friends
|
||||
@@ -749,12 +772,12 @@ W/"[^"]+"
|
||||
|
||||
# Compiler flags (Unix, Java/Scala)
|
||||
# Use if you have things like `-Pdocker` and want to treat them as `docker`
|
||||
#(?:^|[\t ,>"'`=(#])-(?:(?:J-|)[DPWXY]|[Llf])(?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
|
||||
#(?:^|[\t ,>"'`=\[(#])-(?:(?:J-|)[DPWXY]|[Llf])(?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
|
||||
|
||||
# Compiler flags (Windows / PowerShell)
|
||||
# This is a subset of the more general compiler flags pattern.
|
||||
# It avoids matching `-Path` to prevent it from being treated as `ath`
|
||||
#(?:^|[\t ,"'`=(#])-(?:[DPL](?=[A-Z]{2,})|[WXYlf](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,}))
|
||||
#(?:^|[\t ,"'`=\[(#])-(?:[DPL](?=[A-Z]{2,})|[WXYlf](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,}))
|
||||
|
||||
# Compiler flags (linker)
|
||||
,-B
|
||||
@@ -762,7 +785,7 @@ W/"[^"]+"
|
||||
# Library prefix
|
||||
# e.g., `lib`+`archive`, `lib`+`raw`, `lib`+`unwind`
|
||||
# (ignores some words that happen to start with `lib`)
|
||||
(?:\b|_)[Ll]ib(?:re(?=office)|)(?!era[lt]|ero|erty|rar(?:i(?:an|es)|y))(?=[a-z])
|
||||
(?:\b|_)[Ll]ib(?!era[lt])(?:re(?=office)|era|)(?!ero|erty|rar(?:i(?:an|es)|y))(?=[a-z])
|
||||
|
||||
# iSCSI iqn (approximate regex)
|
||||
\biqn\.[0-9]{4}-[0-9]{2}(?:[\.-][a-z][a-z0-9]*)*\b
|
||||
@@ -773,9 +796,9 @@ W/"[^"]+"
|
||||
# curl arguments
|
||||
\b(?:\\n|)curl(?:\.exe|)(?:\s+-[a-zA-Z]{1,2}\b)*(?:\s+-[a-zA-Z]{3,})(?:\s+-[a-zA-Z]+)*
|
||||
# set arguments
|
||||
\b(?:bash|sh|set)(?:\s+[-+][abefimouxE]{1,2})*\s+[-+][abefimouxE]{3,}(?:\s+[-+][abefimouxE]+)*
|
||||
\b(?:bash|(?<!\.)sh|set)(?:\s+[-+][abefimouxE]{1,2})*\s+[-+][abefimouxE]{3,}(?:\s+[-+][abefimouxE]+)*
|
||||
# tar arguments
|
||||
\b(?:\\n|)g?tar(?:\.exe|)(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+
|
||||
\b(?:\\n|)g?tar(?:\.exe|)(?:\s-C \S+|(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+
|
||||
# tput arguments -- https://man7.org/linux/man-pages/man5/terminfo.5.html -- technically they can be more than 5 chars long...
|
||||
\btput\s+(?:(?:-[SV]|-T\s*\w+)\s+)*\w{3,5}\b
|
||||
# macOS temp folders
|
||||
|
||||
937
.github/actions/spell-check/expect.txt
vendored
497
.github/actions/spell-check/line_forbidden.patterns
vendored
34
.github/actions/spell-check/patterns.txt
vendored
@@ -1,5 +1,18 @@
|
||||
# See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns
|
||||
|
||||
Inno Setup
|
||||
|
||||
FFmpeg
|
||||
|
||||
# https://github.com/MicrosoftEdge/edge-launcher
|
||||
MIcrosoftEdgeLauncherCsharp
|
||||
|
||||
# x64
|
||||
(?:(?<=[a-df-z])x|(?<=[A-Z]X))64
|
||||
|
||||
# reversed irreversible binomials
|
||||
\b(?:mouse down and up|low and high)\b
|
||||
|
||||
# marker to ignore all code on line
|
||||
^.*/\* #no-spell-check-line \*/.*$
|
||||
# marker for ignoring a comment to the end of the line
|
||||
@@ -71,11 +84,14 @@ StringComparer.OrdinalIgnoreCase\) \{.*\}
|
||||
# the last line of mimetype="application/x-microsoft.net.object.bytearray.base64" things in .resx files
|
||||
^\s*[-a-zA-Z=;:/0-9+]*[-a-zA-Z;:/0-9+][-a-zA-Z=;:/0-9+]*=$
|
||||
|
||||
# DateTime Formats
|
||||
Get-Date -Format \w+|DateTime\.Now(?::|\.ToString\(")\w+
|
||||
|
||||
# Automatically suggested patterns
|
||||
|
||||
# hit-count: 5402 file-count: 1339
|
||||
# IServiceProvider / isAThing
|
||||
(?:(?:\b|_|(?<=[a-z]))[IT]|(?:\b|_)(?:nsI|isA))(?=(?:[A-Z][a-z]{2,})+(?:[A-Z\d]|\b))
|
||||
(?:(?:\b|_|(?<=[a-z]))[A-Z]|(?:\b|_)(?:nsI|isA))(?=(?:[A-Z][a-z]{2,})+(?:[A-Z\d]|\b))
|
||||
|
||||
# hit-count: 2073 file-count: 842
|
||||
# #includes
|
||||
@@ -159,6 +175,10 @@ aka\.ms/[a-zA-Z0-9]+
|
||||
# kubernetes crd patterns
|
||||
^\s*pattern: .*$
|
||||
|
||||
# hit-count: 7 file-count: 3
|
||||
# unicode escaped characters (4)
|
||||
\\u[0-9a-fA-F]{4}
|
||||
|
||||
# hit-count: 5 file-count: 3
|
||||
# URL escaped characters
|
||||
%[0-9A-F][A-F](?=[A-Za-z])
|
||||
@@ -171,6 +191,10 @@ aka\.ms/[a-zA-Z0-9]+
|
||||
# medium
|
||||
\bmedium\.com/@?[^/\s"]+/[-\w:/*.]+
|
||||
|
||||
# hit-count: 2 file-count: 2
|
||||
# tar arguments
|
||||
\b(?:\\n|)g?tar(?:\.exe|)(?:\s-C \S+|(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+
|
||||
|
||||
# hit-count: 2 file-count: 1
|
||||
# While you could try to match `http://` and `https://` by using `s?` in `https?://`, sometimes there
|
||||
# YouTube url
|
||||
@@ -184,10 +208,6 @@ aka\.ms/[a-zA-Z0-9]+
|
||||
# curl arguments
|
||||
\b(?:\\n|)curl(?:\.exe|)(?:\s+-[a-zA-Z]{1,2}\b)*(?:\s+-[a-zA-Z]{3,})(?:\s+-[a-zA-Z]+)*
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# tar arguments
|
||||
\b(?:\\n|)g?tar(?:\.exe|)(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+
|
||||
|
||||
# #pragma lib
|
||||
^\s*#pragma comment\(lib, ".*?"\)
|
||||
|
||||
@@ -210,13 +230,15 @@ RegExp\(@?([`'"]).*?\g{-1}\)|(?:escapes|regEx):\s*(?:/.*/|([`'"]).*?\g{-1})|retu
|
||||
# mount
|
||||
\bmount\s+-t\s+(\w+)\s+\g{-1}\b
|
||||
# C types and repeated CSS values
|
||||
\s(auto|buffalo|center|div|inherit|long|LONG|none|normal|solid|thin|transparent|very)(?:\s\g{-1})+\s
|
||||
\s(auto|await|buffalo|center|div|inherit|long|LONG|none|normal|solid|thin|transparent|very)(?:\s\g{-1})+\s
|
||||
# C enum and struct
|
||||
\b(?:enum|struct)\s+(\w+)\s+\g{-1}\b
|
||||
# go templates
|
||||
\s(\w+)\s+\g{-1}\s+\`(?:graphql|inject|json|yaml):
|
||||
# doxygen / javadoc / .net
|
||||
(?:[\\@](?:brief|defgroup|groupname|link|t?param|return|retval)|(?:public|private|\[Parameter(?:\(.+\)|)\])(?:\s+(?:static|override|readonly|required|virtual))*)(?:\s+\{\w+\}|)\s+(\w+)\s+\g{-1}\s
|
||||
# C# getter/setter
|
||||
\s(\w+)\s+\g{-1}\s*\{\s*[gs]et;
|
||||
|
||||
# macOS file path
|
||||
(?:Contents\W+|(?!iOS)/)MacOS\b
|
||||
|
||||
47
.github/actions/spell-check/reject.txt
vendored
@@ -1,23 +1,30 @@
|
||||
^attache$
|
||||
^bellows?$
|
||||
attache
|
||||
aroynt.*
|
||||
bellows?
|
||||
benefitting
|
||||
occurences?
|
||||
^dependan.*
|
||||
^develope$
|
||||
^developement$
|
||||
^developpe
|
||||
^Devers?$
|
||||
^devex
|
||||
^devide
|
||||
^Devinn?[ae]
|
||||
^devisal
|
||||
^devisor
|
||||
^diables?$
|
||||
^oer$
|
||||
.*dnt
|
||||
dependan.*
|
||||
developement
|
||||
developp?e
|
||||
Devers?
|
||||
devex.*
|
||||
devide
|
||||
Devinn?[ae]
|
||||
devisals?
|
||||
devisors?
|
||||
diables?
|
||||
hasta?
|
||||
hastat.*
|
||||
immediatly
|
||||
inisle
|
||||
inital
|
||||
linge
|
||||
oer
|
||||
Sorce
|
||||
^[Ss]pae.*
|
||||
^Teh$
|
||||
^untill$
|
||||
^untilling$
|
||||
^venders?$
|
||||
^wether.*
|
||||
[Ss]pae.*
|
||||
Teh
|
||||
untill
|
||||
untilling
|
||||
venders?
|
||||
wether.*
|
||||
|
||||
@@ -16,7 +16,7 @@ For each CSV in `Generated Files/ReleaseNotes/grouped_csv/`, create a markdown f
|
||||
- Use the “Verb-ed + Scenario + Impact” sentence structure—make readers think, “That’s exactly what I need” or “Yes, that’s an awesome fix.”; The "impact" can be end-user focused (written to convey user excitement) or technical (performance/stability) when user-facing impact is minimal.
|
||||
- If nothing special on impact or unclear impact, mark as needing human summary
|
||||
- Source from Title, Body, and CopilotSummary (prefer CopilotSummary when available)
|
||||
- The `NeedThanks` column contains a comma-separated list of external contributor usernames who should be thanked (empty = no thanks needed, all authors are core team). For each non-empty `NeedThanks` value, append thanks for **every** listed contributor: `Thanks [@user1](https://github.com/user1)!` for a single contributor, or `Thanks [@user1](https://github.com/user1) and [@user2](https://github.com/user2)!` for two, or `Thanks [@user1](https://github.com/user1), [@user2](https://github.com/user2), and [@user3](https://github.com/user3)!` for three or more.
|
||||
- The `NeedThanks` column contains a comma-separated list of external contributor usernames who should be credited (empty = no attribution needed, all authors are core team). For each non-empty `NeedThanks` value, append a `by` attribution that lists **every** contributor, matching GitHub's standard contributor-attribution style: `by [@user1](https://github.com/user1)` for a single contributor, `by [@user1](https://github.com/user1) and [@user2](https://github.com/user2)` for two, or `by [@user1](https://github.com/user1), [@user2](https://github.com/user2), and [@user3](https://github.com/user3)` for three or more. In the final consolidated release notes (Step 4.2), the attribution follows the PR link, e.g. `…in [#1234](url) by [@user](url)`. Do not use "Thanks @user!" phrasing.
|
||||
- Do NOT include PR numbers in bullet lines
|
||||
- Do NOT mention “security” or “privacy” issues, since these are not known and could be leveraged by attackers in earlier versions. Instead, describe the user-facing scenario, usage, or impact.
|
||||
- If confidence < 70%, write: `Human Summary Needed: <PR full link>`
|
||||
|
||||
18
.github/workflows/spelling2.yml
vendored
@@ -55,7 +55,7 @@ name: Spell checking
|
||||
# spelling:
|
||||
# # remove `security-events: write` and `use_sarif: 1`
|
||||
# # remove `experimental_apply_changes_via_bot: 1`
|
||||
# ... otherwise adjust the `with:` as you wish
|
||||
# ... otherwise, adjust the `with:` as you wish
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -74,6 +74,8 @@ on:
|
||||
types:
|
||||
- "created"
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
spelling:
|
||||
name: Check Spelling
|
||||
@@ -85,7 +87,7 @@ jobs:
|
||||
outputs:
|
||||
followup: ${{ steps.spelling.outputs.followup }}
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ contains(github.event_name, 'pull_request') || github.event_name == 'push' }}
|
||||
if: ${{ (contains(github.event_name, 'pull_request') && github.event.pull_request.state == 'open') || github.event_name == 'push' }}
|
||||
concurrency:
|
||||
group: spelling-${{ github.event.pull_request.number || github.ref }}
|
||||
# note: If you use only_check_changed_files, you do not want cancel-in-progress
|
||||
@@ -140,7 +142,7 @@ jobs:
|
||||
comment-push:
|
||||
name: Report (Push)
|
||||
# If your workflow isn't running on push, you can remove this job
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-slim
|
||||
needs: spelling
|
||||
permissions:
|
||||
actions: read
|
||||
@@ -150,24 +152,21 @@ jobs:
|
||||
- name: comment
|
||||
uses: check-spelling/check-spelling@cfb6f7e75bbfc89c71eaa30366d0c166f1bd9c8c # v0.0.26
|
||||
with:
|
||||
spell_check_this: microsoft/PowerToys@main
|
||||
task: ${{ needs.spelling.outputs.followup }}
|
||||
|
||||
comment-pr:
|
||||
name: Report (PR)
|
||||
# If you workflow isn't running on pull_request*, you can remove this job
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-slim
|
||||
needs: spelling
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
pull-requests: write
|
||||
if: (success() || failure()) && needs.spelling.outputs.followup && contains(github.event_name, 'pull_request')
|
||||
steps:
|
||||
- name: comment
|
||||
uses: check-spelling/check-spelling@cfb6f7e75bbfc89c71eaa30366d0c166f1bd9c8c # v0.0.26
|
||||
with:
|
||||
spell_check_this: check-spelling/spell-check-this@prerelease
|
||||
task: ${{ needs.spelling.outputs.followup }}
|
||||
experimental_apply_changes_via_bot: ${{ github.repository_owner != 'microsoft' && 1 }}
|
||||
|
||||
@@ -177,12 +176,13 @@ jobs:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
actions: read
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-slim
|
||||
if: ${{
|
||||
github.repository_owner != 'microsoft' &&
|
||||
github.event_name == 'issue_comment' &&
|
||||
github.event.issue.pull_request &&
|
||||
contains(github.event.comment.body, '@check-spelling-bot apply') &&
|
||||
contains(github.event.comment.body, '@check-spelling-bot') &&
|
||||
contains(github.event.comment.body, 'apply') &&
|
||||
contains(github.event.comment.body, 'https://')
|
||||
}}
|
||||
concurrency:
|
||||
|
||||
6
.gitignore
vendored
@@ -365,6 +365,8 @@ installer/*/*.wxs.bk
|
||||
**/.claude/settings.local.json
|
||||
|
||||
# Squad / Copilot agents — local-only, not committed
|
||||
.squad/
|
||||
.copilot
|
||||
.squad
|
||||
.squad-workstream
|
||||
.github/agents/
|
||||
.github/agents/**squad**.md
|
||||
.github/workflows/**squad**.yml
|
||||
|
||||
@@ -26,94 +26,64 @@
|
||||
"PowerToys.Settings.UI.Lib.dll",
|
||||
"PowerToys.GPOWrapper.dll",
|
||||
"PowerToys.GPOWrapperProjection.dll",
|
||||
"PowerToys.AllExperiments.dll",
|
||||
"LanguageModelProvider.dll",
|
||||
|
||||
"Common.Search.dll",
|
||||
|
||||
"PowerToys.AlwaysOnTop.exe",
|
||||
"PowerToys.AlwaysOnTopModuleInterface.dll",
|
||||
|
||||
"PowerToys.CmdNotFoundModuleInterface.dll",
|
||||
|
||||
|
||||
"PowerToys.ColorPicker.dll",
|
||||
"PowerToys.ColorPickerUI.dll",
|
||||
"PowerToys.ColorPickerUI.exe",
|
||||
|
||||
"PowerToys.CropAndLockModuleInterface.dll",
|
||||
"PowerToys.CropAndLock.exe",
|
||||
|
||||
"PowerToys.PowerOCRModuleInterface.dll",
|
||||
"PowerToys.PowerOCR.dll",
|
||||
"PowerToys.PowerOCR.exe",
|
||||
|
||||
"PowerToys.AdvancedPasteModuleInterface.dll",
|
||||
"WinUI3Apps\\PowerToys.AdvancedPaste.exe",
|
||||
"WinUI3Apps\\PowerToys.AdvancedPaste.dll",
|
||||
|
||||
"PowerToys.AwakeModuleInterface.dll",
|
||||
"PowerToys.Awake.exe",
|
||||
"PowerToys.Awake.dll",
|
||||
|
||||
"PowerToys.FancyZonesEditor.exe",
|
||||
"PowerToys.FancyZonesEditor.dll",
|
||||
"PowerToys.FancyZonesEditorCommon.dll",
|
||||
"PowerToys.FancyZonesModuleInterface.dll",
|
||||
"PowerToys.FancyZones.exe",
|
||||
"FancyZonesCLI.exe",
|
||||
"FancyZonesCLI.dll",
|
||||
|
||||
"PowerToys.GcodePreviewHandler.dll",
|
||||
"PowerToys.GcodePreviewHandler.exe",
|
||||
"PowerToys.GcodePreviewHandlerCpp.dll",
|
||||
"PowerToys.GcodeThumbnailProvider.dll",
|
||||
"PowerToys.GcodeThumbnailProvider.exe",
|
||||
"PowerToys.GcodeThumbnailProviderCpp.dll",
|
||||
"PowerToys.BgcodePreviewHandler.dll",
|
||||
"PowerToys.BgcodePreviewHandler.exe",
|
||||
"PowerToys.BgcodePreviewHandlerCpp.dll",
|
||||
"PowerToys.BgcodeThumbnailProvider.dll",
|
||||
"PowerToys.BgcodeThumbnailProvider.exe",
|
||||
"PowerToys.BgcodeThumbnailProviderCpp.dll",
|
||||
"PowerToys.ManagedTelemetry.dll",
|
||||
"PowerToys.MarkdownPreviewHandler.dll",
|
||||
"PowerToys.MarkdownPreviewHandler.exe",
|
||||
"PowerToys.MarkdownPreviewHandlerCpp.dll",
|
||||
"PowerToys.MonacoPreviewHandler.dll",
|
||||
"PowerToys.MonacoPreviewHandler.exe",
|
||||
"PowerToys.MonacoPreviewHandlerCpp.dll",
|
||||
"PowerToys.PdfPreviewHandler.dll",
|
||||
"PowerToys.PdfPreviewHandler.exe",
|
||||
"PowerToys.PdfPreviewHandlerCpp.dll",
|
||||
"PowerToys.PdfThumbnailProvider.dll",
|
||||
"PowerToys.PdfThumbnailProvider.exe",
|
||||
"PowerToys.PdfThumbnailProviderCpp.dll",
|
||||
"PowerToys.powerpreview.dll",
|
||||
"PowerToys.PreviewHandlerCommon.dll",
|
||||
"PowerToys.QoiPreviewHandler.dll",
|
||||
"PowerToys.QoiPreviewHandler.exe",
|
||||
"PowerToys.QoiPreviewHandlerCpp.dll",
|
||||
"PowerToys.QoiThumbnailProvider.dll",
|
||||
"PowerToys.QoiThumbnailProvider.exe",
|
||||
"PowerToys.QoiThumbnailProviderCpp.dll",
|
||||
"PowerToys.StlThumbnailProvider.dll",
|
||||
"PowerToys.StlThumbnailProvider.exe",
|
||||
"PowerToys.StlThumbnailProviderCpp.dll",
|
||||
"PowerToys.SvgPreviewHandler.dll",
|
||||
"PowerToys.SvgPreviewHandler.exe",
|
||||
"PowerToys.SvgPreviewHandlerCpp.dll",
|
||||
"PowerToys.SvgThumbnailProvider.dll",
|
||||
"PowerToys.SvgThumbnailProvider.exe",
|
||||
"PowerToys.SvgThumbnailProviderCpp.dll",
|
||||
"PowerToys.KeyboardManager.dll",
|
||||
|
||||
"KeyboardManagerEditor\\PowerToys.KeyboardManagerEditor.exe",
|
||||
"WinUI3Apps\\PowerToys.KeyboardManagerEditorUI.exe",
|
||||
"WinUI3Apps\\PowerToys.KeyboardManagerEditorUI.dll",
|
||||
"KeyboardManagerEngine\\PowerToys.KeyboardManagerEngine.exe",
|
||||
"PowerToys.KeyboardManagerEditorLibraryWrapper.dll",
|
||||
"WinUI3Apps\\PowerToys.HostsModuleInterface.dll",
|
||||
"WinUI3Apps\\PowerToys.HostsUILib.dll",
|
||||
"WinUI3Apps\\PowerToys.Hosts.dll",
|
||||
"WinUI3Apps\\PowerToys.Hosts.exe",
|
||||
@@ -136,7 +106,6 @@
|
||||
"WinUI3Apps\\PowerToys.QuickAccess.exe",
|
||||
"WinUI3Apps\\PowerToys.Settings.UI.Controls.dll",
|
||||
|
||||
"WinUI3Apps\\PowerToys.EnvironmentVariablesModuleInterface.dll",
|
||||
"WinUI3Apps\\PowerToys.EnvironmentVariablesUILib.dll",
|
||||
"WinUI3Apps\\PowerToys.EnvironmentVariables.dll",
|
||||
"WinUI3Apps\\PowerToys.EnvironmentVariables.exe",
|
||||
@@ -149,7 +118,6 @@
|
||||
"WinUI3Apps\\PowerToys.ImageResizerContextMenu.dll",
|
||||
"WinUI3Apps\\ImageResizerContextMenuPackage.msix",
|
||||
|
||||
"PowerToys.LightSwitchModuleInterface.dll",
|
||||
"LightSwitchService\\PowerToys.LightSwitchService.exe",
|
||||
|
||||
"PowerToys.KeyboardManager.dll",
|
||||
@@ -185,7 +153,6 @@
|
||||
"RunPlugins\\WebSearch\\Community.PowerToys.Run.Plugin.WebSearch.dll",
|
||||
"RunPlugins\\WindowsTerminal\\Microsoft.PowerToys.Run.Plugin.WindowsTerminal.dll",
|
||||
|
||||
"WinUI3Apps\\PowerToys.MeasureToolModuleInterface.dll",
|
||||
"WinUI3Apps\\PowerToys.MeasureToolCore.dll",
|
||||
"WinUI3Apps\\PowerToys.MeasureToolUI.dll",
|
||||
"WinUI3Apps\\PowerToys.MeasureToolUI.exe",
|
||||
@@ -201,7 +168,6 @@
|
||||
|
||||
"PowerToys.MouseWithoutBorders.dll",
|
||||
"PowerToys.MouseWithoutBorders.exe",
|
||||
"PowerToys.MouseWithoutBordersModuleInterface.dll",
|
||||
"PowerToys.MouseWithoutBordersService.dll",
|
||||
"PowerToys.MouseWithoutBordersService.exe",
|
||||
"PowerToys.MouseWithoutBordersHelper.dll",
|
||||
@@ -214,7 +180,6 @@
|
||||
"PowerAccent.Core.dll",
|
||||
"PowerToys.PowerAccent.dll",
|
||||
"PowerToys.PowerAccent.exe",
|
||||
"PowerToys.PowerAccentModuleInterface.dll",
|
||||
"PowerToys.PowerAccentKeyboardService.dll",
|
||||
|
||||
"PowerToys.PowerDisplayModuleInterface.dll",
|
||||
@@ -235,7 +200,6 @@
|
||||
"PowerToys.WorkspacesEditor.dll",
|
||||
"PowerToys.WorkspacesLauncherUI.exe",
|
||||
"PowerToys.WorkspacesLauncherUI.dll",
|
||||
"PowerToys.WorkspacesModuleInterface.dll",
|
||||
"PowerToys.WorkspacesCsharpLibrary.dll",
|
||||
|
||||
"WinUI3Apps\\PowerToys.RegistryPreviewExt.dll",
|
||||
@@ -244,10 +208,8 @@
|
||||
"WinUI3Apps\\PowerToys.RegistryPreview.exe",
|
||||
|
||||
"PowerToys.ShortcutGuide.exe",
|
||||
"PowerToys.ShortcutGuideModuleInterface.dll",
|
||||
|
||||
"PowerToys.ZoomIt.exe",
|
||||
"PowerToys.ZoomItModuleInterface.dll",
|
||||
"PowerToys.ZoomItSettingsInterop.dll",
|
||||
|
||||
"PowerToys.GrabAndMove.exe",
|
||||
@@ -256,7 +218,6 @@
|
||||
"WinUI3Apps\\PowerToys.Settings.dll",
|
||||
"WinUI3Apps\\PowerToys.Settings.exe",
|
||||
|
||||
"PowerToys.CmdPalModuleInterface.dll",
|
||||
"CmdPalKeyboardService.dll",
|
||||
"PowerToys.ModuleContracts.dll",
|
||||
"Awake.ModuleServices.dll",
|
||||
@@ -264,8 +225,8 @@
|
||||
"Workspaces.ModuleServices.dll",
|
||||
"Microsoft.CommandPalette.Extensions.dll",
|
||||
"Microsoft.CommandPalette.Extensions.Toolkit.dll",
|
||||
"Microsoft.CmdPal.Ext.PowerToys.dll",
|
||||
"Microsoft.CmdPal.Ext.PowerToys.exe",
|
||||
"WinUI3Apps\\Microsoft.CmdPal.Ext.PowerToys.dll",
|
||||
"WinUI3Apps\\Microsoft.CmdPal.Ext.PowerToys.exe",
|
||||
"*Microsoft.CmdPal.UI_*.msix",
|
||||
|
||||
"PowerToys.DSC.dll",
|
||||
|
||||
3
.vscode/settings.json
vendored
@@ -13,5 +13,6 @@
|
||||
{
|
||||
"file": ".github/prompts/create-pr-summary.prompt.md"
|
||||
}
|
||||
]
|
||||
],
|
||||
"sarif-viewer.connectToGithubCodeScanning": "on"
|
||||
}
|
||||
@@ -8,6 +8,17 @@
|
||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Generate version data -->
|
||||
<Target Name="GenerateVersionData" BeforeTargets="PrepareForBuild">
|
||||
<ItemGroup>
|
||||
<HeaderLines Include="#pragma once" />
|
||||
<HeaderLines Include="#define VERSION_MAJOR $(Version.Split('.')[0])" />
|
||||
<HeaderLines Include="#define VERSION_MINOR $(Version.Split('.')[1])" />
|
||||
<HeaderLines Include="#define VERSION_REVISION $(Version.Split('.')[2])" />
|
||||
</ItemGroup>
|
||||
<WriteLinesToFile File="Generated Files\version_gen.h" Lines="@(HeaderLines)" Overwrite="true" Encoding="Unicode" WriteOnlyWhenDifferent="true" />
|
||||
</Target>
|
||||
|
||||
<!-- Project configurations -->
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
|
||||
384
PowerToys.slnx
@@ -9,15 +9,14 @@
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/common/Common.UI/Common.UI.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/common/Common.UI.Controls/Common.UI.Controls.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/common/COMUtils/COMUtils.vcxproj" Id="7319089e-46d6-4400-bc65-e39bdf1416ee" />
|
||||
<Project Path="src/common/Common.UI/Common.UI.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/common/Display/Display.vcxproj" Id="caba8dfb-823b-4bf2-93ac-3f31984150d9" />
|
||||
<Project Path="src/common/FilePreviewCommon/FilePreviewCommon.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
@@ -56,8 +55,6 @@
|
||||
</Project>
|
||||
<Project Path="src/common/UnitTests-CommonLib/UnitTests-CommonLib.vcxproj" Id="1a066c63-64b3-45f8-92fe-664e1cce8077" />
|
||||
<Project Path="src/common/UnitTests-CommonUtils/UnitTests-CommonUtils.vcxproj" Id="8b5cfb38-ccba-40a8-ad7a-89c57b070884" />
|
||||
<Project Path="src/common/updating/updating.vcxproj" Id="17da04df-e393-4397-9cf0-84dabe11032e" />
|
||||
<Project Path="src/common/version/version.vcxproj" Id="cc6e41ac-8174-4e8a-8d22-85dd7f4851df" />
|
||||
</Folder>
|
||||
<Folder Name="/common/interop/">
|
||||
<Project Path="src/common/interop/interop-tests/Common.Interop.UnitTests.csproj">
|
||||
@@ -107,7 +104,6 @@
|
||||
<File Path="src/common/utils/MsWindowsSettings.h" />
|
||||
<File Path="src/common/utils/OnThreadExecutor.h" />
|
||||
<File Path="src/common/utils/os-detect.h" />
|
||||
<File Path="src/common/utils/package.h" />
|
||||
<File Path="src/common/utils/ProcessWaiter.h" />
|
||||
<File Path="src/common/utils/process_path.h" />
|
||||
<File Path="src/common/utils/registry.h" />
|
||||
@@ -117,6 +113,7 @@
|
||||
<File Path="src/common/utils/string_utils.h" />
|
||||
<File Path="src/common/utils/timeutil.h" />
|
||||
<File Path="src/common/utils/UnhandledExceptionHandler.h" />
|
||||
<File Path="src/common/utils/version.h" />
|
||||
<File Path="src/common/utils/winapi_error.h" />
|
||||
<File Path="src/common/utils/window.h" />
|
||||
</Folder>
|
||||
@@ -144,7 +141,6 @@
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
<Deploy />
|
||||
</Project>
|
||||
<Project Path="src/modules/AdvancedPaste/AdvancedPasteModuleInterface/AdvancedPasteModuleInterface.vcxproj" Id="fc373b24-3293-453c-aaf5-cf2909dcee6a" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/AdvancedPaste/Tests/">
|
||||
<Project Path="src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/AdvancedPaste.FuzzTests.csproj">
|
||||
@@ -158,7 +154,6 @@
|
||||
</Folder>
|
||||
<Folder Name="/modules/AlwaysOnTop/">
|
||||
<Project Path="src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.vcxproj" Id="1dc3be92-ce89-43fb-8110-9c043a2fe7a2" />
|
||||
<Project Path="src/modules/alwaysontop/AlwaysOnTopModuleInterface/AlwaysOnTopModuleInterface.vcxproj" Id="48a0a19e-a0be-4256-acf8-cc3b80291af9" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/awake/">
|
||||
<Project Path="src/modules/awake/Awake.ModuleServices/Awake.ModuleServices.csproj">
|
||||
@@ -169,19 +164,12 @@
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/awake/AwakeModuleInterface/AwakeModuleInterface.vcxproj" Id="5e7360a8-d048-4ed3-8f09-0bfd64c5529a" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/cmdNotFound/">
|
||||
<Project Path="src/modules/cmdNotFound/CmdNotFoundModuleInterface/CmdNotFoundModuleInterface.vcxproj" Id="0014d652-901f-4456-8d65-06fc5f997fb0" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/colorpicker/">
|
||||
<Project Path="src/modules/colorPicker/ColorPicker.ModuleServices/ColorPicker.ModuleServices.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/colorPicker/ColorPicker/ColorPicker.vcxproj" Id="655c9af2-18d3-4da6-80e4-85504a7722ba">
|
||||
<BuildDependency Project="src/common/logger/logger.vcxproj" />
|
||||
</Project>
|
||||
<Project Path="src/modules/colorPicker/ColorPickerUI/ColorPickerUI.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
@@ -195,7 +183,6 @@
|
||||
</Folder>
|
||||
<Folder Name="/modules/CommandPalette/">
|
||||
<Project Path="src/modules/cmdpal/CmdPalKeyboardService/CmdPalKeyboardService.vcxproj" Id="5f63c743-f6ce-4dba-a200-2b3f8a14e8c2" />
|
||||
<Project Path="src/modules/cmdpal/CmdPalModuleInterface/CmdPalModuleInterface.vcxproj" Id="0adeb797-c8c7-4ffa-acd5-2af6cad7ecd8" />
|
||||
<Project Path="src/modules/cmdpal/Microsoft.CmdPal.Common/Microsoft.CmdPal.Common.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
@@ -319,6 +306,10 @@
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.Indexer.UnitTests/Microsoft.CmdPal.Ext.Indexer.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/cmdpal/Tests/Microsoft.CmdPal.Ext.Registry.UnitTests/Microsoft.CmdPal.Ext.Registry.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
@@ -378,14 +369,12 @@
|
||||
</Folder>
|
||||
<Folder Name="/modules/CropAndLock/">
|
||||
<Project Path="src/modules/CropAndLock/CropAndLock/CropAndLock.vcxproj" Id="f5e1146e-b7b3-4e11-85fd-270a500bd78c" />
|
||||
<Project Path="src/modules/CropAndLock/CropAndLockModuleInterface/CropAndLockModuleInterface.vcxproj" Id="3157fa75-86cf-4ee2-8f62-c43f776493c6" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/EnvironmentVariables/">
|
||||
<Project Path="src/modules/EnvironmentVariables/EnvironmentVariables/EnvironmentVariables.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/EnvironmentVariables/EnvironmentVariablesModuleInterface/EnvironmentVariablesModuleInterface.vcxproj" Id="b9420661-b0e4-4241-abd4-4a27a1f64250" />
|
||||
<Project Path="src/modules/EnvironmentVariables/EnvironmentVariablesUILib/EnvironmentVariablesUILib.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/fancyzones/">
|
||||
@@ -403,7 +392,6 @@
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj" Id="f9c68edf-ac74-4b77-9af1-005d9c9f6a99" />
|
||||
<Project Path="src/modules/fancyzones/FancyZonesModuleInterface/FancyZonesModuleInterface.vcxproj" Id="48804216-2a0e-4168-a6d8-9cd068d14227" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/fancyzones/Tests/">
|
||||
<Project Path="src/modules/fancyzones/FancyZones.FuzzTests/FancyZones.FuzzTests.csproj">
|
||||
@@ -426,6 +414,119 @@
|
||||
<BuildDependency Project="src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj" />
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/File Explorer/">
|
||||
<Project Path="src/modules/previewpane/BgcodePreviewHandler/BgcodePreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/BgcodeThumbnailProvider/BgcodeThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/Common/PreviewHandlerCommon.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/FileExplorerDllExporter/FileExplorerDllExporter.vcxproj" Id="f6088a11-1c9e-4420-aa90-cf7e78dd7f1c" />
|
||||
<Project Path="src/modules/previewpane/GcodePreviewHandler/GcodePreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/GcodeThumbnailProvider/GcodeThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/MarkdownPreviewHandler/MarkdownPreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/MonacoPreviewHandler/MonacoPreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/PdfPreviewHandler/PdfPreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/PdfThumbnailProvider/PdfThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/QoiPreviewHandler/QoiPreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/QoiThumbnailProvider/QoiThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/StlThumbnailProvider/StlThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/SvgPreviewHandler/SvgPreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/SvgThumbnailProvider/SvgThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/File Explorer/Tests/">
|
||||
<Project Path="src/modules/previewpane/UnitTests-BgcodePreviewHandler/Preview.BgcodePreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-BgcodeThumbnailProvider/Preview.BgcodeThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-GcodePreviewHandler/Preview.GcodePreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-GcodeThumbnailProvider/Preview.GcodeThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-MarkdownPreviewHandler/Preview.MarkdownPreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-PdfPreviewHandler/Preview.PdfPreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-PdfThumbnailProvider/Preview.PdfThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-PreviewHandlerCommon/Preview.PreviewHandlerCommon.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-QoiPreviewHandler/Preview.QoiPreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-QoiThumbnailProvider/Preview.QoiThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-StlThumbnailProvider/Preview.StlThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-SvgPreviewHandler/Preview.SvgPreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-SvgThumbnailProvider/Preview.SvgThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/FileLocksmith/">
|
||||
<Project Path="src/modules/FileLocksmith/FileLocksmithCLI/FileLocksmithCLI.vcxproj" Id="49d456d3-f485-45af-8875-45b44f193ddc" />
|
||||
<Project Path="src/modules/FileLocksmith/FileLocksmithContextMenu/FileLocksmithContextMenu.vcxproj" Id="799a50d8-de89-4ed1-8ff8-ad5a9ed8c0ca" />
|
||||
@@ -445,7 +546,6 @@
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/Hosts/HostsModuleInterface/HostsModuleInterface.vcxproj" Id="b41b888c-7db8-4747-b262-4062e05a230d" />
|
||||
<Project Path="src/modules/Hosts/HostsUILib/HostsUILib.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/Hosts/Tests/">
|
||||
@@ -481,12 +581,8 @@
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/interface/">
|
||||
<File Path="src/modules/interface/powertoy_module_interface.h" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/keyboardmanager/">
|
||||
<Project Path="src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj" Id="8affa899-0b73-49ec-8c50-0fadda57b2fc" />
|
||||
<Project Path="src/modules/keyboardmanager/dll/KeyboardManager.vcxproj" Id="89f34af7-1c34-4a72-aa6e-534bcf972bd9" />
|
||||
<Project Path="src/modules/keyboardmanager/KeyboardManagerEditor/KeyboardManagerEditor.vcxproj" Id="8df78b53-200e-451f-9328-01eb907193ae" />
|
||||
<Project Path="src/modules/keyboardmanager/KeyboardManagerEditorLibrary/KeyboardManagerEditorLibrary.vcxproj" Id="23d2070d-e4ad-4add-85a7-083d9c76ad49" />
|
||||
<Project Path="src/modules/keyboardmanager/KeyboardManagerEditorLibraryWrapper/KeyboardManagerEditorLibraryWrapper.vcxproj" Id="4382a954-179a-4078-92af-715187dfff50" />
|
||||
@@ -497,39 +593,11 @@
|
||||
<Project Path="src/modules/keyboardmanager/KeyboardManagerEngine/KeyboardManagerEngine.vcxproj" Id="ba661f5b-1d5a-4ffc-9bf1-fc39df280bdd" />
|
||||
<Project Path="src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardManagerEngineLibrary.vcxproj" Id="e496b7fc-1e99-4bab-849b-0e8367040b02" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/MouseUtils/">
|
||||
<Project Path="src/modules/MouseUtils/CursorWrap/CursorWrap.vcxproj" Id="48a1db8c-5df8-4fb3-9e14-2b67f3f2d8b5" />
|
||||
<Project Path="src/modules/MouseUtils/FindMyMouse/FindMyMouse.vcxproj" Id="e94fd11c-0591-456f-899f-efc0ca548336" />
|
||||
<Project Path="src/modules/MouseUtils/MouseHighlighter/MouseHighlighter.vcxproj" Id="782a61be-9d85-4081-b35c-1ccc9dcc1e88" />
|
||||
<Project Path="src/modules/MouseUtils/MouseJump.Common/MouseJump.Common.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/MouseUtils/MouseJump/MouseJump.vcxproj" Id="8a08d663-4995-40e3-b42c-3f910625f284" />
|
||||
<Project Path="src/modules/MouseUtils/MouseJumpUI/MouseJumpUI.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/MouseUtils/MousePointerCrosshairs/MousePointerCrosshairs.vcxproj" Id="eae14c0e-7a6b-45da-9080-a7d8c077ba6e" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/MouseUtils/Tests/">
|
||||
<Project Path="src/modules/MouseUtils/MouseJump.Common.UnitTests/MouseJump.Common.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/MouseUtils/MouseUtils.UITests/MouseUtils.UITests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/keyboardmanager/Tests/">
|
||||
<Project Path="src/modules/keyboardmanager/KeyboardManagerEditorTest/KeyboardManagerEditorTest.vcxproj" Id="62173d9a-6724-4c00-a1c8-fb646480a9ec" />
|
||||
<Project Path="src/modules/keyboardmanager/KeyboardManagerEngineTest/KeyboardManagerEngineTest.vcxproj" Id="7f4b3a60-bc27-45a7-8000-68b0b6ea7466" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/launcher/">
|
||||
<Project Path="src/modules/launcher/Microsoft.Launcher/Microsoft.Launcher.vcxproj" Id="e364f67b-bb12-4e91-b639-355866ebcd8b">
|
||||
<BuildDependency Project="src/modules/launcher/PowerLauncher/PowerLauncher.csproj" />
|
||||
</Project>
|
||||
<Project Path="src/modules/launcher/PowerLauncher.Telemetry/PowerLauncher.Telemetry.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
@@ -697,8 +765,6 @@
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/LightSwitch/">
|
||||
<Project Path="src/modules/LightSwitch/LightSwitchLib/LightSwitchLib.vcxproj" Id="79267138-2895-4346-9021-21408d65379f" />
|
||||
<Project Path="src/modules/LightSwitch/LightSwitchModuleInterface/LightSwitchModuleInterface.vcxproj" Id="38177d56-6ad1-4adf-88c9-2843a7932166" />
|
||||
<Project Path="src/modules/LightSwitch/LightSwitchService/LightSwitchService.vcxproj" Id="08e71c67-6a7e-4ca1-b04e-2fb336410bac" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/LightSwitch/Tests/">
|
||||
@@ -721,7 +787,6 @@
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/powerdisplay/PowerDisplayModuleInterface/PowerDisplayModuleInterface.vcxproj" Id="d1234567-8901-2345-6789-abcdef012345" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/PowerDisplay/Tests/">
|
||||
<Project Path="src/modules/powerdisplay/PowerDisplay.Lib.UnitTests/PowerDisplay.Lib.UnitTests.csproj">
|
||||
@@ -733,9 +798,7 @@
|
||||
<Project Path="src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.vcxproj" Id="54a93af7-60c7-4f6c-99d2-fbb1f75f853a">
|
||||
<BuildDependency Project="src/common/Display/Display.vcxproj" />
|
||||
<BuildDependency Project="src/common/SettingsAPI/SettingsAPI.vcxproj" />
|
||||
<BuildDependency Project="src/common/version/version.vcxproj" />
|
||||
</Project>
|
||||
<Project Path="src/modules/MeasureTool/MeasureToolModuleInterface/MeasureToolModuleInterface.vcxproj" Id="92c39820-9f84-4529-bc7d-22aae514d63b" />
|
||||
<Project Path="src/modules/MeasureTool/MeasureToolUI/MeasureToolUI.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
@@ -747,6 +810,30 @@
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/MouseUtils/">
|
||||
<Project Path="src/modules/MouseUtils/CursorWrap/CursorWrap.vcxproj" Id="48a1db8c-5df8-4fb3-9e14-2b67f3f2d8b5" />
|
||||
<Project Path="src/modules/MouseUtils/FindMyMouse/FindMyMouse.vcxproj" Id="e94fd11c-0591-456f-899f-efc0ca548336" />
|
||||
<Project Path="src/modules/MouseUtils/MouseHighlighter/MouseHighlighter.vcxproj" Id="782a61be-9d85-4081-b35c-1ccc9dcc1e88" />
|
||||
<Project Path="src/modules/MouseUtils/MouseJump.Common/MouseJump.Common.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/MouseUtils/MouseJumpUI/MouseJumpUI.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/MouseUtils/MousePointerCrosshairs/MousePointerCrosshairs.vcxproj" Id="eae14c0e-7a6b-45da-9080-a7d8c077ba6e" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/MouseUtils/Tests/">
|
||||
<Project Path="src/modules/MouseUtils/MouseJump.Common.UnitTests/MouseJump.Common.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/MouseUtils/MouseUtils.UITests/MouseUtils.UITests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/MouseWithoutBorders/">
|
||||
<Project Path="src/modules/MouseWithoutBorders/App/Helper/MouseWithoutBordersHelper.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
@@ -760,7 +847,6 @@
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/MouseWithoutBorders/ModuleInterface/MouseWithoutBordersModuleInterface.vcxproj" Id="2833c9c6-ab32-4048-a5c7-a70898337b57" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/MouseWithoutBorders/Tests/">
|
||||
<Project Path="src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/MouseWithoutBorders.UnitTests.csproj">
|
||||
@@ -802,14 +888,12 @@
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/poweraccent/PowerAccentKeyboardService/PowerAccentKeyboardService.vcxproj" Id="c97d9a5d-206c-454e-997e-009e227d7f02" />
|
||||
<Project Path="src/modules/poweraccent/PowerAccentModuleInterface/PowerAccentModuleInterface.vcxproj" Id="34a354c5-23c7-4343-916c-c52daf4fc39d" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/PowerOCR/">
|
||||
<Project Path="src/modules/PowerOCR/PowerOCR/PowerOCR.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/PowerOCR/PowerOCRModuleInterface/PowerOCRModuleInterface.vcxproj" Id="6ab6a2d6-f859-4a82-9184-0bd29c9f07d1" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/PowerOCR/Tests/">
|
||||
<Project Path="src/modules/PowerOCR/PowerOCR-UITests/PowerOCR.UITests.csproj">
|
||||
@@ -839,140 +923,11 @@
|
||||
<BuildDependency Project="src/modules/powerrename/lib/PowerRenameLib.vcxproj" />
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/previewpane/">
|
||||
<Project Path="src/modules/previewpane/BgcodePreviewHandler/BgcodePreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/BgcodePreviewHandlerCpp/BgcodePreviewHandlerCpp.vcxproj" Id="f6088a11-1c9e-4420-aa90-cf7e78dd7f1c" />
|
||||
<Project Path="src/modules/previewpane/BgcodeThumbnailProvider/BgcodeThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/BgcodeThumbnailProviderCpp/BgcodeThumbnailProviderCpp.vcxproj" Id="47b0678c-806b-4fe1-9f50-46ba88989532" />
|
||||
<Project Path="src/modules/previewpane/Common/PreviewHandlerCommon.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/GcodePreviewHandler/GcodePreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/GcodePreviewHandlerCpp/GcodePreviewHandlerCpp.vcxproj" Id="5a5dd09d-723a-44d3-8f2b-293584c3d731" />
|
||||
<Project Path="src/modules/previewpane/GcodeThumbnailProvider/GcodeThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/GcodeThumbnailProviderCpp/GcodeThumbnailProviderCpp.vcxproj" Id="56cc2f10-6e41-453d-be16-c593a5e58482" />
|
||||
<Project Path="src/modules/previewpane/MarkdownPreviewHandler/MarkdownPreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/MarkdownPreviewHandlerCpp/MarkdownPreviewHandlerCpp.vcxproj" Id="ed9a1ac6-aeb0-4569-a6e9-e1696182b545" />
|
||||
<Project Path="src/modules/previewpane/MonacoPreviewHandler/MonacoPreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/MonacoPreviewHandlerCpp/MonacoPreviewHandlerCpp.vcxproj" Id="b3e869c4-8210-4ebd-a621-ff4c4afcbfa9" />
|
||||
<Project Path="src/modules/previewpane/PdfPreviewHandler/PdfPreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/PdfPreviewHandlerCpp/PdfPreviewHandlerCpp.vcxproj" Id="54f7c616-fd41-4e62-bff9-015686914f4d" />
|
||||
<Project Path="src/modules/previewpane/PdfThumbnailProvider/PdfThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/PdfThumbnailProviderCpp/PdfThumbnailProviderCpp.vcxproj" Id="ca5518ed-0458-4b09-8f53-4122b9888655" />
|
||||
<Project Path="src/modules/previewpane/powerpreview/powerpreview.vcxproj" Id="217df501-135c-4e38-bfc8-99d4821032ea">
|
||||
<BuildDependency Project="src/common/version/version.vcxproj" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/QoiPreviewHandler/QoiPreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/QoiPreviewHandlerCpp/QoiPreviewHandlerCpp.vcxproj" Id="3baf9c81-a194-4925-a035-5e24a5d1e542" />
|
||||
<Project Path="src/modules/previewpane/QoiThumbnailProvider/QoiThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/QoiThumbnailProviderCpp/QoiThumbnailProviderCpp.vcxproj" Id="ccb5e44f-84d9-4203-83c6-1c9ec9302bc7" />
|
||||
<Project Path="src/modules/previewpane/StlThumbnailProvider/StlThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/StlThumbnailProviderCpp/StlThumbnailProviderCpp.vcxproj" Id="d6dcc3ae-18c0-488a-b978-baa9e3cff09d" />
|
||||
<Project Path="src/modules/previewpane/SvgPreviewHandler/SvgPreviewHandler.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/SvgPreviewHandlerCpp/SvgPreviewHandlerCpp.vcxproj" Id="143f13e3-d2e3-4d83-b035-356612d99956" />
|
||||
<Project Path="src/modules/previewpane/SvgThumbnailProvider/SvgThumbnailProvider.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/SvgThumbnailProviderCpp/SvgThumbnailProviderCpp.vcxproj" Id="2bbc9e33-21ec-401c-84da-bb6590a9b2aa" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/previewpane/Tests/">
|
||||
<Project Path="src/modules/previewpane/UnitTests-BgcodePreviewHandler/Preview.BgcodePreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-BgcodeThumbnailProvider/Preview.BgcodeThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-GcodePreviewHandler/Preview.GcodePreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-GcodeThumbnailProvider/Preview.GcodeThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-MarkdownPreviewHandler/Preview.MarkdownPreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-PdfPreviewHandler/Preview.PdfPreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-PdfThumbnailProvider/Preview.PdfThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-PreviewHandlerCommon/Preview.PreviewHandlerCommon.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-QoiPreviewHandler/Preview.QoiPreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-QoiThumbnailProvider/Preview.QoiThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-StlThumbnailProvider/Preview.StlThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-SvgPreviewHandler/Preview.SvgPreviewHandler.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/previewpane/UnitTests-SvgThumbnailProvider/Preview.SvgThumbnailProvider.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/RegistryPreview/">
|
||||
<Project Path="src/modules/registrypreview/RegistryPreview/RegistryPreview.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/registrypreview/RegistryPreviewExt/RegistryPreviewExt.vcxproj" Id="697c6af9-0a48-49a9-866c-67da12384015" />
|
||||
<Project Path="src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewUILib.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/RegistryPreview/Test/">
|
||||
@@ -983,7 +938,6 @@
|
||||
</Folder>
|
||||
<Folder Name="/modules/shortcutguide/">
|
||||
<Project Path="src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.vcxproj" Id="2edb3eb4-fa92-4bff-b2d8-566584837231" />
|
||||
<Project Path="src/modules/ShortcutGuide/ShortcutGuideModuleInterface/ShortcutGuideModuleInterface.vcxproj" Id="2d604c07-51fc-46bb-9eb7-75aecc7f5e81" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/Workspaces/">
|
||||
<Project Path="src/modules/Workspaces/Workspaces.ModuleServices/Workspaces.ModuleServices.csproj">
|
||||
@@ -1004,7 +958,6 @@
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/Workspaces/WorkspacesLib/WorkspacesLib.vcxproj" Id="b31fcc55-b5a4-4ea7-b414-2dceae6af332" />
|
||||
<Project Path="src/modules/Workspaces/WorkspacesModuleInterface/WorkspacesModuleInterface.vcxproj" Id="45285df2-9742-4eca-9ac9-58951fc26489" />
|
||||
<Project Path="src/modules/Workspaces/WorkspacesSnapshotTool/WorkspacesSnapshotTool.vcxproj" Id="3d63307b-9d27-44fd-b033-b26f39245b85" />
|
||||
<Project Path="src/modules/Workspaces/WorkspacesWindowArranger/WorkspacesWindowArranger.vcxproj" Id="37d07516-4185-43a4-924f-3c7a5d95ecf6" />
|
||||
</Folder>
|
||||
@@ -1033,7 +986,6 @@
|
||||
<BuildDependency Project="src/modules/ZoomIt/ZoomItBreak/ZoomItBreak.vcxproj" />
|
||||
</Project>
|
||||
<Project Path="src/modules/ZoomIt/ZoomItBreak/ZoomItBreak.vcxproj" Id="94ba3051-c8d7-454a-9d46-1a7c78e228a3" />
|
||||
<Project Path="src/modules/ZoomIt/ZoomItModuleInterface/ZoomItModuleInterface.vcxproj" Id="e4585179-2ac1-4d5f-a3ff-cfc5392f694c" />
|
||||
<Project Path="src/modules/ZoomIt/ZoomItSettingsInterop/ZoomItSettingsInterop.vcxproj" Id="ca7d8106-30b9-4aec-9d05-b69b31b8c461" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/GrabAndMove/">
|
||||
@@ -1082,39 +1034,17 @@
|
||||
<File Path="src/Solution.props" />
|
||||
<File Path="src/Version.props" />
|
||||
</Folder>
|
||||
<Project Path="src/ActionRunner/ActionRunner.vcxproj" Id="d29ddd63-e2cf-4657-9fd5-2aede4257e5d">
|
||||
<BuildDependency Project="src/common/updating/updating.vcxproj" />
|
||||
</Project>
|
||||
<Project Path="src/PackageIdentity/PackageIdentity.vcxproj" Id="e2a5a82e-1e5b-4c8d-9a4f-2b1a8f9e5c3d" />
|
||||
<Project Path="src/runner/runner.vcxproj" Id="9412d5c6-2cf2-4fc2-a601-b55508ea9b27">
|
||||
<BuildDependency Project="src/ActionRunner/ActionRunner.vcxproj" />
|
||||
<BuildDependency Project="src/common/notifications/BackgroundActivator/BackgroundActivator.vcxproj" />
|
||||
<BuildDependency Project="src/common/notifications/BackgroundActivatorDLL/BackgroundActivatorDLL.vcxproj" />
|
||||
<BuildDependency Project="src/common/updating/updating.vcxproj" />
|
||||
<BuildDependency Project="src/modules/awake/Awake/Awake.csproj" />
|
||||
<BuildDependency Project="src/modules/awake/AwakeModuleInterface/AwakeModuleInterface.vcxproj" />
|
||||
<BuildDependency Project="src/modules/colorPicker/ColorPicker/ColorPicker.vcxproj" />
|
||||
<BuildDependency Project="src/modules/colorPicker/ColorPickerUI/ColorPickerUI.csproj" />
|
||||
<BuildDependency Project="src/modules/fancyzones/editor/FancyZonesEditor/FancyZonesEditor.csproj" />
|
||||
<BuildDependency Project="src/modules/fancyzones/FancyZonesLib/FancyZonesLib.vcxproj" />
|
||||
<BuildDependency Project="src/modules/fancyzones/FancyZonesModuleInterface/FancyZonesModuleInterface.vcxproj" />
|
||||
<BuildDependency Project="src/modules/imageresizer/dll/ImageResizerExt.vcxproj" />
|
||||
<BuildDependency Project="src/modules/imageresizer/ui/ImageResizerUI.csproj" />
|
||||
<BuildDependency Project="src/modules/keyboardmanager/dll/KeyboardManager.vcxproj" />
|
||||
<BuildDependency Project="src/modules/launcher/Microsoft.Launcher/Microsoft.Launcher.vcxproj" />
|
||||
<BuildDependency Project="src/modules/LightSwitch/LightSwitchModuleInterface/LightSwitchModuleInterface.vcxproj" />
|
||||
<BuildDependency Project="src/modules/LightSwitch/LightSwitchService/LightSwitchService.vcxproj" />
|
||||
<BuildDependency Project="src/modules/GrabAndMove/GrabAndMoveModuleInterface/GrabAndMoveModuleInterface.vcxproj" />
|
||||
<BuildDependency Project="src/modules/GrabAndMove/GrabAndMove/GrabAndMove.vcxproj" />
|
||||
<BuildDependency Project="src/modules/powerrename/dll/PowerRenameExt.vcxproj" />
|
||||
<BuildDependency Project="src/modules/powerrename/lib/PowerRenameLib.vcxproj" />
|
||||
<BuildDependency Project="src/modules/previewpane/Common/PreviewHandlerCommon.csproj" />
|
||||
<BuildDependency Project="src/modules/previewpane/MarkdownPreviewHandler/MarkdownPreviewHandler.csproj" />
|
||||
<BuildDependency Project="src/modules/previewpane/PdfPreviewHandler/PdfPreviewHandler.csproj" />
|
||||
<BuildDependency Project="src/modules/previewpane/powerpreview/powerpreview.vcxproj" />
|
||||
<BuildDependency Project="src/modules/previewpane/SvgPreviewHandler/SvgPreviewHandler.csproj" />
|
||||
<BuildDependency Project="src/PackageIdentity/PackageIdentity.vcxproj" />
|
||||
<Project Path="src/PowerToys.ActionRunner/PowerToys.ActionRunner.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/Runner/RunnerV2.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/Update/Update.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/Update/PowerToys.Update.vcxproj" Id="44ce9ae1-4390-42c5-bacc-0fd6b40aa203" />
|
||||
<Project Path="tools/project_template/ModuleTemplate/ModuleTemplateCompileTest.vcxproj" Id="64a80062-4d8b-4229-8a38-dfa1d7497749" />
|
||||
</Solution>
|
||||
|
||||
14
README.md
@@ -29,13 +29,13 @@ PowerToys includes over 30 utilities to help you customize and optimize your Win
|
||||
| [<img src="doc/images/icons/AdvancedPaste.png" alt="Advanced Paste icon" height="16"> Advanced Paste](https://aka.ms/PowerToysOverview_AdvancedPaste) | [<img src="doc/images/icons/Always%20On%20Top.png" alt="Always on Top icon" height="16"> Always on Top](https://aka.ms/PowerToysOverview_AoT) | [<img src="doc/images/icons/Awake.png" alt="Awake icon" height="16"> Awake](https://aka.ms/PowerToysOverview_Awake) |
|
||||
| [<img src="doc/images/icons/Color%20Picker.png" alt="Color Picker icon" height="16"> Color Picker](https://aka.ms/PowerToysOverview_ColorPicker) | [<img src="doc/images/icons/Command%20Not%20Found.png" alt="Command Not Found icon" height="16"> Command Not Found](https://aka.ms/PowerToysOverview_CmdNotFound) | [<img src="doc/images/icons/Command Palette.png" alt="Command Palette icon" height="16"> Command Palette](https://aka.ms/PowerToysOverview_CmdPal) |
|
||||
| [<img src="doc/images/icons/Crop%20And%20Lock.png" alt="Crop and Lock icon" height="16"> Crop And Lock](https://aka.ms/PowerToysOverview_CropAndLock) | [<img src="doc/images/icons/Environment%20Manager.png" alt="Environment Variables icon" height="16"> Environment Variables](https://aka.ms/PowerToysOverview_EnvironmentVariables) | [<img src="doc/images/icons/FancyZones.png" alt="FancyZones icon" height="16"> FancyZones](https://aka.ms/PowerToysOverview_FancyZones) |
|
||||
| [<img src="doc/images/icons/File%20Explorer%20Preview.png" alt="File Explorer Add-ons icon" height="16"> File Explorer Add-ons](https://aka.ms/PowerToysOverview_FileExplorerAddOns) | [<img src="doc/images/icons/File%20Locksmith.png" alt="File Locksmith icon" height="16"> File Locksmith](https://aka.ms/PowerToysOverview_FileLocksmith) | [<img src="doc/images/icons/Host%20File%20Editor.png" alt="Hosts File Editor icon" height="16"> Hosts File Editor](https://aka.ms/PowerToysOverview_HostsFileEditor) |
|
||||
| [<img src="doc/images/icons/Image%20Resizer.png" alt="Image Resizer icon" height="16"> Image Resizer](https://aka.ms/PowerToysOverview_ImageResizer) | [<img src="doc/images/icons/Keyboard%20Manager.png" alt="Keyboard Manager icon" height="16"> Keyboard Manager](https://aka.ms/PowerToysOverview_KeyboardManager) | [<img src="doc/images/icons/Light Switch.png" alt="Light Switch icon" height="16"> Light Switch](https://aka.ms/PowerToysOverview_LightSwitch) |
|
||||
| [<img src="doc/images/icons/Find My Mouse.png" alt="Mouse Utilities icon" height="16"> Mouse Utilities](https://aka.ms/PowerToysOverview_MouseUtilities) | [<img src="doc/images/icons/MouseWithoutBorders.png" alt="Mouse Without Borders icon" height="16"> Mouse Without Borders](https://aka.ms/PowerToysOverview_MouseWithoutBorders) | [<img src="doc/images/icons/NewPlus.png" alt="New+ icon" height="16"> New+](https://aka.ms/PowerToysOverview_NewPlus) |
|
||||
| [<img src="doc/images/icons/Peek.png" alt="Peek icon" height="16"> Peek](https://aka.ms/PowerToysOverview_Peek) | [<img src="doc/images/icons/PowerRename.png" alt="PowerRename icon" height="16"> PowerRename](https://aka.ms/PowerToysOverview_PowerRename) | [<img src="doc/images/icons/PowerToys%20Run.png" alt="PowerToys Run icon" height="16"> PowerToys Run](https://aka.ms/PowerToysOverview_PowerToysRun) |
|
||||
| [<img src="doc/images/icons/PowerAccent.png" alt="Quick Accent icon" height="16"> Quick Accent](https://aka.ms/PowerToysOverview_QuickAccent) | [<img src="doc/images/icons/Registry%20Preview.png" alt="Registry Preview icon" height="16"> Registry Preview](https://aka.ms/PowerToysOverview_RegistryPreview) | [<img src="doc/images/icons/MeasureTool.png" alt="Screen Ruler icon" height="16"> Screen Ruler](https://aka.ms/PowerToysOverview_ScreenRuler) |
|
||||
| [<img src="doc/images/icons/Shortcut%20Guide.png" alt="Shortcut Guide icon" height="16"> Shortcut Guide](https://aka.ms/PowerToysOverview_ShortcutGuide) | [<img src="doc/images/icons/PowerOCR.png" alt="Text Extractor icon" height="16"> Text Extractor](https://aka.ms/PowerToysOverview_TextExtractor) | [<img src="doc/images/icons/Workspaces.png" alt="Workspaces icon" height="16"> Workspaces](https://aka.ms/PowerToysOverview_Workspaces) |
|
||||
| [<img src="doc/images/icons/ZoomIt.png" alt="ZoomIt icon" height="16"> ZoomIt](https://aka.ms/PowerToysOverview_ZoomIt) | | |
|
||||
| [<img src="doc/images/icons/File%20Explorer%20Preview.png" alt="File Explorer Add-ons icon" height="16"> File Explorer Add-ons](https://aka.ms/PowerToysOverview_FileExplorerAddOns) | [<img src="doc/images/icons/File%20Locksmith.png" alt="File Locksmith icon" height="16"> File Locksmith](https://aka.ms/PowerToysOverview_FileLocksmith) | [<img src="doc/images/icons/GrabAndMove.png" alt="Grab And Move icon" height="16"> Grab And Move](https://aka.ms/PowerToysOverview_GrabAndMove) |
|
||||
| [<img src="doc/images/icons/Host%20File%20Editor.png" alt="Hosts File Editor icon" height="16"> Hosts File Editor](https://aka.ms/PowerToysOverview_HostsFileEditor) | [<img src="doc/images/icons/Image%20Resizer.png" alt="Image Resizer icon" height="16"> Image Resizer](https://aka.ms/PowerToysOverview_ImageResizer) | [<img src="doc/images/icons/Keyboard%20Manager.png" alt="Keyboard Manager icon" height="16"> Keyboard Manager](https://aka.ms/PowerToysOverview_KeyboardManager) |
|
||||
| [<img src="doc/images/icons/Light Switch.png" alt="Light Switch icon" height="16"> Light Switch](https://aka.ms/PowerToysOverview_LightSwitch) | [<img src="doc/images/icons/Find My Mouse.png" alt="Mouse Utilities icon" height="16"> Mouse Utilities](https://aka.ms/PowerToysOverview_MouseUtilities) | [<img src="doc/images/icons/MouseWithoutBorders.png" alt="Mouse Without Borders icon" height="16"> Mouse Without Borders](https://aka.ms/PowerToysOverview_MouseWithoutBorders) |
|
||||
| [<img src="doc/images/icons/NewPlus.png" alt="New+ icon" height="16"> New+](https://aka.ms/PowerToysOverview_NewPlus) | [<img src="doc/images/icons/Peek.png" alt="Peek icon" height="16"> Peek](https://aka.ms/PowerToysOverview_Peek) | [<img src="doc/images/icons/PowerDisplay.png" alt="PowerDisplay icon" height="16"> PowerDisplay](https://aka.ms/PowerToysOverview_PowerDisplay) |
|
||||
| [<img src="doc/images/icons/PowerRename.png" alt="PowerRename icon" height="16"> PowerRename](https://aka.ms/PowerToysOverview_PowerRename) | [<img src="doc/images/icons/PowerToys%20Run.png" alt="PowerToys Run icon" height="16"> PowerToys Run](https://aka.ms/PowerToysOverview_PowerToysRun) | [<img src="doc/images/icons/PowerAccent.png" alt="Quick Accent icon" height="16"> Quick Accent](https://aka.ms/PowerToysOverview_QuickAccent) |
|
||||
| [<img src="doc/images/icons/Registry%20Preview.png" alt="Registry Preview icon" height="16"> Registry Preview](https://aka.ms/PowerToysOverview_RegistryPreview) | [<img src="doc/images/icons/MeasureTool.png" alt="Screen Ruler icon" height="16"> Screen Ruler](https://aka.ms/PowerToysOverview_ScreenRuler) | [<img src="doc/images/icons/Shortcut%20Guide.png" alt="Shortcut Guide icon" height="16"> Shortcut Guide](https://aka.ms/PowerToysOverview_ShortcutGuide) |
|
||||
| [<img src="doc/images/icons/PowerOCR.png" alt="Text Extractor icon" height="16"> Text Extractor](https://aka.ms/PowerToysOverview_TextExtractor) | [<img src="doc/images/icons/Workspaces.png" alt="Workspaces icon" height="16"> Workspaces](https://aka.ms/PowerToysOverview_Workspaces) | [<img src="doc/images/icons/ZoomIt.png" alt="ZoomIt icon" height="16"> ZoomIt](https://aka.ms/PowerToysOverview_ZoomIt) |
|
||||
|
||||
## 📦 Installation
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ After generating the resx file, rename the existing rc and h files to ProjName.b
|
||||
</Target>
|
||||
```
|
||||
|
||||
This event runs a script which generates a resource.h and ProjName.rc in the `Generated Files` folder using the strings in all the resx files along with the existing information in resource.base.h and ProjName.base.rc. The script is [convert-resx-to-rc.ps1](https://github.com/microsoft/PowerToys/blob/main/tools/build/convert-resx-to-rc.ps1). The script uses [`resgen`](https://learn.microsoft.com/dotnet/framework/tools/resgen-exe-resource-file-generator#Convert) to convert the resx file to a string table expected in the .rc file format. When the resources are added to the rc file the `IDS_` prefix is added and resource names are in upper case (as it was originally). Any occurrences of `"` in the string resource is escaped as `""` to prevent build errors. The string tables are added to the rc file in the following format:
|
||||
This event runs a script which generates a resource.h and ProjName.rc in the `Generated Files` folder using the strings in all the resx files along with the existing information in resource.base.h and ProjName.base.rc. The script is [convert-resx-to-rc.ps1](https://github.com/microsoft/PowerToys/blob/main/tools/build/convert-resx-to-rc.ps1). The script uses [`resgen`](https://learn.microsoft.com/dotnet/framework/tools/resgen-exe-resource-file-generator#Convert) to convert the resx file to a string table expected in the .rc file format. When the resources are added to the rc file the `IDS_` prefix is added and resource names are in uppercase (as it was originally). Any occurrences of `"` in the string resource is escaped as `""` to prevent build errors. The string tables are added to the rc file in the following format:
|
||||
```
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
@@ -353,7 +353,7 @@ On a cold launch, DevPal will do the following:
|
||||
* Start it up.
|
||||
* Check if it's fresh or frozen.
|
||||
* Call `TopLevelCommands`, and put all of them in the list
|
||||
* Create a extension cache entry for that app.
|
||||
* Create an extension cache entry for that app.
|
||||
* If the provider is frozen: we can actually release the
|
||||
`ICommandProvider` instance at this point.
|
||||
* And of course, if we don't find all the packages we had cached, then delete
|
||||
@@ -454,7 +454,7 @@ ms-windows-store://assoc/?Tags=AppExtension-com.microsoft.commandpalette
|
||||
|
||||
to open the store to a list of extensions. However, we can't list those
|
||||
ourselves directly. Our friends in DevHome suggested it could be possible to
|
||||
stand up a azure service which could query the store for us, and return a list
|
||||
stand up an azure service which could query the store for us, and return a list
|
||||
of extensions. This is not something that they currently have planned, nor would
|
||||
it be cheap from an engineering standpoint.
|
||||
|
||||
@@ -1780,7 +1780,7 @@ class MyAppSettings {
|
||||
/* You can save the settings to the file here */
|
||||
var mySettingsFilePath = /* whatever */;
|
||||
string mySettingsJson = mySettings.Settings.GetState();
|
||||
// Or you could raise a event to indicate to the rest of your app that settings have changed.
|
||||
// Or you could raise an event to indicate to the rest of your app that settings have changed.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2006,7 +2006,7 @@ class CommandWithOnlyProperties : IExtendedAttributesProvider { ... }
|
||||
|
||||
will populate the WinRT type cache in Command Palette with the type information
|
||||
for `ICommandWithProperties`. In fact, if Command Palette has the
|
||||
`IExtendedAttributesProvider` type info in it's cache, and then later receives a new
|
||||
`IExtendedAttributesProvider` type info in its cache, and then later receives a new
|
||||
`MyCommandWithProperties` object, it'll actually be able to know that
|
||||
`MyCommandWithProperties` is an `IExtendedAttributesProvider`. WinRT is just weird
|
||||
like that some times.
|
||||
@@ -2350,7 +2350,7 @@ follow - these are not part of the current SDK spec.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> A thought: what if a action returns a `CommandResult.Entity`, then that takes
|
||||
> A thought: what if an action returns a `CommandResult.Entity`, then that takes
|
||||
> devpal back home, but leaves the entity in the query box. This would allow for
|
||||
> a Quicksilver-like "thing, do" flow. That command would prepopulate the
|
||||
> parameters. So we would then filter top-level commands based on things that can
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
This guide is for iterating on `src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Microsoft.CmdPal.Ext.PowerToys.csproj`.
|
||||
|
||||
The extension is registered through the shared sparse package defined in `src/PackageIdentity/AppxManifest.xml`. That manifest declares `Microsoft.CmdPal.Ext.PowerToys.exe` at the sparse package root, so the sparse package and the extension must be built for the same platform and configuration, for example `x64\Debug`.
|
||||
The extension is registered through the shared sparse package defined in `src/PackageIdentity/AppxManifest.xml`. That manifest declares `Microsoft.CmdPal.Ext.PowerToys.exe` relative to the sparse package's ExternalLocation (`WinUI3Apps\` subfolder), so the sparse package and the extension must be built for the same platform and configuration, for example `x64\Debug`.
|
||||
|
||||
## Local development loop
|
||||
|
||||
@@ -30,12 +30,12 @@ The extension is registered through the shared sparse package defined in `src/Pa
|
||||
The command will look like this:
|
||||
|
||||
```powershell
|
||||
Add-AppxPackage -Path "<repo>\<Platform>\<Configuration>\PowerToysSparse.msix" -ExternalLocation "<repo>\<Platform>\<Configuration>"
|
||||
Add-AppxPackage -Path "<repo>\<Platform>\<Configuration>\PowerToysSparse.msix" -ExternalLocation "<repo>\<Platform>\<Configuration>\WinUI3Apps"
|
||||
```
|
||||
|
||||
4. Build `src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Microsoft.CmdPal.Ext.PowerToys.csproj` in the same platform and configuration.
|
||||
|
||||
This project writes `Microsoft.CmdPal.Ext.PowerToys.exe` directly into the sparse package root, such as `x64\Debug` or `ARM64\Debug`. That matches the `Executable="Microsoft.CmdPal.Ext.PowerToys.exe"` entry in `src/PackageIdentity/AppxManifest.xml`.
|
||||
This project writes `Microsoft.CmdPal.Ext.PowerToys.exe` into the `WinUI3Apps\` subfolder of the output root, such as `x64\Debug\WinUI3Apps` or `ARM64\Debug\WinUI3Apps`. That matches the `Executable="Microsoft.CmdPal.Ext.PowerToys.exe"` entry in `src/PackageIdentity/AppxManifest.xml` resolved relative to the sparse package's ExternalLocation.
|
||||
|
||||
5. Restart Command Palette.
|
||||
|
||||
|
||||
@@ -461,7 +461,7 @@ Editor read/write config data handler is in FancyZonesEditorCommon project.
|
||||
FancyZones cpp project read/write config data handler is in FancyZonesLib project.
|
||||
|
||||

|
||||
However, the files write and read those are C:\Users\“xxxxxx”\AppData\Local\Microsoft\PowerToys\FancyZones
|
||||
However, the files read from and written to are those in `C:\Users\“xxxxxx”\AppData\Local\Microsoft\PowerToys\FancyZones`
|
||||
|
||||
You can think of the editor as a visual config editor, which is most of its functionality. Another feature is used to set the layout for the monitor displays.
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ There are three different score types with different start values.
|
||||
| Medium score | 5000 |
|
||||
| Low score | 1000 |
|
||||
|
||||
Each score will decreased by one when a condition match.
|
||||
Each score will be decreased by one when a condition match.
|
||||
|
||||
| Priority | Condition | Score type |
|
||||
| -------- | ----------------------------------------------------------------- | ------------ |
|
||||
@@ -134,7 +134,7 @@ The plugin use only these interfaces (all inside the `Main.cs`):
|
||||
| `plugin.json` | All meta-data for this plugin |
|
||||
|
||||
1. We need this extra wrapper class to make it possible that the JSON file can have and use a JSON schema file.
|
||||
Because the JSON file must have a object as root type, instead of a array.
|
||||
Because the JSON file must have an object as root type, instead of an array.
|
||||
|
||||
### Important project values (*.csproj)
|
||||
|
||||
|
||||
93
doc/devdocs/tools/installer-diagnostics.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# PowerToys Installer & Update Diagnostics
|
||||
|
||||
A step-by-step guide for diagnosing installer and update issues reported by users.
|
||||
|
||||
## Quick Reference: Key Files
|
||||
|
||||
| File/Folder | Path | Contains |
|
||||
|---|---|---|
|
||||
| UpdateState.json | `%LOCALAPPDATA%\Microsoft\PowerToys\UpdateState.json` | Persisted update state machine |
|
||||
| Runner logs | `%LOCALAPPDATA%\Microsoft\PowerToys\RunnerLogs\runner-log_*.log` | Startup, update checks, cleanup |
|
||||
| Update logs | `%LOCALAPPDATA%\Microsoft\PowerToys\UpdateLogs\update-log_*.log` | PowerToys.Update.exe activity |
|
||||
| Updates folder | `%LOCALAPPDATA%\Microsoft\PowerToys\Updates\` | Downloaded installer files |
|
||||
|
||||
> **Note:** These paths use `%LOCALAPPDATA%` (per-user AppData) regardless of whether PowerToys was installed per-user or per-machine. The data/settings location is always per-user.
|
||||
|
||||
## Update State Values
|
||||
|
||||
From `src/common/updating/updateState.h` (`UpdateState::State` enum):
|
||||
|
||||
| Value | Name | Meaning |
|
||||
|---|---|---|
|
||||
| 0 | upToDate | No update needed |
|
||||
| 1 | errorDownloading | Download or install failed, will retry |
|
||||
| 2 | readyToDownload | New version found, not yet downloaded |
|
||||
| 3 | readyToInstall | Installer downloaded, waiting for user action |
|
||||
| 4 | networkError | GitHub API call failed |
|
||||
|
||||
---
|
||||
|
||||
## Symptom: Old update installers accumulating on disk
|
||||
|
||||
### What to ask the user for
|
||||
|
||||
1. Contents of `UpdateState.json`
|
||||
2. Runner logs (last few days from `RunnerLogs\`)
|
||||
3. Update logs (from `UpdateLogs\`, if they exist)
|
||||
4. List of files in `Updates\` folder (names + sizes)
|
||||
|
||||
### Step 1: Check the running version
|
||||
|
||||
In runner logs, look for the startup line:
|
||||
|
||||
```
|
||||
[info] Scoobe: product_version=v0.XX.X last_version_run=v0.XX.X
|
||||
```
|
||||
|
||||
- **If version < v0.73.0**: The pre-download cleanup (PR #27908) is missing. Each downloaded installer accumulates because cleanup only runs at startup when state is `upToDate`. Ask the user to manually upgrade to the latest version.
|
||||
- **If version >= v0.73.0**: The pre-download cleanup exists. Accumulation should not happen under normal conditions. Continue to Step 2.
|
||||
|
||||
### Step 2: Check UpdateState.json
|
||||
|
||||
```jsonc
|
||||
{"state": 3, "downloadedInstallerFilename": "powertoyssetup-0.98.1-x64.exe" /* additional fields may be present */}
|
||||
```
|
||||
|
||||
- **state = 0 (upToDate)**: Cleanup should run at startup. If files are accumulating, check runner logs for "Failed to delete" warnings (Step 4).
|
||||
- **state = 3 (readyToInstall)**: An installer is downloaded but never installed. Cleanup at startup is skipped (by design, to preserve the pending installer). On v0.73+, cleanup can still occur when a future update check triggers a new download (pre-download cleanup path).
|
||||
- **state = 1 (errorDownloading)**: A previous download or install failed. Startup cleanup is skipped (state is not `upToDate`). On v0.73+, cleanup runs before the next installer download is attempted.
|
||||
- **state = 2 or 4**: Startup cleanup is skipped. On v0.73+, cleanup runs before the next installer download is attempted.
|
||||
|
||||
### Step 3: Check if PowerToys.Update.exe has ever run
|
||||
|
||||
- **UpdateLogs directory missing**: This suggests `PowerToys.Update.exe` may never have been launched, or it did not progress far enough to create logs. The user may never have triggered an install, or Stage 1 may have failed before Stage 2 could run.
|
||||
- **UpdateLogs exist but show only "logger is initialized"**: The exe launched but the command-line argument didn't match any action (possible argument parsing issue).
|
||||
- **UpdateLogs show install activity**: The update process ran. Check for success/failure.
|
||||
|
||||
### Step 4: Check runner logs for cleanup evidence
|
||||
|
||||
Search for these patterns:
|
||||
|
||||
| Log pattern | Meaning |
|
||||
|---|---|
|
||||
| `Failed to delete installer file ... Access is denied` | File locked by AV, another process, or permissions issue |
|
||||
| `Failed to delete log file ...` | Same, for old log files |
|
||||
| `Discovered new version` | Periodic update check ran |
|
||||
| `New version is already downloaded` | State is `readyToInstall` and filename matches — no re-download, no cleanup |
|
||||
| No cleanup-related entries at all | Inconclusive by itself — `cleanup_updates()` is silent on success. Corroborate with the Updates folder contents (Step 5) and the running version (Step 1). |
|
||||
|
||||
### Step 5: Check the Updates folder contents
|
||||
|
||||
- **All different versions**: Cleanup likely did not run across multiple update cycles. Confirm with the running version (Step 1) and update state before concluding a state gate issue.
|
||||
- **Duplicate filenames**: Unusual — would suggest repeated download without cleanup.
|
||||
- **Single file matching `downloadedInstallerFilename`**: Normal for `readyToInstall` state.
|
||||
|
||||
### Common root causes
|
||||
|
||||
| Root cause | Evidence | Fix |
|
||||
|---|---|---|
|
||||
| Running pre-v0.73.0 binary | `product_version` < v0.73.0 in runner log | Manually upgrade to latest |
|
||||
| State stuck at `readyToInstall` (pre-v0.73) | `"state": 3` in UpdateState.json, no UpdateLogs | Manually upgrade to latest |
|
||||
| File lock preventing deletion | "Failed to delete ... Access is denied" in runner logs | Check AV software, reboot and retry |
|
||||
| Update installer never launched | No UpdateLogs directory | Check if update notifications are disabled by GPO or setting |
|
||||
| Install fails silently | UpdateLogs show init but no install activity | Check related issues: #46966, #46967, #46969 |
|
||||
BIN
doc/images/icons/GrabAndMove.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
doc/images/icons/PowerDisplay.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
doc/images/overview/CmdPal_large.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
doc/images/overview/CmdPal_small.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
doc/images/overview/GrabAndMove_large.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
doc/images/overview/GrabAndMove_small.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
doc/images/overview/NewPlus_large.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
doc/images/overview/NewPlus_small.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
doc/images/overview/Original/CmdPal.png
Normal file
|
After Width: | Height: | Size: 318 KiB |
BIN
doc/images/overview/Original/GrabAndMove.png
Normal file
|
After Width: | Height: | Size: 141 KiB |
BIN
doc/images/overview/Original/NewPlus.png
Normal file
|
After Width: | Height: | Size: 182 KiB |
BIN
doc/images/overview/Original/PowerDisplay.png
Normal file
|
After Width: | Height: | Size: 111 KiB |
BIN
doc/images/overview/PowerDisplay_large.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
doc/images/overview/PowerDisplay_small.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
@@ -7,7 +7,6 @@
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="../src/common/Telemetry/EtwTrace/EtwTrace.vcxproj" Id="8f021b46-362b-485c-bfba-ccf83e820cbd" />
|
||||
<Project Path="../src/common/version/version.vcxproj" Id="cc6e41ac-8174-4e8a-8d22-85dd7f4851df" />
|
||||
<Project Path="../src/logging/logging.vcxproj" Id="7e1e3f13-2bd6-3f75-a6a7-873a2b55c60f">
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
</Project>
|
||||
|
||||
@@ -10,11 +10,10 @@
|
||||
#include "../../src/common/utils/gpo.h"
|
||||
#include "../../src/common/utils/MsiUtils.h"
|
||||
#include "../../src/common/utils/modulesRegistry.h"
|
||||
#include "../../src/common/updating/installer.h"
|
||||
#include "../../src/common/version/version.h"
|
||||
#include "../../src/common/utils/version.h"
|
||||
#include "../../src/common/Telemetry/EtwTrace/EtwTrace.h"
|
||||
#include "../../src/common/utils/package.h"
|
||||
#include "../../src/common/utils/clean_video_conference.h"
|
||||
#include "../../src/common/utils/package.h"
|
||||
|
||||
#include <winrt/Windows.ApplicationModel.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
@@ -26,6 +25,7 @@
|
||||
#include <UserEnv.h>
|
||||
#include <winnt.h>
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
HINSTANCE DLL_HANDLE = nullptr;
|
||||
@@ -639,7 +639,7 @@ UINT __stdcall InstallPackageIdentityMSIXCA(MSIHANDLE hInstall)
|
||||
try
|
||||
{
|
||||
|
||||
std::wstring externalLocation = installFolderPath; // External content location (PowerToys install folder)
|
||||
std::wstring externalLocation = installFolderPath + L"WinUI3Apps\\"; // External content location (WinUI3Apps subfolder to isolate DACL changes from preview handler DLLs)
|
||||
Uri externalUri{ externalLocation }; // External location URI for sparse package content
|
||||
Uri packageUri{ msixPath }; // The MSIX file URI
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
#include "../../src/common/version/version.h"
|
||||
#include "../../src/common/utils/version.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -6,13 +6,16 @@
|
||||
<?define BaseApplicationsFilesPath=$(var.BinDir)\?>
|
||||
|
||||
<Fragment>
|
||||
<DirectoryRef Id="INSTALLFOLDER">
|
||||
<!-- winmd must be in WinUI3Apps (ExternalLocation) for WinRT COM proxy/stub resolution -->
|
||||
<DirectoryRef Id="WinUI3AppsInstallFolder">
|
||||
<Component Id="Microsoft_CommandPalette_Extensions_winmd" Guid="304AD25A-A986-4058-940E-61DB79EBD78C" Bitness="always64">
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="Microsoft_CommandPalette_Extensions_winmd" Value="" KeyPath="yes" />
|
||||
</RegistryKey>
|
||||
<File Id="Microsoft.CommandPalette.Extensions.winmd" Source="$(var.BinDir)Microsoft.CommandPalette.Extensions.winmd" />
|
||||
<File Id="Microsoft.CommandPalette.Extensions.winmd" Source="$(var.BinDir)WinUI3Apps\Microsoft.CommandPalette.Extensions.winmd" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
<DirectoryRef Id="INSTALLFOLDER">
|
||||
<!-- Generated by generateFileComponents.ps1 -->
|
||||
<!--BaseApplicationsFiles_Component_Def-->
|
||||
</DirectoryRef>
|
||||
|
||||
@@ -66,9 +66,12 @@
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="svgs_icons" Value="" KeyPath="yes" />
|
||||
</RegistryKey>
|
||||
<File Id="icon.ico" Source="$(var.BinDir)svgs\icon.ico" />
|
||||
<File Id="PowerToysWhite.ico" Source="$(var.BinDir)svgs\PowerToysWhite.ico" />
|
||||
<File Id="PowerToysDark.ico" Source="$(var.BinDir)svgs\PowerToysDark.ico" />
|
||||
<File Id="icon.ico" Source="$(var.BinDir)Assets\Runner\icon.ico" />
|
||||
<File Id="iconUpdate.ico" Source="$(var.BinDir)Assets\Runner\iconUpdate.ico" />
|
||||
<File Id="PowerToysWhite.ico" Source="$(var.BinDir)Assets\Runner\PowerToysWhite.ico" />
|
||||
<File Id="PowerToysWhiteUpdate.ico" Source="$(var.BinDir)Assets\Runner\PowerToysWhiteUpdate.ico" />
|
||||
<File Id="PowerToysDark.ico" Source="$(var.BinDir)Assets\Runner\PowerToysDark.ico" />
|
||||
<File Id="PowerToysDarkUpdate.ico" Source="$(var.BinDir)Assets\Runner\PowerToysDarkUpdate.ico" />
|
||||
</Component>
|
||||
</Directory>
|
||||
</DirectoryRef>
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
|
||||
<?define KeyboardManagerAssetsFiles=?>
|
||||
<?define KeyboardManagerAssetsWinUI3Files=?>
|
||||
<?define KeyboardManagerAssetsFilesPath=$(var.BinDir)\Assets\KeyboardManager\?>
|
||||
<?define KeyboardManagerAssetsFilesPath=$(var.BinDir)\WinUI3Apps\Assets\KeyboardManager\?>
|
||||
<?define KeyboardManagerAssetsWinUI3FilesPath=$(var.BinDir)\WinUI3Apps\Assets\KeyboardManagerEditor\?>
|
||||
|
||||
<Fragment>
|
||||
<DirectoryRef Id="BaseApplicationsAssetsFolder">
|
||||
<DirectoryRef Id="WinUI3AppsAssetsFolder">
|
||||
<Directory Id="KeyboardManagerAssetsInstallFolder" Name="KeyboardManager" />
|
||||
</DirectoryRef>
|
||||
<DirectoryRef Id="WinUI3AppsAssetsFolder">
|
||||
|
||||
@@ -4,16 +4,16 @@
|
||||
|
||||
<?include $(sys.CURRENTDIR)\Common.wxi?>
|
||||
|
||||
<Bundle Name="PowerToys (Preview) $(var.PowerToysPlatform)" Version="$(var.Version)" Manufacturer="Microsoft Corporation" IconSourceFile="$(var.BinDir)svgs\icon.ico" UpgradeCode="$(var.UpgradeCode)">
|
||||
<Bundle Name="PowerToys (Preview) $(var.PowerToysPlatform)" Version="$(var.Version)" Manufacturer="Microsoft Corporation" IconSourceFile="$(var.BinDir)icon.ico" UpgradeCode="$(var.UpgradeCode)">
|
||||
<BootstrapperApplication>
|
||||
<bal:WixStandardBootstrapperApplication
|
||||
LicenseFile="$(var.RepoDir)\installer\License.rtf"
|
||||
LogoFile="$(var.RepoDir)\installer\PowerToysSetupVNext\Images\logo44.png"
|
||||
LogoFile="$(var.RepoDir)\installer\PowerToysSetupVNext\Images\logo44.png"
|
||||
SuppressOptionsUI="no"
|
||||
SuppressRepair="yes"
|
||||
Theme="rtfLicense"
|
||||
ThemeFile="$(var.RepoDir)\installer\PowerToysSetupVNext\RtfTheme.xml"/>
|
||||
<Payload Name="icon.ico" SourceFile="$(var.BinDir)svgs\icon.ico" Compressed="yes" />
|
||||
<Payload Name="icon.ico" SourceFile="$(var.BinDir)icon.ico" Compressed="yes" />
|
||||
<Payload Name="SilentFilesInUseBAFunction.dll" SourceFile="$(var.RepoDir)installer\$(var.PowerToysPlatform)\Release\SilentFilesInUseBAFunction.dll" Compressed="yes" bal:BAFunctions="yes" />
|
||||
</BootstrapperApplication>
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
</Property>
|
||||
<Launch Condition="(WINDOWSBUILDNUMBER >= 19041)" Message="This application is only supported on Windows 10 version v2004 (build 19041) or higher." />
|
||||
|
||||
<Icon Id="powertoys.exe" SourceFile="$(var.BinDir)svgs\icon.ico" />
|
||||
<Icon Id="powertoys.exe" SourceFile="$(var.BinDir)icon.ico" />
|
||||
|
||||
<Property Id="ARPPRODUCTICON" Value="powertoys.exe" />
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<Fragment>
|
||||
<!-- Resource directories should be added only if the installer is built on the build farm -->
|
||||
<?ifdef env.IsPipeline?>
|
||||
<?foreach ParentDirectory in INSTALLFOLDER;HistoryPluginFolder;CalculatorPluginFolder;FolderPluginFolder;ProgramPluginFolder;ShellPluginFolder;IndexerPluginFolder;UnitConverterPluginFolder;ValueGeneratorPluginFolder;UriPluginFolder;WindowWalkerPluginFolder;OneNotePluginFolder;RegistryPluginFolder;VSCodeWorkspacesPluginFolder;ServicePluginFolder;SystemPluginFolder;TimeDatePluginFolder;WindowsSettingsPluginFolder;WindowsTerminalPluginFolder;WebSearchPluginFolder;PowerToysPluginFolder?>
|
||||
<?foreach ParentDirectory in INSTALLFOLDER;WinUI3AppsInstallFolder;HistoryPluginFolder;CalculatorPluginFolder;FolderPluginFolder;ProgramPluginFolder;ShellPluginFolder;IndexerPluginFolder;UnitConverterPluginFolder;ValueGeneratorPluginFolder;UriPluginFolder;WindowWalkerPluginFolder;OneNotePluginFolder;RegistryPluginFolder;VSCodeWorkspacesPluginFolder;ServicePluginFolder;SystemPluginFolder;TimeDatePluginFolder;WindowsSettingsPluginFolder;WindowsTerminalPluginFolder;WebSearchPluginFolder;PowerToysPluginFolder?>
|
||||
<DirectoryRef Id="$(var.ParentDirectory)">
|
||||
<!-- Resource file directories -->
|
||||
<?foreach Language in $(var.LocLanguageList)?>
|
||||
@@ -361,11 +361,11 @@
|
||||
</RegistryKey>
|
||||
<File Id="BgcodePreviewHandler_$(var.IdSafeLanguage)_File" Source="$(var.BinDir)\$(var.Language)\PowerToys.BgcodePreviewHandler.resources.dll" />
|
||||
</Component>
|
||||
<Component Id="CmdPalExtPowerToys_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)INSTALLFOLDER" Guid="$(var.CompGUIDPrefix)23">
|
||||
<Component Id="CmdPalExtPowerToys_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)WinUI3AppsInstallFolder" Guid="$(var.CompGUIDPrefix)23">
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="CmdPalExtPowerToys_$(var.IdSafeLanguage)_Component" Value="" KeyPath="yes" />
|
||||
</RegistryKey>
|
||||
<File Id="CmdPalExtPowerToys_$(var.IdSafeLanguage)_File" Source="$(var.BinDir)\$(var.Language)\Microsoft.CmdPal.Ext.PowerToys.resources.dll" />
|
||||
<File Id="CmdPalExtPowerToys_$(var.IdSafeLanguage)_File" Source="$(var.BinDir)\WinUI3Apps\$(var.Language)\Microsoft.CmdPal.Ext.PowerToys.resources.dll" />
|
||||
</Component>
|
||||
<?undef IdSafeLanguage?>
|
||||
<?undef CompGUIDPrefix?>
|
||||
@@ -433,6 +433,7 @@
|
||||
<?define IdSafeLanguage = $(var.Language)?>
|
||||
<?endif?>
|
||||
<RemoveFolder Id="RemoveFolderResourcesResource$(var.IdSafeLanguage)INSTALLFOLDER" Directory="Resource$(var.IdSafeLanguage)INSTALLFOLDER" On="uninstall" />
|
||||
<RemoveFolder Id="RemoveFolderResourcesResource$(var.IdSafeLanguage)WinUI3AppsInstallFolder" Directory="Resource$(var.IdSafeLanguage)WinUI3AppsInstallFolder" On="uninstall" />
|
||||
<RemoveFolder Id="RemoveFolderResourcesResource$(var.IdSafeLanguage)CalculatorPluginFolder" Directory="Resource$(var.IdSafeLanguage)CalculatorPluginFolder" On="uninstall" />
|
||||
<RemoveFolder Id="RemoveFolderResourcesResource$(var.IdSafeLanguage)FolderPluginFolder" Directory="Resource$(var.IdSafeLanguage)FolderPluginFolder" On="uninstall" />
|
||||
<RemoveFolder Id="RemoveFolderResourcesResource$(var.IdSafeLanguage)ProgramPluginFolder" Directory="Resource$(var.IdSafeLanguage)ProgramPluginFolder" On="uninstall" />
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
<?define SettingsV2IconsModelsFiles=?>
|
||||
<?define SettingsV2IconsModelsFilesPath=$(var.BinDir)WinUI3Apps\Assets\Settings\Icons\Models\?>
|
||||
|
||||
<?define SettingsV2AssetsCmdPalFiles=?>
|
||||
<?define SettingsV2AssetsCmdPalFilesPath=$(var.BinDir)WinUI3Apps\Assets\Settings\CmdPal\?>
|
||||
|
||||
<Fragment>
|
||||
<DirectoryRef Id="WinUI3AppsAssetsFolder">
|
||||
<Directory Id="SettingsV2AssetsInstallFolder" Name="Settings">
|
||||
@@ -27,6 +30,7 @@
|
||||
<Directory Id="SettingsV2AssetsModulesInstallFolder" Name="Modules">
|
||||
<Directory Id="SettingsV2OOBEAssetsModulesInstallFolder" Name="OOBE" />
|
||||
</Directory>
|
||||
<Directory Id="SettingsV2AssetsCmdPalInstallFolder" Name="CmdPal" />
|
||||
</Directory>
|
||||
</DirectoryRef>
|
||||
|
||||
@@ -55,6 +59,11 @@
|
||||
<!--SettingsV2IconsModelsFiles_Component_Def-->
|
||||
</DirectoryRef>
|
||||
|
||||
<DirectoryRef Id="SettingsV2AssetsCmdPalInstallFolder" FileSource="$(var.SettingsV2AssetsCmdPalFilesPath)">
|
||||
<!-- Generated by generateFileComponents.ps1 -->
|
||||
<!--SettingsV2AssetsCmdPalFiles_Component_Def-->
|
||||
</DirectoryRef>
|
||||
|
||||
<DirectoryRef Id="SettingsAppAssetsScriptsFolder" FileSource="$(var.SettingsV2AssetsFilesPath)\Scripts\">
|
||||
<Component Id="CommandNotFound_Scripts" Guid="898EFA1E-EDD3-4F4B-8C7F-4A14B0D05B02" Bitness="always64">
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
@@ -80,6 +89,7 @@
|
||||
<RemoveFolder Id="RemoveFolderSettingsV2IconsModelsInstallFolder" Directory="SettingsV2IconsModelsInstallFolder" On="uninstall" />
|
||||
<RemoveFolder Id="RemoveFolderSettingsV2AssetsModulesInstallFolder" Directory="SettingsV2AssetsModulesInstallFolder" On="uninstall" />
|
||||
<RemoveFolder Id="RemoveFolderSettingsV2OOBEAssetsModulesInstallFolder" Directory="SettingsV2OOBEAssetsModulesInstallFolder" On="uninstall" />
|
||||
<RemoveFolder Id="RemoveFolderSettingsV2AssetsCmdPalInstallFolder" Directory="SettingsV2AssetsCmdPalInstallFolder" On="uninstall" />
|
||||
<RemoveFolder Id="RemoveFolderSettingsAppAssetsScriptsFolder" Directory="SettingsAppAssetsScriptsFolder" On="uninstall" />
|
||||
</Component>
|
||||
<ComponentRef Id="CommandNotFound_Scripts" />
|
||||
|
||||
@@ -191,7 +191,7 @@ Generate-FileList -fileDepsJson "" -fileListName ImageResizerAssetsFiles -wxsFil
|
||||
Generate-FileComponents -fileListName "ImageResizerAssetsFiles" -wxsFilePath $PSScriptRoot\ImageResizer.wxs
|
||||
|
||||
#KeyboardManager
|
||||
Generate-FileList -fileDepsJson "" -fileListName KeyboardManagerAssetsFiles -wxsFilePath $PSScriptRoot\KeyboardManager.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\KeyboardManager"
|
||||
Generate-FileList -fileDepsJson "" -fileListName KeyboardManagerAssetsFiles -wxsFilePath $PSScriptRoot\KeyboardManager.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\KeyboardManager"
|
||||
Generate-FileList -fileDepsJson "" -fileListName KeyboardManagerAssetsWinUI3Files -wxsFilePath $PSScriptRoot\KeyboardManager.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\KeyboardManagerEditor"
|
||||
Generate-FileComponents -fileListName "KeyboardManagerAssetsFiles" -wxsFilePath $PSScriptRoot\KeyboardManager.wxs
|
||||
Generate-FileComponents -fileListName "KeyboardManagerAssetsWinUI3Files" -wxsFilePath $PSScriptRoot\KeyboardManager.wxs
|
||||
@@ -336,11 +336,13 @@ Generate-FileList -fileDepsJson "" -fileListName SettingsV2AssetsModulesFiles -w
|
||||
Generate-FileList -fileDepsJson "" -fileListName SettingsV2OOBEAssetsModulesFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Settings\Modules\OOBE\"
|
||||
Generate-FileList -fileDepsJson "" -fileListName SettingsV2OOBEAssetsFluentIconsFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Settings\Icons\"
|
||||
Generate-FileList -fileDepsJson "" -fileListName SettingsV2IconsModelsFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Settings\Icons\Models\"
|
||||
Generate-FileList -fileDepsJson "" -fileListName SettingsV2AssetsCmdPalFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Settings\CmdPal\"
|
||||
Generate-FileComponents -fileListName "SettingsV2AssetsFiles" -wxsFilePath $PSScriptRoot\Settings.wxs
|
||||
Generate-FileComponents -fileListName "SettingsV2AssetsModulesFiles" -wxsFilePath $PSScriptRoot\Settings.wxs
|
||||
Generate-FileComponents -fileListName "SettingsV2OOBEAssetsModulesFiles" -wxsFilePath $PSScriptRoot\Settings.wxs
|
||||
Generate-FileComponents -fileListName "SettingsV2OOBEAssetsFluentIconsFiles" -wxsFilePath $PSScriptRoot\Settings.wxs
|
||||
Generate-FileComponents -fileListName "SettingsV2IconsModelsFiles" -wxsFilePath $PSScriptRoot\Settings.wxs
|
||||
Generate-FileComponents -fileListName "SettingsV2AssetsCmdPalFiles" -wxsFilePath $PSScriptRoot\Settings.wxs
|
||||
|
||||
#Workspaces
|
||||
Generate-FileList -fileDepsJson "" -fileListName WorkspacesImagesComponentFiles -wxsFilePath $PSScriptRoot\Workspaces.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\Workspaces\"
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="DOTNET_CORE_DOWNLOAD_FAILURE" xml:space="preserve">
|
||||
<value>Couldn't download .NET Core Desktop Runtime 3.1, please install it manually.</value>
|
||||
</data>
|
||||
<data name="DOTNET_CORE_DOWNLOAD_FAILURE_TITLE" xml:space="preserve">
|
||||
<value>PowerToys installation error</value>
|
||||
</data>
|
||||
<data name="GITHUB_NEW_VERSION_AVAILABLE_OFFER_VISIT" xml:space="preserve">
|
||||
<value>An update to PowerToys is available. Visit our GitHub page to update.</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,36 +0,0 @@
|
||||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
#include "../common/version/version.h"
|
||||
|
||||
1 VERSIONINFO
|
||||
FILEVERSION FILE_VERSION
|
||||
PRODUCTVERSION PRODUCT_VERSION
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS_NT_WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE VFT2_UNKNOWN
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0" // US English (0x0409), Unicode (0x04B0) charset
|
||||
BEGIN
|
||||
VALUE "CompanyName", COMPANY_NAME
|
||||
VALUE "FileDescription", FILE_DESCRIPTION
|
||||
VALUE "FileVersion", FILE_VERSION_STRING
|
||||
VALUE "InternalName", INTERNAL_NAME
|
||||
VALUE "LegalCopyright", COPYRIGHT_NOTE
|
||||
VALUE "OriginalFilename", ORIGINAL_FILENAME
|
||||
VALUE "ProductName", PRODUCT_NAME
|
||||
VALUE "ProductVersion", PRODUCT_VERSION_STRING
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200 // US English (0x0409), Unicode (1200) charset
|
||||
END
|
||||
END
|
||||
@@ -1,109 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include "Generated Files/resource.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <string_view>
|
||||
|
||||
#include <common/utils/elevation.h>
|
||||
#include <common/utils/process_path.h>
|
||||
#include <common/utils/resources.h>
|
||||
#include <common/utils/timeutil.h>
|
||||
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
|
||||
#include <common/logger/logger.h>
|
||||
|
||||
#include <winrt/Windows.ApplicationModel.h>
|
||||
#include <winrt/Windows.Storage.h>
|
||||
|
||||
#include "../runner/tray_icon.h"
|
||||
#include "../runner/ActionRunnerUtils.h"
|
||||
|
||||
using namespace cmdArg;
|
||||
|
||||
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
|
||||
{
|
||||
int nArgs = 0;
|
||||
LPWSTR* args = CommandLineToArgvW(GetCommandLineW(), &nArgs);
|
||||
if (!args || nArgs < 2)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::wstring_view action{ args[1] };
|
||||
|
||||
std::filesystem::path logFilePath(PTSettingsHelper::get_root_save_folder_location());
|
||||
logFilePath.append(LogSettings::actionRunnerLogPath);
|
||||
Logger::init(LogSettings::actionRunnerLoggerName, logFilePath.wstring(), PTSettingsHelper::get_log_settings_file_location());
|
||||
|
||||
if (action == RUN_NONELEVATED)
|
||||
{
|
||||
int nextArg = 2;
|
||||
|
||||
std::wstring_view target;
|
||||
std::wstring_view pidFile;
|
||||
std::wstring params;
|
||||
|
||||
while (nextArg < nArgs)
|
||||
{
|
||||
if (std::wstring_view(args[nextArg]) == L"-target" && nextArg + 1 < nArgs)
|
||||
{
|
||||
target = args[nextArg + 1];
|
||||
nextArg += 2;
|
||||
}
|
||||
else if (std::wstring_view(args[nextArg]) == L"-pidFile" && nextArg + 1 < nArgs)
|
||||
{
|
||||
pidFile = args[nextArg + 1];
|
||||
nextArg += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
params += args[nextArg];
|
||||
params += L' ';
|
||||
nextArg++;
|
||||
}
|
||||
}
|
||||
|
||||
HANDLE hMapFile = NULL;
|
||||
PDWORD pidBuffer = NULL;
|
||||
|
||||
if (!pidFile.empty())
|
||||
{
|
||||
hMapFile = OpenFileMappingW(FILE_MAP_WRITE, FALSE, pidFile.data());
|
||||
if (hMapFile)
|
||||
{
|
||||
pidBuffer = static_cast<PDWORD>(MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(DWORD)));
|
||||
if (pidBuffer)
|
||||
{
|
||||
*pidBuffer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
run_same_elevation(target.data(), params, pidBuffer);
|
||||
|
||||
if (!pidFile.empty())
|
||||
{
|
||||
if (pidBuffer)
|
||||
{
|
||||
FlushViewOfFile(pidBuffer, sizeof(DWORD));
|
||||
UnmapViewOfFile(pidBuffer);
|
||||
}
|
||||
|
||||
if (hMapFile)
|
||||
{
|
||||
FlushFileBuffers(hMapFile);
|
||||
CloseHandle(hMapFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<Import Project="$(RepoRoot)packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('$(RepoRoot)packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
|
||||
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(RepoRoot)tools\build\convert-resx-to-rc.ps1 $(MSBuildThisFileDirectory) resource.base.h resource.h actionRunner.base.rc actionRunner.rc" />
|
||||
</Target>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D}</ProjectGuid>
|
||||
<RootNamespace>actionRunner</RootNamespace>
|
||||
<ProjectName>PowerToys.ActionRunner</ProjectName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration">
|
||||
|
||||
</PropertyGroup>
|
||||
<Import Project="$(RepoRoot)deps\expected.props" />
|
||||
<PropertyGroup>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup>
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<AdditionalIncludeDirectories>../;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>WindowsApp.lib;Msi.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ActionRunner.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\common\logger\logger.vcxproj">
|
||||
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\common\SettingsAPI\SettingsAPI.vcxproj">
|
||||
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="resource.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="ActionRunner.base.rc" />
|
||||
<ResourceCompile Include="Generated Files\ActionRunner.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="$(RepoRoot)deps\spdlog.props" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="$(RepoRoot)packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('$(RepoRoot)packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
<Import Project="$(RepoRoot)packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('$(RepoRoot)packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('$(RepoRoot)packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '$(RepoRoot)packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('$(RepoRoot)packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(RepoRoot)packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
<Error Condition="!Exists('$(RepoRoot)packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(RepoRoot)packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -1,11 +0,0 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by PowerToys.ActionRunner.rc
|
||||
|
||||
//////////////////////////////
|
||||
// Non-localizable
|
||||
|
||||
#define FILE_DESCRIPTION "PowerToys ActionRunner"
|
||||
#define INTERNAL_NAME "PowerToys.ActionRunner"
|
||||
#define ORIGINAL_FILENAME "PowerToys.ActionRunner.exe"
|
||||
|
||||
@@ -38,17 +38,7 @@
|
||||
</Capabilities>
|
||||
|
||||
<Applications>
|
||||
<Application Id="PowerToys.OCR" Executable="PowerToys.PowerOCR.exe" EntryPoint="Windows.FullTrustApplication">
|
||||
<uap:VisualElements
|
||||
DisplayName="PowerToys.OCR"
|
||||
Description="PowerToys OCR Module"
|
||||
BackgroundColor="transparent"
|
||||
Square150x150Logo="Images\Square150x150Logo.png"
|
||||
Square44x44Logo="Images\Square44x44Logo.png"
|
||||
AppListEntry="none">
|
||||
</uap:VisualElements>
|
||||
</Application>
|
||||
<Application Id="PowerToys.SettingsUI" Executable="WinUI3Apps\PowerToys.Settings.exe" EntryPoint="Windows.FullTrustApplication">
|
||||
<Application Id="PowerToys.SettingsUI" Executable="PowerToys.Settings.exe" EntryPoint="Windows.FullTrustApplication">
|
||||
<uap:VisualElements
|
||||
DisplayName="PowerToys.SettingsUI"
|
||||
Description="PowerToys Settings UI"
|
||||
@@ -58,7 +48,7 @@
|
||||
AppListEntry="none">
|
||||
</uap:VisualElements>
|
||||
</Application>
|
||||
<Application Id="PowerToys.ImageResizerUI" Executable="WinUI3Apps\PowerToys.ImageResizer.exe" EntryPoint="Windows.FullTrustApplication">
|
||||
<Application Id="PowerToys.ImageResizerUI" Executable="PowerToys.ImageResizer.exe" EntryPoint="Windows.FullTrustApplication">
|
||||
<uap:VisualElements
|
||||
DisplayName="PowerToys.ImageResizer"
|
||||
Description="PowerToys Image Resizer UI"
|
||||
|
||||
@@ -417,6 +417,7 @@ if ($NoSign) {
|
||||
Write-BuildLog "Identity Name: $($script:Config.IdentityName)" -Level Info
|
||||
}
|
||||
|
||||
$winUI3AppsDir = Join-Path $outDir "WinUI3Apps"
|
||||
Write-BuildLog "Register sparse package:" -Level Info
|
||||
Write-BuildLog " Add-AppxPackage -Path `"$msixPath`" -ExternalLocation `"$outDir`"" -Level Warning
|
||||
Write-BuildLog "(If already installed and you changed manifest only): Add-AppxPackage -Register `"$manifestPath`" -ExternalLocation `"$outDir`" -ForceApplicationShutdown" -Level Warning
|
||||
Write-BuildLog " Add-AppxPackage -Path `"$msixPath`" -ExternalLocation `"$winUI3AppsDir`"" -Level Warning
|
||||
Write-BuildLog "(If already installed and you changed manifest only): Add-AppxPackage -Register `"$manifestPath`" -ExternalLocation `"$winUI3AppsDir`" -ForceApplicationShutdown" -Level Warning
|
||||
|
||||
@@ -4,9 +4,9 @@ This document describes how to build, sign, register, and consume the shared spa
|
||||
|
||||
## Package overview
|
||||
|
||||
The sparse package lives under `src/PackageIdentity`. It produces a payload-free MSIX whose `Identity` matches `Microsoft.PowerToys.SparseApp`. The manifest contains one entry per Win32 surface that should run with identity (for example Settings, PowerOCR, Image Resizer).
|
||||
The sparse package lives under `src/PackageIdentity`. It produces a payload-free MSIX whose `Identity` matches `Microsoft.PowerToys.SparseApp`. The manifest contains one entry per Win32 surface that should run with identity (for example Settings, Image Resizer, CmdPal Extension).
|
||||
|
||||
> The MSIX contains only metadata. When the package is registered you must point `-ExternalLocation` to the output folder that hosts the Win32 binaries (for example `x64\Release`).
|
||||
> The MSIX contains only metadata. When the package is registered you must point `-ExternalLocation` to the `WinUI3Apps` subfolder of the output folder that hosts the Win32 binaries (for example `x64\Release\WinUI3Apps`). This isolates the DACL changes that MSIX registration applies on Windows 23H2/24H2 to the `WinUI3Apps` folder, keeping the root install folder clean for preview handler DLLs.
|
||||
|
||||
## Building the sparse package locally
|
||||
|
||||
@@ -53,16 +53,17 @@ After `PowerToysSparse.msix` is generated:
|
||||
# First time registration
|
||||
$repoRoot = "C:/git/PowerToys"
|
||||
$outputRoot = Join-Path $repoRoot "x64/Release"
|
||||
Add-AppxPackage -Path (Join-Path $outputRoot "PowerToysSparse.msix") -ExternalLocation $outputRoot
|
||||
$externalLocation = Join-Path $outputRoot "WinUI3Apps"
|
||||
Add-AppxPackage -Path (Join-Path $outputRoot "PowerToysSparse.msix") -ExternalLocation $externalLocation
|
||||
|
||||
# Re-register after manifest tweaks only
|
||||
Add-AppxPackage -Register (Join-Path $repoRoot "src/PackageIdentity/AppxManifest.xml") -ExternalLocation $outputRoot -ForceApplicationShutdown
|
||||
Add-AppxPackage -Register (Join-Path $repoRoot "src/PackageIdentity/AppxManifest.xml") -ExternalLocation $externalLocation -ForceApplicationShutdown
|
||||
|
||||
# Remove the sparse identity
|
||||
Get-AppxPackage -Name Microsoft.PowerToys.SparseApp | Remove-AppxPackage
|
||||
```
|
||||
|
||||
`-ExternalLocation` should match the output folder that contains the Win32 executables declared in the manifest. Re-run registration whenever the manifest or executable layout changes.
|
||||
`-ExternalLocation` should match the `WinUI3Apps` subfolder that contains the Win32 executables declared in the manifest. Re-run registration whenever the manifest or executable layout changes.
|
||||
|
||||
## CI-specific guidance
|
||||
|
||||
@@ -72,7 +73,7 @@ Get-AppxPackage -Name Microsoft.PowerToys.SparseApp | Remove-AppxPackage
|
||||
|
||||
## Consuming the identity from other components
|
||||
|
||||
1. Add a new `<Application>` entry inside `src/PackageIdentity/AppxManifest.xml`. Use a unique `Id` (for example `PowerToys.MyModuleUI`) and set `Executable` to the Win32 binary relative to the `-ExternalLocation` root.
|
||||
1. Add a new `<Application>` entry inside `src/PackageIdentity/AppxManifest.xml`. Use a unique `Id` (for example `PowerToys.MyModuleUI`) and set `Executable` to the Win32 binary relative to the `-ExternalLocation` (`WinUI3Apps` subfolder).
|
||||
2. Ensure the binary is copied into the platform/configuration output folder (`x64\Release`, `ARM64\Debug`, etc.) so the sparse package can locate it.
|
||||
3. Embed a sparse identity manifest in the Win32 binary so it binds to the MSIX identity at runtime. The manifest must declare an `<msix>` element with `packageName="Microsoft.PowerToys.SparseApp"`, `applicationId` matching the `<Application Id>`, and a `publisher` that matches the sparse package. Keep the manifest’s publisher in sync with `src/PackageIdentity/.user/PowerToysSparse.publisher.txt` (emitted by `BuildSparsePackage.ps1`). See `src/modules/imageresizer/ui/ImageResizerUI.csproj` for an example that points `ApplicationManifest` to `ImageResizerUI.dev.manifest` for local builds and switches to `ImageResizerUI.prod.manifest` when `$(CIBuild)` is `true`.
|
||||
4. Register or re-register the sparse package so Windows learns about the new application Id.
|
||||
|
||||
22
src/PowerToys.ActionRunner/PowerToys.ActionRunner.csproj
Normal file
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="$(RepoRoot)src\Common.Dotnet.CsWinRT.props" />
|
||||
<Import Project="$(RepoRoot)src\Common.SelfContained.props" />
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<Description>PowerToys Action Runner</Description>
|
||||
<AssemblyName>PowerToys</AssemblyName>
|
||||
<OutputPath>$(RepoRoot)$(Platform)\$(Configuration)</OutputPath>
|
||||
<Nullable>enable</Nullable>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Assets\PowerToysDark.ico">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Assets\PowerToysLight.ico">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
120
src/PowerToys.ActionRunner/Program.cs
Normal file
@@ -0,0 +1,120 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace PowerToys.ActionRunner;
|
||||
|
||||
internal sealed partial class Program
|
||||
{
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
if (args.Length < 1)
|
||||
{
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (args[0])
|
||||
{
|
||||
case "-run-non-elevated":
|
||||
ExecuteRunNonElevated(args[1..]);
|
||||
break;
|
||||
default:
|
||||
Environment.Exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ExecuteRunNonElevated(string[] args)
|
||||
{
|
||||
string? target = null;
|
||||
string? pidFile = null;
|
||||
string? arguments = null;
|
||||
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
string arg = args[i];
|
||||
if (arg == "-target" && i + 1 < args.Length)
|
||||
{
|
||||
target = args[i + 1];
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else if (arg == "-pidFile" && i + 1 < args.Length)
|
||||
{
|
||||
pidFile = args[i + 1];
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
arguments = args[i + 1] + " ";
|
||||
i++;
|
||||
|
||||
if (target == null)
|
||||
{
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(pidFile))
|
||||
{
|
||||
IntPtr pidBuffer = IntPtr.Zero;
|
||||
IntPtr mapFile = OpenFileMapping(0x0002 /* FILE_MAP_WRITE */, false, pidFile);
|
||||
if (mapFile != IntPtr.Zero)
|
||||
{
|
||||
pidBuffer = MapViewOfFile(mapFile, 0x001F /* FILE_MAP_ALL_ACCESS */, 0, 0, sizeof(uint));
|
||||
if (pidBuffer != IntPtr.Zero)
|
||||
{
|
||||
Marshal.WriteInt32(pidBuffer, 0);
|
||||
}
|
||||
}
|
||||
|
||||
Process? p = Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = target,
|
||||
Arguments = arguments.Trim(),
|
||||
UseShellExecute = true,
|
||||
});
|
||||
|
||||
if (pidBuffer != IntPtr.Zero)
|
||||
{
|
||||
Marshal.WriteInt32(pidBuffer, p?.Id ?? 0);
|
||||
FlushViewOfFile(pidBuffer, sizeof(uint));
|
||||
UnmapViewOfFile(pidBuffer);
|
||||
}
|
||||
|
||||
if (mapFile != IntPtr.Zero)
|
||||
{
|
||||
FlushFileBuffers(mapFile);
|
||||
CloseHandle(mapFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[LibraryImport("Kernel32.dll", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
|
||||
private static partial IntPtr OpenFileMapping(uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, string lpName);
|
||||
|
||||
[LibraryImport("Kernel32.dll", SetLastError = true)]
|
||||
private static partial IntPtr MapViewOfFile(IntPtr hFileMappingObject, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, UIntPtr dwNumberOfBytesToMap);
|
||||
|
||||
[LibraryImport("Kernel32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static partial bool UnmapViewOfFile(IntPtr lpBaseAddress);
|
||||
|
||||
[LibraryImport("Kernel32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static partial bool FlushViewOfFile(IntPtr lpBaseAddress, uint dwNumberOfBytesToFlush);
|
||||
|
||||
[LibraryImport("Kernel32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static partial bool FlushFileBuffers(IntPtr hFile);
|
||||
|
||||
[LibraryImport("Kernel32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static partial bool CloseHandle(IntPtr hObject);
|
||||
}
|
||||
BIN
src/Runner/Assets/Runner/PowerToysDark.ico
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
src/Runner/Assets/Runner/PowerToysDarkUpdate.ico
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
src/Runner/Assets/Runner/PowerToysLight.ico
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
src/Runner/Assets/Runner/PowerToysWhiteUpdate.ico
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
src/Runner/Assets/Runner/iconUpdate.ico
Normal file
|
After Width: | Height: | Size: 42 KiB |
17
src/Runner/Extensions/PackageVersionExtensions.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
// 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 Windows.ApplicationModel;
|
||||
|
||||
namespace RunnerV2.Extensions
|
||||
{
|
||||
internal static class PackageVersionExtensions
|
||||
{
|
||||
public static Version ToVersion(this PackageVersion packageVersion)
|
||||
{
|
||||
return new Version(packageVersion.Major, packageVersion.Minor, packageVersion.Build, packageVersion.Revision);
|
||||
}
|
||||
}
|
||||
}
|
||||
40
src/Runner/Helpers/AIHelper.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
|
||||
namespace RunnerV2.Helpers
|
||||
{
|
||||
internal static class AIHelper
|
||||
{
|
||||
public static void DetectAiCapabilities(bool skipSettingsCheck = false)
|
||||
{
|
||||
new Thread(() => DetectAiCapabilitiesInternal(skipSettingsCheck)).Start();
|
||||
}
|
||||
|
||||
private static void DetectAiCapabilitiesInternal(bool skipSettingsCheck)
|
||||
{
|
||||
if (!skipSettingsCheck)
|
||||
{
|
||||
var generalSettings = SettingsUtils.Default.GetSettings<GeneralSettings>();
|
||||
if (!generalSettings.Enabled.ImageResizer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Path.Exists("WinUI3Apps\\PowerToys.ImageResizer.exe"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var p = Process.Start("WinUI3Apps\\PowerToys.ImageResizer.exe", "--detect-ai");
|
||||
p.WaitForExit(30000);
|
||||
p.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
39
src/Runner/Helpers/AutoStartHelper.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using PowerToys.Interop;
|
||||
|
||||
namespace RunnerV2.Helpers
|
||||
{
|
||||
internal static class AutoStartHelper
|
||||
{
|
||||
internal static void SetAutoStartState(bool enabled)
|
||||
{
|
||||
bool isActive = AutoStart.IsAutoStartTaskActiveForThisUser();
|
||||
if (isActive && enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isActive && !enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (isActive && !enabled)
|
||||
{
|
||||
AutoStart.DeleteAutoStartTaskForThisUser();
|
||||
}
|
||||
else if (!isActive && enabled)
|
||||
{
|
||||
AutoStart.CreateAutoStartTaskForThisUser(ElevationHelper.IsProcessElevated());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
57
src/Runner/Helpers/COMUtils.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace RunnerV2.Helpers
|
||||
{
|
||||
internal static class COMUtils
|
||||
{
|
||||
public static void InitializeCOMSecurity(string securityDescriptor)
|
||||
{
|
||||
if (!NativeMethods.ConvertStringSecurityDescriptorToSecurityDescriptorW(
|
||||
securityDescriptor,
|
||||
1,
|
||||
out IntPtr pSD,
|
||||
out _))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uint absoluteSDSize = 0;
|
||||
uint daclSize = 0;
|
||||
uint groupSize = 0;
|
||||
uint ownerSize = 0;
|
||||
uint saclSize = 0;
|
||||
|
||||
if (!NativeMethods.MakeAbsoluteSD(pSD, IntPtr.Zero, ref absoluteSDSize, IntPtr.Zero, ref daclSize, IntPtr.Zero, ref saclSize, IntPtr.Zero, ref ownerSize, IntPtr.Zero, ref groupSize))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IntPtr absoluteSD = Marshal.AllocHGlobal((int)absoluteSDSize);
|
||||
IntPtr dacl = Marshal.AllocHGlobal((int)daclSize);
|
||||
IntPtr sacl = Marshal.AllocHGlobal((int)saclSize);
|
||||
IntPtr owner = Marshal.AllocHGlobal((int)ownerSize);
|
||||
IntPtr group = Marshal.AllocHGlobal((int)groupSize);
|
||||
|
||||
if (!NativeMethods.MakeAbsoluteSD(pSD, absoluteSD, ref absoluteSDSize, dacl, ref daclSize, sacl, ref saclSize, owner, ref ownerSize, group, ref groupSize))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_ = NativeMethods.CoInitializeSecurity(
|
||||
absoluteSD,
|
||||
-1,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
6, // RPC_C_AUTHN_LEVEL_PKT_PRIVACY
|
||||
2, // RPC_C_IMP_LEVEL_IDENTIFY
|
||||
IntPtr.Zero,
|
||||
64 | 4096, // EOAC_DYNAMIC_CLOAKING | EOAC_DISABLE_AAA
|
||||
IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
255
src/Runner/Helpers/CentralizedKeyboardHookManager.cs
Normal file
@@ -0,0 +1,255 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Windows.System;
|
||||
|
||||
namespace RunnerV2.Helpers
|
||||
{
|
||||
internal static class CentralizedKeyboardHookManager
|
||||
{
|
||||
private static readonly UIntPtr _ignoreKeyEventFlag = 0x5556;
|
||||
|
||||
public static bool DebugConsole { get => _debugConsole; set => _debugConsole = value; }
|
||||
|
||||
private static volatile bool _debugConsole;
|
||||
|
||||
public static OrderedDictionary<string, List<(HotkeySettings HotkeySettings, Action Action)>> KeyboardHooks { get; } = [];
|
||||
|
||||
private static HotkeySettingsControlHook _hotkeySettingsControlHook = new(OnKeyDown, OnKeyUp, IsActive, (_, specialFlags) => specialFlags != _ignoreKeyEventFlag);
|
||||
|
||||
private static void OnKeyDown(int key)
|
||||
{
|
||||
if (_debugConsole)
|
||||
{
|
||||
Console.WriteLine($"Key down: {(VirtualKey)key}, Ctrl: {_ctrlState}, Alt: {_altState}, Shift: {_shiftState}, Win: {_winState}");
|
||||
}
|
||||
|
||||
if ((VirtualKey)key == VirtualKey.RightMenu && _ctrlState)
|
||||
{
|
||||
_ctrlAltState = true;
|
||||
}
|
||||
|
||||
switch ((VirtualKey)key)
|
||||
{
|
||||
case VirtualKey.Control:
|
||||
case VirtualKey.LeftControl:
|
||||
case VirtualKey.RightControl:
|
||||
_ctrlState = true;
|
||||
break;
|
||||
case VirtualKey.Menu:
|
||||
case VirtualKey.LeftMenu:
|
||||
case VirtualKey.RightMenu:
|
||||
_altState = true;
|
||||
break;
|
||||
case VirtualKey.Shift:
|
||||
case VirtualKey.LeftShift:
|
||||
case VirtualKey.RightShift:
|
||||
_shiftState = true;
|
||||
break;
|
||||
case VirtualKey.LeftWindows:
|
||||
case VirtualKey.RightWindows:
|
||||
_winState = true;
|
||||
break;
|
||||
default:
|
||||
if (OnKeyboardEvent(new HotkeySettings
|
||||
{
|
||||
Code = key,
|
||||
Ctrl = _ctrlState,
|
||||
Alt = _altState,
|
||||
Shift = _shiftState,
|
||||
Win = _winState,
|
||||
}))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
SendSingleKeyboardInput((short)key, (uint)NativeKeyboardHelper.KeyEventF.KeyDown);
|
||||
if (_debugConsole)
|
||||
{
|
||||
Console.WriteLine($"Key down send: {(VirtualKey)key}, Ctrl: {_ctrlState}, Alt: {_altState}, Shift: {_shiftState}, Win: {_winState}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnKeyUp(int key)
|
||||
{
|
||||
if (_debugConsole)
|
||||
{
|
||||
Console.WriteLine($"Key up: {(VirtualKey)key}, Ctrl: {_ctrlState}, Alt: {_altState}, Shift: {_shiftState}, Win: {_winState}");
|
||||
}
|
||||
|
||||
switch ((VirtualKey)key)
|
||||
{
|
||||
case VirtualKey.Control:
|
||||
case VirtualKey.LeftControl:
|
||||
case VirtualKey.RightControl:
|
||||
_ctrlState = false;
|
||||
break;
|
||||
case VirtualKey.Menu:
|
||||
case VirtualKey.LeftMenu:
|
||||
case VirtualKey.RightMenu:
|
||||
_altState = false;
|
||||
break;
|
||||
case VirtualKey.Shift:
|
||||
case VirtualKey.LeftShift:
|
||||
case VirtualKey.RightShift:
|
||||
_shiftState = false;
|
||||
break;
|
||||
case VirtualKey.LeftWindows:
|
||||
case VirtualKey.RightWindows:
|
||||
_winState = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Correctly release Ctrl key if Ctrl+Alt (AltGr) was used.
|
||||
if (_ctrlAltState && (VirtualKey)key == VirtualKey.RightMenu)
|
||||
{
|
||||
_ctrlAltState = false;
|
||||
_ctrlState = false;
|
||||
|
||||
SendSingleKeyboardInput((short)VirtualKey.LeftControl, (uint)NativeKeyboardHelper.KeyEventF.KeyUp);
|
||||
}
|
||||
|
||||
SendSingleKeyboardInput((short)key, (uint)NativeKeyboardHelper.KeyEventF.KeyUp);
|
||||
if (_debugConsole)
|
||||
{
|
||||
Console.WriteLine($"Key up send: {(VirtualKey)key}, Ctrl: {_ctrlState}, Alt: {_altState}, Shift: {_shiftState}, Win: {_winState}");
|
||||
}
|
||||
}
|
||||
|
||||
private static bool _ctrlState;
|
||||
private static bool _altState;
|
||||
private static bool _shiftState;
|
||||
private static bool _winState;
|
||||
private static bool _ctrlAltState;
|
||||
|
||||
private static bool _isActive;
|
||||
|
||||
private static bool IsActive()
|
||||
{
|
||||
return _isActive;
|
||||
}
|
||||
|
||||
public static void AddKeyboardHook(string moduleName, HotkeySettings hotkeySettings, Action action)
|
||||
{
|
||||
#pragma warning disable CA1854 // Prefer the 'IDictionary.TryGetValue(TKey, out TValue)' method
|
||||
if (!KeyboardHooks.ContainsKey(moduleName))
|
||||
{
|
||||
KeyboardHooks[moduleName] = [];
|
||||
}
|
||||
#pragma warning restore CA1854 // Prefer the 'IDictionary.TryGetValue(TKey, out TValue)' method
|
||||
|
||||
KeyboardHooks[moduleName].Add((hotkeySettings, action));
|
||||
}
|
||||
|
||||
public static void RemoveAllHooksFromModule(string moduleName)
|
||||
{
|
||||
KeyboardHooks.Remove(moduleName);
|
||||
}
|
||||
|
||||
private static bool OnKeyboardEvent(HotkeySettings pressedHotkey)
|
||||
{
|
||||
bool shortcutHandled = false;
|
||||
|
||||
foreach (var moduleHooks in KeyboardHooks.Values)
|
||||
{
|
||||
foreach (var (hotkeySettings, action) in moduleHooks)
|
||||
{
|
||||
if (hotkeySettings == pressedHotkey)
|
||||
{
|
||||
action();
|
||||
shortcutHandled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return shortcutHandled;
|
||||
}
|
||||
|
||||
public static void Start()
|
||||
{
|
||||
if (_hotkeySettingsControlHook.GetDisposedState())
|
||||
{
|
||||
_hotkeySettingsControlHook = new(OnKeyDown, OnKeyUp, IsActive, (_, specialFlags) => specialFlags != _ignoreKeyEventFlag);
|
||||
}
|
||||
|
||||
_isActive = true;
|
||||
}
|
||||
|
||||
public static void Stop()
|
||||
{
|
||||
_isActive = false;
|
||||
_hotkeySettingsControlHook.Dispose();
|
||||
}
|
||||
|
||||
// Function to send a single key event to the system which would be ignored by the hotkey control.
|
||||
private static void SendSingleKeyboardInput(short keyCode, uint keyStatus)
|
||||
{
|
||||
if (IsExtendedVirtualKey(keyCode))
|
||||
{
|
||||
keyStatus |= (uint)NativeKeyboardHelper.KeyEventF.ExtendedKey;
|
||||
}
|
||||
|
||||
NativeKeyboardHelper.INPUT input = new()
|
||||
{
|
||||
type = NativeKeyboardHelper.INPUTTYPE.INPUT_KEYBOARD,
|
||||
data = new NativeKeyboardHelper.InputUnion
|
||||
{
|
||||
ki = new NativeKeyboardHelper.KEYBDINPUT
|
||||
{
|
||||
wVk = keyCode,
|
||||
dwFlags = keyStatus,
|
||||
dwExtraInfo = _ignoreKeyEventFlag,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
NativeKeyboardHelper.INPUT[] inputs = [input];
|
||||
|
||||
_ = NativeMethods.SendInput(1, inputs, NativeKeyboardHelper.INPUT.Size);
|
||||
}
|
||||
|
||||
private static bool IsExtendedVirtualKey(short vk)
|
||||
{
|
||||
return vk switch
|
||||
{
|
||||
0xA5 => true, // VK_RMENU (Right Alt - AltGr)
|
||||
0xA3 => true, // VK_RCONTROL
|
||||
0x2D => true, // VK_INSERT
|
||||
0x2E => true, // VK_DELETE
|
||||
0x23 => true, // VK_END
|
||||
0x24 => true, // VK_HOME
|
||||
0x21 => true, // VK_PRIOR (Page Up)
|
||||
0x22 => true, // VK_NEXT (Page Down)
|
||||
0x90 => true, // VK_NUMLOCK
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
internal static List<string> GetAllModulesWithShortcut(HotkeySettings hotkeySettings)
|
||||
{
|
||||
List<string> modulesWithShortcut = [];
|
||||
foreach (var moduleHooks in KeyboardHooks)
|
||||
{
|
||||
foreach (var (registeredHotkeySettings, _) in moduleHooks.Value)
|
||||
{
|
||||
if (registeredHotkeySettings == hotkeySettings)
|
||||
{
|
||||
modulesWithShortcut.Add(moduleHooks.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return modulesWithShortcut;
|
||||
}
|
||||
}
|
||||
}
|
||||
101
src/Runner/Helpers/ElevationHelper.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 System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using static RunnerV2.NativeMethods;
|
||||
|
||||
namespace RunnerV2.Helpers
|
||||
{
|
||||
internal static partial class ElevationHelper
|
||||
{
|
||||
internal static RestartScheduledMode RestartScheduled { get; set; } = RestartScheduledMode.None;
|
||||
|
||||
internal enum RestartScheduledMode
|
||||
{
|
||||
None,
|
||||
RestartElevated,
|
||||
RestartElevatedWithOpenSettings,
|
||||
RestartNonElevated,
|
||||
}
|
||||
|
||||
private static bool? _cachedValue;
|
||||
|
||||
internal static void RestartIfScheudled()
|
||||
{
|
||||
switch (RestartScheduled)
|
||||
{
|
||||
case RestartScheduledMode.None:
|
||||
return;
|
||||
case RestartScheduledMode.RestartElevated:
|
||||
RestartAsAdministrator("--restartedElevated --restarted");
|
||||
break;
|
||||
case RestartScheduledMode.RestartElevatedWithOpenSettings:
|
||||
RestartAsAdministrator("--restartedElevated --open-settings --restarted");
|
||||
break;
|
||||
case RestartScheduledMode.RestartNonElevated:
|
||||
RestartAsNonElevated("--restarted --open-settings");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void RestartAsNonElevated(string arguments)
|
||||
{
|
||||
PowerToys.Interop.Elevation.RunNonElevated(Environment.ProcessPath, arguments);
|
||||
}
|
||||
|
||||
private static void RestartAsAdministrator(string arguments)
|
||||
{
|
||||
Logger.LogInfo("Restarting as administrator, because it was scheudled.");
|
||||
|
||||
ProcessStartInfo processStartInfo = new()
|
||||
{
|
||||
Arguments = arguments,
|
||||
Verb = "runas",
|
||||
UseShellExecute = true,
|
||||
FileName = Environment.ProcessPath,
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
Process.Start(processStartInfo);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Failed to restart as administrator.", ex);
|
||||
}
|
||||
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
internal static bool IsProcessElevated(bool useCachedValue = true)
|
||||
{
|
||||
if (_cachedValue is not null && useCachedValue)
|
||||
{
|
||||
return _cachedValue.Value;
|
||||
}
|
||||
|
||||
bool elevated = false;
|
||||
if (OpenProcessToken(Process.GetCurrentProcess().Handle, TOKENQUERY, out nint token))
|
||||
{
|
||||
TokenElevation elevation = default;
|
||||
if (GetTokenInformation(token, TOKEN_INFORMATION_CLASS.TOKEN_ELEVATION, ref elevation, (uint)Marshal.SizeOf(elevation), out uint _))
|
||||
{
|
||||
elevated = elevation.TokenIsElevated != 0;
|
||||
}
|
||||
|
||||
if (token != IntPtr.Zero)
|
||||
{
|
||||
CloseHandle(token);
|
||||
}
|
||||
}
|
||||
|
||||
_cachedValue = elevated;
|
||||
return elevated;
|
||||
}
|
||||
}
|
||||
}
|
||||
252
src/Runner/Helpers/HotkeyConflictsManager.cs
Normal file
@@ -0,0 +1,252 @@
|
||||
// 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.Runtime.InteropServices;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Threading;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
|
||||
namespace RunnerV2.Helpers
|
||||
{
|
||||
internal static class HotkeyConflictsManager
|
||||
{
|
||||
public sealed record HotkeyConflict(HotkeySettings Hotkey, string ModuleName, int HotkeyID);
|
||||
|
||||
private static readonly Lock _hotkeyLock = new();
|
||||
|
||||
private static readonly Dictionary<int, List<HotkeyConflict>> _sysConflictHotkeys = [];
|
||||
private static readonly Dictionary<int, List<HotkeyConflict>> _inAppConflictHotkeys = [];
|
||||
|
||||
internal static bool HasConflict(HotkeySettings hotkey)
|
||||
{
|
||||
_hotkeyLock.Enter();
|
||||
if (hotkey.IsEmpty())
|
||||
{
|
||||
_hotkeyLock.Exit();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (HasConflictWithSystemHotkey(hotkey))
|
||||
{
|
||||
_hotkeyLock.Exit();
|
||||
return true;
|
||||
}
|
||||
|
||||
var modulesWithSameHotkey = CentralizedKeyboardHookManager.GetAllModulesWithShortcut(hotkey);
|
||||
_hotkeyLock.Exit();
|
||||
return modulesWithSameHotkey.Count > 0;
|
||||
}
|
||||
|
||||
internal static List<HotkeyConflict> GetAllConflicts(HotkeySettings hotkey)
|
||||
{
|
||||
_hotkeyLock.Enter();
|
||||
List<HotkeyConflict> conflicts = [];
|
||||
if (hotkey.IsEmpty())
|
||||
{
|
||||
_hotkeyLock.Exit();
|
||||
return conflicts;
|
||||
}
|
||||
|
||||
if (HasConflictWithSystemHotkey(hotkey))
|
||||
{
|
||||
conflicts.Add(new HotkeyConflict(hotkey, "System", -1));
|
||||
}
|
||||
|
||||
conflicts.AddRange(_inAppConflictHotkeys.GetValueOrDefault(hotkey.GetHashCode(), []));
|
||||
|
||||
_hotkeyLock.Exit();
|
||||
return conflicts;
|
||||
}
|
||||
|
||||
internal static JsonNode GetHotkeyConflictsAsJson()
|
||||
{
|
||||
_hotkeyLock.Enter();
|
||||
|
||||
JsonNode hotkeyConflicts = new JsonObject();
|
||||
|
||||
static JsonObject SerializeShortcut(HotkeySettings hotkey) =>
|
||||
new()
|
||||
{
|
||||
["win"] = hotkey.Win,
|
||||
["ctrl"] = hotkey.Ctrl,
|
||||
["alt"] = hotkey.Alt,
|
||||
["shift"] = hotkey.Shift,
|
||||
["key"] = hotkey.Code,
|
||||
};
|
||||
|
||||
JsonArray inAppConflictsArray = [];
|
||||
JsonArray sysConflictsArray = [];
|
||||
|
||||
foreach (List<HotkeyConflict> conflicts in _inAppConflictHotkeys.Values)
|
||||
{
|
||||
if (conflicts.Count == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
JsonObject conflictGroup = [];
|
||||
|
||||
conflictGroup["hotkey"] = SerializeShortcut(conflicts[0].Hotkey);
|
||||
|
||||
JsonArray modules = [];
|
||||
foreach (HotkeyConflict conflict in conflicts)
|
||||
{
|
||||
JsonObject moduleInfo = [];
|
||||
moduleInfo["moduleName"] = conflict.ModuleName;
|
||||
moduleInfo["hotkeyID"] = conflict.HotkeyID;
|
||||
modules.Add(moduleInfo);
|
||||
}
|
||||
|
||||
conflictGroup["modules"] = modules;
|
||||
inAppConflictsArray.Add(conflictGroup);
|
||||
}
|
||||
|
||||
foreach (List<HotkeyConflict> conflicts in _sysConflictHotkeys.Values)
|
||||
{
|
||||
if (conflicts.Count == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
JsonObject conflictGroup = [];
|
||||
|
||||
conflictGroup["hotkey"] = SerializeShortcut(conflicts[0].Hotkey);
|
||||
|
||||
JsonArray modules = [];
|
||||
foreach (HotkeyConflict conflict in conflicts)
|
||||
{
|
||||
JsonObject moduleInfo = [];
|
||||
moduleInfo["moduleName"] = conflict.ModuleName;
|
||||
moduleInfo["hotkeyID"] = conflict.HotkeyID;
|
||||
modules.Add(moduleInfo);
|
||||
}
|
||||
|
||||
conflictGroup["modules"] = modules;
|
||||
sysConflictsArray.Add(conflictGroup);
|
||||
}
|
||||
|
||||
hotkeyConflicts.Root["inAppConflicts"] = inAppConflictsArray;
|
||||
hotkeyConflicts.Root["sysConflicts"] = sysConflictsArray;
|
||||
|
||||
_hotkeyLock.Exit();
|
||||
return hotkeyConflicts;
|
||||
}
|
||||
|
||||
internal static void AddHotkey(HotkeySettings hotkey, string moduleName, int hotkeyID)
|
||||
{
|
||||
switch (HasConflict(hotkey, moduleName))
|
||||
{
|
||||
case ConflictType.InApp:
|
||||
if (!_inAppConflictHotkeys.ContainsKey(hotkey.GetHashCode()))
|
||||
{
|
||||
_inAppConflictHotkeys[hotkey.GetHashCode()] = [];
|
||||
}
|
||||
|
||||
_inAppConflictHotkeys[hotkey.GetHashCode()].Add(new HotkeyConflict(hotkey, moduleName, hotkeyID));
|
||||
break;
|
||||
case ConflictType.System:
|
||||
// PowerToys Run has own keyboard hook
|
||||
if (moduleName == "PowerToys Run")
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!_sysConflictHotkeys.ContainsKey(hotkey.GetHashCode()))
|
||||
{
|
||||
_sysConflictHotkeys[hotkey.GetHashCode()] = [];
|
||||
}
|
||||
|
||||
_sysConflictHotkeys[hotkey.GetHashCode()].Add(new HotkeyConflict(hotkey, moduleName, hotkeyID));
|
||||
break;
|
||||
case ConflictType.None:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void RemoveHotkeysOfModule(string moduleName)
|
||||
{
|
||||
_hotkeyLock.Enter();
|
||||
foreach (List<HotkeyConflict> conflicts in _inAppConflictHotkeys.Values)
|
||||
{
|
||||
conflicts.RemoveAll(conflict => conflict.ModuleName == moduleName);
|
||||
}
|
||||
|
||||
foreach (List<HotkeyConflict> conflicts in _sysConflictHotkeys.Values)
|
||||
{
|
||||
conflicts.RemoveAll(conflict => conflict.ModuleName == moduleName);
|
||||
}
|
||||
|
||||
_hotkeyLock.Exit();
|
||||
}
|
||||
|
||||
protected enum ConflictType
|
||||
{
|
||||
None,
|
||||
InApp,
|
||||
System,
|
||||
}
|
||||
|
||||
private static ConflictType HasConflict(HotkeySettings hotkey, string moduleName)
|
||||
{
|
||||
_hotkeyLock.Enter();
|
||||
|
||||
if (hotkey.IsEmpty())
|
||||
{
|
||||
_hotkeyLock.Exit();
|
||||
return ConflictType.None;
|
||||
}
|
||||
|
||||
if (HasConflictWithSystemHotkey(hotkey))
|
||||
{
|
||||
_hotkeyLock.Exit();
|
||||
return ConflictType.System;
|
||||
}
|
||||
|
||||
var modulesWithSameHotkey = CentralizedKeyboardHookManager.GetAllModulesWithShortcut(hotkey);
|
||||
modulesWithSameHotkey.Remove(moduleName); // Remove the current module from the list to avoid false positive
|
||||
|
||||
if (modulesWithSameHotkey.Count > 0)
|
||||
{
|
||||
_hotkeyLock.Exit();
|
||||
return ConflictType.InApp;
|
||||
}
|
||||
|
||||
_hotkeyLock.Exit();
|
||||
return ConflictType.None;
|
||||
}
|
||||
|
||||
private static bool HasConflictWithSystemHotkey(HotkeySettings hotkey)
|
||||
{
|
||||
if (hotkey.IsEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint modifiers = (uint)((hotkey.Win ? 0x0008 : 0) |
|
||||
(hotkey.Ctrl ? 0x0002 : 0) |
|
||||
(hotkey.Alt ? 0x0001 : 0) |
|
||||
(hotkey.Shift ? 0x0004 : 0));
|
||||
|
||||
// Use a unique ID for this test registration
|
||||
int hotkeyId = 0x0FFF;
|
||||
|
||||
if (!NativeMethods.RegisterHotKey(IntPtr.Zero, hotkeyId, modifiers, (uint)hotkey.Code))
|
||||
{
|
||||
if (Marshal.GetLastWin32Error() == 1409/* ERROR_HOTKEY_ALREADY_REGISTERED */)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NativeMethods.UnregisterHotKey(IntPtr.Zero, hotkeyId);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
52
src/Runner/Helpers/NotificationHelper.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ManagedCommon;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace RunnerV2.Helpers
|
||||
{
|
||||
internal static class NotificationHelper
|
||||
{
|
||||
public enum ToastType
|
||||
{
|
||||
ElevatedDontShowAgain,
|
||||
CouldntToggleFileExplorerModules,
|
||||
}
|
||||
|
||||
public static string GetToastKey(ToastType key) => key switch
|
||||
{
|
||||
ToastType.ElevatedDontShowAgain => @"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\DontShowMeThisDialogAgain\{e16ea82f-6d94-4f30-bb02-d6d911588afd}",
|
||||
ToastType.CouldntToggleFileExplorerModules => @"(SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\DontShowMeThisDialogAgain\{7e29e2b2-b31c-4dcd-b7b0-79c078b02430})",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(key), key, null),
|
||||
};
|
||||
|
||||
public static bool DisableToast(ToastType type)
|
||||
{
|
||||
try
|
||||
{
|
||||
RegistryKey? key = Registry.CurrentUser.CreateSubKey(GetToastKey(type));
|
||||
|
||||
if (key != null)
|
||||
{
|
||||
key.SetValue(null, BitConverter.GetBytes(DateTimeOffset.UtcNow.ToUnixTimeSeconds()), RegistryValueKind.QWord);
|
||||
key.Close();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError("Could not disable toast notification.", e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
194
src/Runner/Helpers/PackageHelper.cs
Normal file
@@ -0,0 +1,194 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Interop;
|
||||
using ManagedCommon;
|
||||
using RunnerV2.Extensions;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.Foundation;
|
||||
using Windows.Management.Deployment;
|
||||
|
||||
namespace RunnerV2.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides helper methods for working with UWP packages.
|
||||
/// </summary>
|
||||
internal static partial class PackageHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the registered UWP package based on the display name and version check.
|
||||
/// </summary>
|
||||
/// <param name="packageDisplayName">The display name of the package.</param>
|
||||
/// <param name="checkVersion">If true, the package version will be checked against the executing assembly version.</param>
|
||||
/// <returns>If a package is found the corresponding <see cref="Package"/> object. If none is found <c>null</c>.</returns>
|
||||
internal static Package? GetRegisteredPackage(string packageDisplayName, bool checkVersion)
|
||||
{
|
||||
PackageManager packageManager = new();
|
||||
foreach (var package in packageManager.FindPackagesForUser(null))
|
||||
{
|
||||
if (package.Id.FullName.Contains(packageDisplayName) && (!checkVersion || package.Id.Version.ToVersion() == Assembly.GetExecutingAssembly().GetName().Version))
|
||||
{
|
||||
return package;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static string[] FindMsixFiles(string directoryPath, bool recursive)
|
||||
{
|
||||
if (!Directory.Exists(directoryPath))
|
||||
{
|
||||
Logger.LogError("Tried to search msix files in " + directoryPath + ", but it does not exist.");
|
||||
return [];
|
||||
}
|
||||
|
||||
List<string> matchedFiles = [];
|
||||
|
||||
try
|
||||
{
|
||||
foreach (string file in Directory.GetFiles(directoryPath, "*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly))
|
||||
{
|
||||
if (File.Exists(file) && msixPackagePattern().IsMatch(Path.GetFileName(file)))
|
||||
{
|
||||
matchedFiles.Add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError("An error occured while searching for MSIX files.", e);
|
||||
}
|
||||
|
||||
return [.. matchedFiles];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Installs the specified appx package along with its dependencies.
|
||||
/// </summary>
|
||||
/// <param name="packagePath">Path to the package</param>
|
||||
/// <param name="dependencies">Array of dependency package paths</param>
|
||||
/// <returns>True if the installation was successful, false otherwise</returns>
|
||||
internal static bool InstallPackage(string packagePath, string[] dependencies, bool isSparsePackage = false)
|
||||
{
|
||||
Logger.LogInfo("Starting package install of package \"" + packagePath + "\"");
|
||||
PackageManager packageManager = new();
|
||||
List<Uri> uris = [];
|
||||
|
||||
if (IsPackageSatisfied(packagePath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach (string dependency in dependencies)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (IsPackageSatisfied(dependency))
|
||||
{
|
||||
Logger.LogInfo("Dependency \"" + dependency + "\" is already satisfied.");
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
uris.Add(new Uri(packagePath));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Could not process dependency package at path \"" + dependency + "\"", ex);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
IAsyncOperationWithProgress<DeploymentResult, DeploymentProgress> deploymentOperation = isSparsePackage
|
||||
? packageManager.AddPackageByUriAsync(new Uri(packagePath), new AddPackageOptions { ExternalLocationUri = new Uri(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)! + "\\WinUi3Apps"), ForceUpdateFromAnyVersion = true })
|
||||
: packageManager.AddPackageAsync(new Uri(packagePath), uris, DeploymentOptions.ForceApplicationShutdown);
|
||||
deploymentOperation.Get();
|
||||
|
||||
switch (deploymentOperation.Status)
|
||||
{
|
||||
case AsyncStatus.Error:
|
||||
Logger.LogError($"Registering {packagePath} failed. ErrorCode: {deploymentOperation.ErrorCode}, ErrorText: {deploymentOperation.GetResults().ErrorText}");
|
||||
break;
|
||||
case AsyncStatus.Canceled:
|
||||
Logger.LogError($"Registering {packagePath} was canceled.");
|
||||
break;
|
||||
case AsyncStatus.Completed:
|
||||
Logger.LogInfo($"Registering {packagePath} succeded.");
|
||||
break;
|
||||
default:
|
||||
Logger.LogDebug($"Registering {packagePath} package started.");
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError($"Exception thrown while trying to register package: {packagePath}", e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the package specified by the given path is already installed and satisfies the required version.
|
||||
/// </summary>
|
||||
/// <param name="packagePath">Path to the package.</param>
|
||||
/// <returns>True if the package is already installed and satisfies the required version, false otherwise.</returns>
|
||||
private static bool IsPackageSatisfied(string packagePath)
|
||||
{
|
||||
if (!GetPackageNameAndVersionFromAppx(packagePath, out string name, out PackageVersion version))
|
||||
{
|
||||
Logger.LogError("Could not get package name and version from dependency package at path \"" + packagePath + "\"");
|
||||
return false;
|
||||
}
|
||||
|
||||
PackageManager packageManager = new();
|
||||
|
||||
foreach (var package in packageManager.FindPackagesForUser(null))
|
||||
{
|
||||
if (package.Id.Name.Equals(name, StringComparison.OrdinalIgnoreCase) &&
|
||||
package.Id.Version.ToVersion() >= version.ToVersion())
|
||||
{
|
||||
Logger.LogInfo($@"Package ""{name}"" is already statisfied with version: {package.Id.Version}. Target version: {version}. PackagePath: {packagePath}");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Logger.LogInfo($@"Package ""{name}"" with version {version} is not satisfied. PackagePath: {packagePath}");
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the package name and version from the specified appx package file.
|
||||
/// </summary>
|
||||
/// <param name="packagePath">Path to the package file.</param>
|
||||
/// <param name="name">Output parameter for the package name.</param>
|
||||
/// <param name="packageVersion">Output parameter for the package version.</param>
|
||||
/// <returns>True if the package name and version were successfully retrieved, false otherwise.</returns>
|
||||
private static bool GetPackageNameAndVersionFromAppx(string packagePath, out string name, out PackageVersion packageVersion)
|
||||
{
|
||||
bool retValue = PowerToys.Interop.Package.GetPackageNameAndVersionFromAppx(packagePath, out name, out PowerToys.Interop.PACKAGE_VERSION packageVersionInterop);
|
||||
packageVersion = new PackageVersion
|
||||
{
|
||||
Major = packageVersionInterop.Major,
|
||||
Minor = packageVersionInterop.Minor,
|
||||
Build = packageVersionInterop.Build,
|
||||
Revision = packageVersionInterop.Revision,
|
||||
};
|
||||
return retValue;
|
||||
}
|
||||
|
||||
[GeneratedRegex("(^.+\\.(appx|msix|msixbundle)$)", RegexOptions.IgnoreCase)]
|
||||
private static partial Regex msixPackagePattern();
|
||||
}
|
||||
}
|
||||
30
src/Runner/Helpers/ProcessHelper.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace RunnerV2.Helpers
|
||||
{
|
||||
internal static class ProcessHelper
|
||||
{
|
||||
internal static void ScheudleProcessKill(string processName, int msDelay = 500)
|
||||
{
|
||||
new Thread(async () =>
|
||||
{
|
||||
Process[] processes = Process.GetProcessesByName(processName);
|
||||
|
||||
await Task.Delay(msDelay);
|
||||
foreach (var process in processes)
|
||||
{
|
||||
if (!process.HasExited)
|
||||
{
|
||||
process.Kill();
|
||||
}
|
||||
}
|
||||
}).Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
100
src/Runner/Helpers/QuickAccessHelper.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using ManagedCommon;
|
||||
|
||||
namespace RunnerV2.Helpers
|
||||
{
|
||||
internal static class QuickAccessHelper
|
||||
{
|
||||
private static Process _process = new Process();
|
||||
private static EventWaitHandle _showEvent = new(false, EventResetMode.AutoReset, "Local\\PowerToysQuickAccess__Show");
|
||||
private static EventWaitHandle _exitEvent = new(false, EventResetMode.AutoReset, "Local\\PowerToysQuickAccess__Exit");
|
||||
|
||||
public static void Start()
|
||||
{
|
||||
if (IsRunning)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.LogInfo("Starting Quick Access");
|
||||
|
||||
lock (_process)
|
||||
{
|
||||
string runnerPipeName = "\\\\.\\pipe\\powertoys_quick_access_runner_" + Guid.NewGuid();
|
||||
string appPipeName = "\\\\.\\pipe\\powertoys_quick_access_ui_" + Guid.NewGuid();
|
||||
|
||||
PowerToys.Interop.TwoWayPipeMessageIPCManaged quickAccessIpc = new(runnerPipeName, appPipeName, SettingsHelper.OnSettingsMessageReceived);
|
||||
|
||||
string exePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "WinUI3Apps\\PowerToys.QuickAccess.exe");
|
||||
|
||||
if (!File.Exists(exePath))
|
||||
{
|
||||
Logger.LogError($"Quick Access executable not found at path: {exePath}");
|
||||
return;
|
||||
}
|
||||
|
||||
_process = new Process();
|
||||
_process.StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = exePath,
|
||||
Arguments = $"--show-event=\"Local\\PowerToysQuickAccess__Show\" --exit-event=\"Local\\PowerToysQuickAccess__Exit\" --runner-pipe=\"{runnerPipeName}\" --app-pipe=\"{appPipeName}\"",
|
||||
};
|
||||
_process.Start();
|
||||
quickAccessIpc.Start();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsRunning
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return _process.StartInfo.FileName == string.Empty ? false : !_process.HasExited;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Show()
|
||||
{
|
||||
Start();
|
||||
|
||||
_showEvent.Set();
|
||||
}
|
||||
|
||||
public static void Stop()
|
||||
{
|
||||
if (!IsRunning)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.LogInfo("Stopping Quick Access");
|
||||
_exitEvent.Set();
|
||||
lock (_process)
|
||||
{
|
||||
if (!_process.HasExited)
|
||||
{
|
||||
_process.WaitForExit(2000);
|
||||
}
|
||||
|
||||
if (!_process.HasExited)
|
||||
{
|
||||
_process.Kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
297
src/Runner/Helpers/SettingsHelper.cs
Normal file
@@ -0,0 +1,297 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.IO.Pipelines;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Threading;
|
||||
using System.Windows.Documents;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
using RunnerV2.properties;
|
||||
using Update;
|
||||
|
||||
namespace RunnerV2.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// This class provides helper methods to interact with the PowerToys Settings window.
|
||||
/// </summary>
|
||||
internal static class SettingsHelper
|
||||
{
|
||||
public static bool Debugging { get; set; }
|
||||
|
||||
private static readonly SettingsUtils _settingsUtils = SettingsUtils.Default;
|
||||
private static Process? _process;
|
||||
private static TwoWayPipeMessageIPCManaged? _ipc;
|
||||
|
||||
public static void OpenSettingsWindow(bool showOobeWindow = false, bool showScoobeWindow = false, string? additionalArguments = null)
|
||||
{
|
||||
if (_process is not null && _ipc is not null && !_process.HasExited)
|
||||
{
|
||||
_ipc.Send($@"{{""ShowYourself"": ""{additionalArguments ?? "Dashboard"}""}}");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
_ipc?.End();
|
||||
_ipc = null;
|
||||
|
||||
// Arg 1: Executable path
|
||||
string executablePath = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) ?? throw new InvalidOperationException("No executable path found"), "WinUI3Apps", "PowerToys.Settings.exe");
|
||||
|
||||
// Arg 2,3: Pipe names
|
||||
Pipe settingsPipe = new();
|
||||
Pipe powertoysPipe = new();
|
||||
|
||||
string powerToysPipeName = @"\\.\pipe\powertoys_runner_" + Guid.NewGuid();
|
||||
string settingsPipeName = @"\\.\pipe\powertoys_settings_" + Guid.NewGuid();
|
||||
|
||||
// Arg 4: Process pid
|
||||
string currentProcessId = Environment.ProcessId.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
// Arg 5: Settings theme
|
||||
string theme = Program.GeneralSettings.Theme switch
|
||||
{
|
||||
"light" => "light",
|
||||
"dark" => "dark",
|
||||
"system" when ThemeHelpers.GetAppTheme() == AppTheme.Light => "light",
|
||||
"system" when ThemeHelpers.GetAppTheme() == AppTheme.Dark => "dark",
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
|
||||
// Arg 6: Elevated status
|
||||
string isElevated = Program.GeneralSettings.IsElevated ? "true" : "false";
|
||||
|
||||
// Arg 7: Is user an administrator
|
||||
string isAdmin = Program.GeneralSettings.IsAdmin ? "true" : "false";
|
||||
|
||||
// Arg 8: Show OOBE window
|
||||
string showOobeArg = showOobeWindow ? "true" : "false";
|
||||
|
||||
// Arg 9: Show SCOOBE window
|
||||
string showScoobeArg = showScoobeWindow ? "true" : "false";
|
||||
|
||||
// Arg 10: Are there additional settings window arguments
|
||||
string areThereadditionalArgs = string.IsNullOrEmpty(additionalArguments) ? "false" : "true";
|
||||
|
||||
string executableArgs = $"{powerToysPipeName} {settingsPipeName} {currentProcessId} {theme} {isElevated} {isAdmin} {showOobeArg} {showScoobeArg} {areThereadditionalArgs}";
|
||||
|
||||
if (!string.IsNullOrEmpty(additionalArguments))
|
||||
{
|
||||
executableArgs += $" {additionalArguments}";
|
||||
}
|
||||
|
||||
Logger.LogInfo($"Starting Settings with arguments: {executableArgs}");
|
||||
|
||||
_process = Process.Start(executablePath, executableArgs);
|
||||
|
||||
// Initialize listening to pipes
|
||||
_ipc = new TwoWayPipeMessageIPCManaged(powerToysPipeName, settingsPipeName, OnSettingsMessageReceived);
|
||||
_ipc.Start();
|
||||
}
|
||||
|
||||
public static void OnSettingsMessageReceived(string message)
|
||||
{
|
||||
if (Debugging)
|
||||
{
|
||||
Console.WriteLine("Received message from settings: " + message);
|
||||
}
|
||||
|
||||
JsonDocument messageDocument = JsonDocument.Parse(message);
|
||||
|
||||
foreach (var property in messageDocument.RootElement.EnumerateObject())
|
||||
{
|
||||
switch (property.Name)
|
||||
{
|
||||
case "action":
|
||||
foreach (var moduleName in property.Value.EnumerateObject())
|
||||
{
|
||||
if (moduleName.Name == "general")
|
||||
{
|
||||
switch (moduleName.Value.GetProperty("action_name").GetString())
|
||||
{
|
||||
case "restart_elevation":
|
||||
ElevationHelper.RestartScheduled = ElevationHelper.RestartScheduledMode.RestartElevatedWithOpenSettings;
|
||||
Runner.Close();
|
||||
break;
|
||||
case "restart_maintain_elevation":
|
||||
ElevationHelper.RestartScheduled = ElevationHelper.IsProcessElevated() ? ElevationHelper.RestartScheduledMode.RestartElevatedWithOpenSettings : ElevationHelper.RestartScheduledMode.RestartNonElevated;
|
||||
|
||||
ElevationHelper.RestartIfScheudled();
|
||||
|
||||
break;
|
||||
case "check_for_updates":
|
||||
var version = Assembly.GetExecutingAssembly().GetName().Version!;
|
||||
var versionString = "v" + version.Major + "." + version.Minor + "." + version.Build;
|
||||
UpdateSettingsHelper.TriggerUpdateCheck((version) => { PowerToys.Interop.Notifications.ShowUpdateAvailableNotification("PowerToys", Resources.UpdateNotification_Content + "\n" + versionString + " \u2192 " + version, "PTUpdateNotifyTag", Resources.UpdateNotification_UpdateNow, Resources.UpdateNotification_MoreInfo); });
|
||||
break;
|
||||
case "request_update_state_date":
|
||||
JsonObject response = [];
|
||||
response["updateStateDate"] = UpdateSettingsHelper.GetLastCheckedDate();
|
||||
_ipc?.Send(response.ToJsonString());
|
||||
break;
|
||||
default:
|
||||
Logger.LogWarning($"Received unknown general action from Settings: {moduleName.Value.GetProperty("action_name").GetString()}");
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (IPowerToysModule ptModule in Runner.LoadedModules)
|
||||
{
|
||||
if (ptModule.Name == moduleName.Name && ptModule is IPowerToysModuleCustomActionsProvider customActionsProvider && customActionsProvider.CustomActions.TryGetValue(moduleName.Value.GetProperty("action_name").GetString() ?? string.Empty, out Action<string>? action))
|
||||
{
|
||||
Logger.InitializeLogger("\\" + ptModule.Name + "\\ModuleInterface\\Logs");
|
||||
action(moduleName.Value.GetProperty("value").GetString() ?? string.Empty);
|
||||
Logger.InitializeLogger("\\RunnerLogs");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case "get_all_hotkey_conflicts":
|
||||
JsonNode hotkeyConflicts = HotkeyConflictsManager.GetHotkeyConflictsAsJson();
|
||||
hotkeyConflicts.Root["response_type"] = "all_hotkey_conflicts";
|
||||
_ipc?.Send(hotkeyConflicts.ToJsonString());
|
||||
break;
|
||||
case "check_hotkey_conflict":
|
||||
try
|
||||
{
|
||||
HotkeySettings hotkey = new(
|
||||
property.Value.GetProperty("win").GetBoolean(),
|
||||
property.Value.GetProperty("ctrl").GetBoolean(),
|
||||
property.Value.GetProperty("alt").GetBoolean(),
|
||||
property.Value.GetProperty("shift").GetBoolean(),
|
||||
property.Value.GetProperty("key").GetInt32());
|
||||
|
||||
string requestId = property.Value.GetProperty("request_id").GetString() ?? string.Empty;
|
||||
|
||||
bool hasConflict = HotkeyConflictsManager.HasConflict(hotkey);
|
||||
|
||||
JsonObject response = [];
|
||||
response["response_type"] = "hotkey_conflict_result";
|
||||
response["request_id"] = requestId;
|
||||
response["has_conflict"] = hasConflict;
|
||||
|
||||
if (hasConflict)
|
||||
{
|
||||
List<HotkeyConflictsManager.HotkeyConflict> conflicts = HotkeyConflictsManager.GetAllConflicts(hotkey);
|
||||
JsonArray allConflicts = [];
|
||||
foreach (HotkeyConflictsManager.HotkeyConflict conflict in conflicts)
|
||||
{
|
||||
allConflicts.Add(new JsonObject
|
||||
{
|
||||
["module"] = conflict.ModuleName,
|
||||
["hotkeyID"] = conflict.HotkeyID,
|
||||
});
|
||||
}
|
||||
|
||||
response["all_conflicts"] = allConflicts;
|
||||
}
|
||||
|
||||
_ipc?.Send(response.ToJsonString());
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "module_status":
|
||||
GeneralSettings generalSettings = _settingsUtils.GetSettings<GeneralSettings>();
|
||||
string nameOfModule = property.Value.EnumerateObject().First().Name;
|
||||
bool enabled = property.Value.EnumerateObject().First().Value.GetBoolean();
|
||||
ModuleHelper.SetIsModuleEnabled(generalSettings, ModuleHelper.GetModuleType(nameOfModule), enabled);
|
||||
SettingsUtils.Default.SaveSettings(generalSettings.ToJsonString(), string.Empty);
|
||||
return;
|
||||
case "bugreport":
|
||||
Logger.LogInfo("Starting bug report tool from Settings window");
|
||||
TrayIconManager.ProcessTrayMenuCommand((nuint)TrayIconManager.TrayButton.ReportBug);
|
||||
break;
|
||||
case "bug_report_status":
|
||||
_ipc?.Send($@"{{""bug_report_running"": {(TrayIconManager.IsBugReportToolRunning ? "true" : "false")}}}");
|
||||
break;
|
||||
case "killrunner":
|
||||
Runner.Close();
|
||||
break;
|
||||
case "general":
|
||||
try
|
||||
{
|
||||
_settingsUtils.SaveSettings(property.Value.ToString(), string.Empty);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Failed writing general settings from Settings window", ex);
|
||||
}
|
||||
|
||||
NativeMethods.PostMessageW(Runner.RunnerHwnd, (uint)NativeMethods.WindowMessages.REFRESH_SETTINGS, 0, 0);
|
||||
|
||||
foreach (IPowerToysModule module in Runner.ModulesToLoad)
|
||||
{
|
||||
if (module is IPowerToysModuleSettingsChangedSubscriber settingsChangedSubscriber)
|
||||
{
|
||||
Logger.InitializeLogger("\\" + module.Name + "\\ModuleInterface\\Logs");
|
||||
settingsChangedSubscriber.OnSettingsChanged();
|
||||
Logger.InitializeLogger("\\RunnerLogs");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case "powertoys":
|
||||
foreach (var powertoysSettingsPart in property.Value.EnumerateObject())
|
||||
{
|
||||
if (Runner.LoadedModules.Find(m => m.Name == powertoysSettingsPart.Name) is IPowerToysModuleSettingsChangedSubscriber module && module is IPowerToysModule ptModule && ptModule.Enabled)
|
||||
{
|
||||
Logger.InitializeLogger("\\" + ptModule.Name + "\\ModuleInterface\\Logs");
|
||||
SettingsUtils.Default.SaveSettings(powertoysSettingsPart.Value.ToString(), powertoysSettingsPart.Name);
|
||||
module.OnSettingsChanged();
|
||||
Logger.InitializeLogger("\\RunnerLogs");
|
||||
}
|
||||
else
|
||||
{
|
||||
// If no specific module was found, notify all enabled modules
|
||||
foreach (IPowerToysModule module2 in Runner.LoadedModules.Where(m => m.Enabled))
|
||||
{
|
||||
if (module2 is IPowerToysModuleSettingsChangedSubscriber settingsChangedSubscriber)
|
||||
{
|
||||
Logger.InitializeLogger("\\" + module2.Name + "\\ModuleInterface\\Logs");
|
||||
settingsChangedSubscriber.OnSettingsChanged();
|
||||
Logger.InitializeLogger("\\RunnerLogs");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NativeMethods.PostMessageW(Runner.RunnerHwnd, (uint)NativeMethods.WindowMessages.REFRESH_SETTINGS, 0, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
case "language":
|
||||
File.WriteAllText(SettingsUtils.Default.GetSettingsFilePath(fileName: "language.json"), @$"{{""{property.Name}"": ""{property.Value}""}}");
|
||||
break;
|
||||
default:
|
||||
Logger.LogWarning($"Received unknown message from Settings: {property.Name}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void CloseSettingsWindow()
|
||||
{
|
||||
using var closeEventWrapper = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.PowerToysRunnerTerminateSettingsEvent());
|
||||
closeEventWrapper.Set();
|
||||
}
|
||||
}
|
||||
}
|
||||
467
src/Runner/Helpers/TrayIconManager.cs
Normal file
@@ -0,0 +1,467 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
using RunnerV2.properties;
|
||||
using static RunnerV2.NativeMethods;
|
||||
|
||||
namespace RunnerV2.Helpers
|
||||
{
|
||||
internal static partial class TrayIconManager
|
||||
{
|
||||
private static bool _trayIconVisible;
|
||||
|
||||
private static nint GetTrayIcon()
|
||||
{
|
||||
if (SettingsUtils.Default.GetSettings<GeneralSettings>().ShowThemeAdaptiveTrayIcon)
|
||||
{
|
||||
return Icon.ExtractAssociatedIcon(ThemeHelper.GetCurrentSystemTheme() ? "./Assets/Runner/PowerToysDark.ico" : "./Assets/Runner/PowerToysLight.ico")!.Handle;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Icon.ExtractAssociatedIcon(Environment.ProcessPath!)!.Handle;
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateTrayIcon()
|
||||
{
|
||||
if (!_trayIconVisible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NOTIFYICONDATA notifyicondata = GetNOTIFYICONDATA();
|
||||
Shell_NotifyIcon(0x1, ref notifyicondata);
|
||||
}
|
||||
|
||||
private static NOTIFYICONDATA GetNOTIFYICONDATA() => new()
|
||||
{
|
||||
CbSize = (uint)Marshal.SizeOf<NOTIFYICONDATA>(),
|
||||
HWnd = Runner.RunnerHwnd,
|
||||
UId = 1,
|
||||
HIcon = GetTrayIcon(),
|
||||
UFlags = 0x0000001 | 0x00000002 | 0x4,
|
||||
UCallbackMessage = (uint)WindowMessages.ICON_NOTIFY,
|
||||
SzTip = "PowerToys v" + Assembly.GetExecutingAssembly().GetName().Version!.Major + "." + Assembly.GetExecutingAssembly().GetName().Version!.Minor + "." + Assembly.GetExecutingAssembly().GetName().Version!.Build,
|
||||
};
|
||||
|
||||
internal static void StartTrayIcon()
|
||||
{
|
||||
if (_trayIconVisible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NOTIFYICONDATA notifyicondata = GetNOTIFYICONDATA();
|
||||
ChangeWindowMessageFilterEx(Runner.RunnerHwnd, 0x0111, 0x0001, IntPtr.Zero);
|
||||
|
||||
Shell_NotifyIcon(NIMADD, ref notifyicondata);
|
||||
_trayIconVisible = true;
|
||||
}
|
||||
|
||||
internal static void StopTrayIcon()
|
||||
{
|
||||
if (!_trayIconVisible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NOTIFYICONDATA notifyicondata = new()
|
||||
{
|
||||
CbSize = (uint)Marshal.SizeOf<NOTIFYICONDATA>(),
|
||||
HWnd = Runner.RunnerHwnd,
|
||||
UId = 1,
|
||||
};
|
||||
|
||||
Shell_NotifyIcon(NIMDELETE, ref notifyicondata);
|
||||
_trayIconVisible = false;
|
||||
}
|
||||
|
||||
internal enum TrayButton : uint
|
||||
{
|
||||
Settings = 1,
|
||||
Documentation,
|
||||
ReportBug,
|
||||
Close,
|
||||
QuickAccess,
|
||||
DebugKeyboardShortcuts,
|
||||
DebugSettingsIpc,
|
||||
DebugWriteUncaughtExceptionsToConsole,
|
||||
DebugSendCustomMessage,
|
||||
DebugActivateModule,
|
||||
DebugDeactivateModule,
|
||||
DebugAllEnableModule,
|
||||
DebugAllDisableModule,
|
||||
DebugSendCustomAction,
|
||||
DebugListAllCustomActions,
|
||||
DebugListAllShortcuts,
|
||||
DebugFullModuleReport,
|
||||
}
|
||||
|
||||
private static bool _doubleClickTimerRunning;
|
||||
private static bool _doubleClickDetected;
|
||||
|
||||
private static IntPtr _trayIconMenu;
|
||||
|
||||
static TrayIconManager()
|
||||
{
|
||||
RegenerateRightClickMenu();
|
||||
new ThemeListener().ThemeChanged += (_) =>
|
||||
{
|
||||
PostMessageW(Runner.RunnerHwnd, 0x0800, IntPtr.Zero, 0x9000);
|
||||
};
|
||||
}
|
||||
|
||||
public static void RegenerateRightClickMenu()
|
||||
{
|
||||
_trayIconMenu = CreatePopupMenu();
|
||||
#if DEBUG
|
||||
IntPtr ipcMenu = CreateMenu();
|
||||
AppendMenuW(ipcMenu, 0u, new UIntPtr((uint)TrayButton.DebugSettingsIpc), "Toggle logging Settings IPC");
|
||||
AppendMenuW(ipcMenu, 0u, new UIntPtr((uint)TrayButton.DebugSendCustomMessage), "Send Custom Message To Runner");
|
||||
|
||||
IntPtr modulesMenu = CreateMenu();
|
||||
AppendMenuW(modulesMenu, 0u, new UIntPtr((uint)TrayButton.DebugFullModuleReport), "Full report on all modules");
|
||||
AppendMenuW(modulesMenu, 0x00000800u, UIntPtr.Zero, string.Empty); // serator
|
||||
AppendMenuW(modulesMenu, 0u, new UIntPtr((uint)TrayButton.DebugActivateModule), "Activate Module by name");
|
||||
AppendMenuW(modulesMenu, 0u, new UIntPtr((uint)TrayButton.DebugDeactivateModule), "Deactivate Module by name");
|
||||
AppendMenuW(modulesMenu, 0u, new UIntPtr((uint)TrayButton.DebugAllEnableModule), "Run all enable functions of all modules");
|
||||
AppendMenuW(modulesMenu, 0u, new UIntPtr((uint)TrayButton.DebugAllDisableModule), "Run all disable functions of all modules");
|
||||
AppendMenuW(modulesMenu, 0u, new UIntPtr((uint)TrayButton.DebugSendCustomAction), "Send Custom Action");
|
||||
AppendMenuW(modulesMenu, 0u, new UIntPtr((uint)TrayButton.DebugListAllCustomActions), "List all Custom Actions");
|
||||
AppendMenuW(modulesMenu, 0u, new UIntPtr((uint)TrayButton.DebugListAllShortcuts), "List all Shortcuts");
|
||||
|
||||
AppendMenuW(_trayIconMenu, 0x2u, UIntPtr.Zero, "Debug build options:");
|
||||
AppendMenuW(_trayIconMenu, 0x10u, (UIntPtr)ipcMenu, "Settings <-> Runner IPC");
|
||||
AppendMenuW(_trayIconMenu, 0x10u, (UIntPtr)modulesMenu, "Module interfaces");
|
||||
AppendMenuW(_trayIconMenu, 0u, new UIntPtr((uint)TrayButton.DebugKeyboardShortcuts), "Toggle logging Centralized Keyboard Hook");
|
||||
AppendMenuW(_trayIconMenu, 0u, new UIntPtr((uint)TrayButton.DebugWriteUncaughtExceptionsToConsole), "Toggle logging Uncaught Exceptions");
|
||||
AppendMenuW(_trayIconMenu, 0x00000800u, UIntPtr.Zero, string.Empty); // separator
|
||||
#endif
|
||||
if (SettingsUtils.Default.GetSettings<GeneralSettings>().EnableQuickAccess)
|
||||
{
|
||||
AppendMenuW(_trayIconMenu, 0u, new UIntPtr((uint)TrayButton.QuickAccess), Resources.ContextMenu_QuickAccess + "\t" + Resources.ContextMenu_LeftClick);
|
||||
AppendMenuW(_trayIconMenu, 0u, new UIntPtr((uint)TrayButton.Settings), Resources.ContextMenu_Settings + "\t" + Resources.ContextMenu_DoubleClick);
|
||||
}
|
||||
else
|
||||
{
|
||||
AppendMenuW(_trayIconMenu, 0u, new UIntPtr((uint)TrayButton.Settings), Resources.ContextMenu_Settings + "\t" + Resources.ContextMenu_LeftClick);
|
||||
}
|
||||
|
||||
AppendMenuW(_trayIconMenu, 0x00000800u, UIntPtr.Zero, string.Empty); // serator
|
||||
AppendMenuW(_trayIconMenu, 0u, new UIntPtr((uint)TrayButton.Documentation), Resources.ContextMenu_Documentation);
|
||||
AppendMenuW(_trayIconMenu, 0u, new UIntPtr((uint)TrayButton.ReportBug), Resources.ContextMenu_ReportBug);
|
||||
AppendMenuW(_trayIconMenu, 0x00000800u, UIntPtr.Zero, string.Empty); // separator
|
||||
AppendMenuW(_trayIconMenu, 0u, new UIntPtr((uint)TrayButton.Close), Resources.ContextMenu_Close);
|
||||
}
|
||||
|
||||
internal static void ProcessTrayIconMessage(long lParam)
|
||||
{
|
||||
switch (lParam)
|
||||
{
|
||||
case 0x0205: // WM_RBUTTONDBLCLK
|
||||
case 0x007B: // WM_CONTEXTMENU
|
||||
SetForegroundWindow(Runner.RunnerHwnd);
|
||||
TrackPopupMenu(_trayIconMenu, 0x0004 | 0x0020, Cursor.Position.X, Cursor.Position.Y, 0, Runner.RunnerHwnd, IntPtr.Zero);
|
||||
break;
|
||||
case 0x0202: // WM_LBUTTONUP
|
||||
if (_doubleClickTimerRunning)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
_doubleClickTimerRunning = true;
|
||||
Task.Delay(SystemInformation.DoubleClickTime).ContinueWith(_ =>
|
||||
{
|
||||
if (!_doubleClickDetected)
|
||||
{
|
||||
if (SettingsUtils.Default.GetSettings<GeneralSettings>().EnableQuickAccess)
|
||||
{
|
||||
QuickAccessHelper.Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
SettingsHelper.OpenSettingsWindow();
|
||||
}
|
||||
}
|
||||
|
||||
_doubleClickDetected = false;
|
||||
_doubleClickTimerRunning = false;
|
||||
});
|
||||
break;
|
||||
case 0x0203: // WM_LBUTTONDBLCLK
|
||||
_doubleClickDetected = true;
|
||||
SettingsHelper.OpenSettingsWindow();
|
||||
break;
|
||||
case 0x9000: // Update tray icon
|
||||
UpdateTrayIcon();
|
||||
RegenerateRightClickMenu();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool IsBugReportToolRunning { get; set; }
|
||||
|
||||
internal static void ProcessTrayMenuCommand(nuint commandId)
|
||||
{
|
||||
switch ((TrayButton)commandId)
|
||||
{
|
||||
case TrayButton.Settings:
|
||||
SettingsHelper.OpenSettingsWindow();
|
||||
break;
|
||||
case TrayButton.QuickAccess:
|
||||
QuickAccessHelper.Show();
|
||||
break;
|
||||
case TrayButton.Documentation:
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = "https://aka.ms/PowerToysOverview",
|
||||
UseShellExecute = true,
|
||||
});
|
||||
break;
|
||||
case TrayButton.ReportBug:
|
||||
Logger.LogInfo("Starting bug report tool from tray menu");
|
||||
Process bugReportProcess = new();
|
||||
bugReportProcess.StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "Tools\\PowerToys.BugReportTool.exe",
|
||||
CreateNoWindow = true,
|
||||
};
|
||||
|
||||
bugReportProcess.EnableRaisingEvents = true;
|
||||
|
||||
EnableMenuItem(_trayIconMenu, (uint)TrayButton.ReportBug, 0x000000 | 0x00001);
|
||||
|
||||
bugReportProcess.Exited += (sender, e) =>
|
||||
{
|
||||
bugReportProcess.Dispose();
|
||||
EnableMenuItem(_trayIconMenu, (uint)TrayButton.ReportBug, 0x00000000);
|
||||
IsBugReportToolRunning = false;
|
||||
Logger.LogInfo("Bug report tool exited");
|
||||
};
|
||||
|
||||
bugReportProcess.Start();
|
||||
IsBugReportToolRunning = true;
|
||||
|
||||
break;
|
||||
case TrayButton.Close:
|
||||
Runner.Close();
|
||||
break;
|
||||
#if DEBUG
|
||||
case TrayButton.DebugKeyboardShortcuts:
|
||||
AllocConsole();
|
||||
CentralizedKeyboardHookManager.DebugConsole = !CentralizedKeyboardHookManager.DebugConsole;
|
||||
break;
|
||||
case TrayButton.DebugSettingsIpc:
|
||||
AllocConsole();
|
||||
SettingsHelper.Debugging = !SettingsHelper.Debugging;
|
||||
break;
|
||||
case TrayButton.DebugWriteUncaughtExceptionsToConsole:
|
||||
AllocConsole();
|
||||
Runner.DebbugingLogUncaughtExceptions = !Runner.DebbugingLogUncaughtExceptions;
|
||||
break;
|
||||
case TrayButton.DebugSendCustomMessage:
|
||||
AllocConsole();
|
||||
Console.Write("Enter the message you want to send to the Runner process: ");
|
||||
string? message = Console.ReadLine();
|
||||
if (string.IsNullOrEmpty(message))
|
||||
{
|
||||
Console.WriteLine("No message entered. Aborting.");
|
||||
return;
|
||||
}
|
||||
|
||||
SettingsHelper.OnSettingsMessageReceived(message);
|
||||
break;
|
||||
case TrayButton.DebugActivateModule:
|
||||
AllocConsole();
|
||||
Console.Write("Enter the name of the module you want to activate: ");
|
||||
string? moduleToActivate = Console.ReadLine();
|
||||
if (string.IsNullOrEmpty(moduleToActivate))
|
||||
{
|
||||
Console.WriteLine("No module name entered. Aborting.");
|
||||
return;
|
||||
}
|
||||
|
||||
SettingsHelper.OnSettingsMessageReceived("{\"module_status\": {\"" + moduleToActivate + "\": true}}");
|
||||
break;
|
||||
case TrayButton.DebugDeactivateModule:
|
||||
AllocConsole();
|
||||
Console.Write("Enter the name of the module you want to deactivate: ");
|
||||
string? moduleToDeactivate = Console.ReadLine();
|
||||
if (string.IsNullOrEmpty(moduleToDeactivate))
|
||||
{
|
||||
Console.WriteLine("No module name entered. Aborting.");
|
||||
return;
|
||||
}
|
||||
|
||||
SettingsHelper.OnSettingsMessageReceived("{\"module_status\": {\"" + moduleToDeactivate + "\": false}}");
|
||||
break;
|
||||
|
||||
case TrayButton.DebugAllEnableModule:
|
||||
AllocConsole();
|
||||
foreach (var module in Runner.ModulesToLoad)
|
||||
{
|
||||
module.Enable();
|
||||
}
|
||||
|
||||
Console.WriteLine("All enabled functions run.");
|
||||
break;
|
||||
case TrayButton.DebugAllDisableModule:
|
||||
AllocConsole();
|
||||
foreach (var module in Runner.ModulesToLoad)
|
||||
{
|
||||
module.Disable();
|
||||
}
|
||||
|
||||
Console.WriteLine("All disable functions run.");
|
||||
break;
|
||||
case TrayButton.DebugSendCustomAction:
|
||||
AllocConsole();
|
||||
Console.Write("Enter the name of the module you want to send the action to: ");
|
||||
string? moduleName = Console.ReadLine();
|
||||
if (string.IsNullOrEmpty(moduleName))
|
||||
{
|
||||
Console.WriteLine("No module name entered. Aborting.");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.Write("Enter the name of the action you want to send: ");
|
||||
string? actionName = Console.ReadLine();
|
||||
if (string.IsNullOrEmpty(actionName))
|
||||
{
|
||||
Console.WriteLine("No action name entered. Aborting.");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.Write("Enter the data you want to send with the action (or leave empty for no data): ");
|
||||
string? actionData = Console.ReadLine();
|
||||
if (actionData is null)
|
||||
{
|
||||
Console.WriteLine("No action data entered. Aborting.");
|
||||
return;
|
||||
}
|
||||
|
||||
SettingsHelper.OnSettingsMessageReceived("{\"action\": {\"" + moduleName + "\": {\"action_name\": \"" + actionName + "\", \"value\": \"" + actionData + "\"}}}");
|
||||
break;
|
||||
case TrayButton.DebugListAllCustomActions:
|
||||
AllocConsole();
|
||||
Console.Write("Name of the module whose custom actions you want to list: ");
|
||||
string? moduleNameForCustomActions = Console.ReadLine();
|
||||
if (string.IsNullOrEmpty(moduleNameForCustomActions))
|
||||
{
|
||||
Console.WriteLine("No module name entered. Aborting.");
|
||||
return;
|
||||
}
|
||||
|
||||
var moduleForCustomActions = Runner.ModulesToLoad.FirstOrDefault(m => m.Name.Equals(moduleNameForCustomActions, StringComparison.OrdinalIgnoreCase));
|
||||
if (moduleForCustomActions == null)
|
||||
{
|
||||
Console.WriteLine("No module with that name found. Aborting.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (moduleForCustomActions is not IPowerToysModuleCustomActionsProvider customActionsProvider)
|
||||
{
|
||||
Console.WriteLine("Module does not provide custom actions. Aborting.");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var customAction in customActionsProvider.CustomActions)
|
||||
{
|
||||
Console.WriteLine("Action name: " + customAction.Key);
|
||||
}
|
||||
|
||||
break;
|
||||
case TrayButton.DebugListAllShortcuts:
|
||||
AllocConsole();
|
||||
Console.Write("Name of the module whose shortcuts you want to list: ");
|
||||
string? moduleNameForShortcuts = Console.ReadLine();
|
||||
if (string.IsNullOrEmpty(moduleNameForShortcuts))
|
||||
{
|
||||
Console.WriteLine("No module name entered. Aborting.");
|
||||
return;
|
||||
}
|
||||
|
||||
var moduleForShortcuts = Runner.ModulesToLoad.FirstOrDefault(m => m.Name.Equals(moduleNameForShortcuts, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (moduleForShortcuts == null)
|
||||
{
|
||||
Console.WriteLine("No module with that name found. Aborting.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (moduleForShortcuts is not IPowerToysModuleShortcutsProvider shortcutsProvider)
|
||||
{
|
||||
Console.WriteLine("Module does not provide shortcuts. Aborting.");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var shortcut in shortcutsProvider.Shortcuts)
|
||||
{
|
||||
Console.WriteLine("Shortcut: " + shortcut.Hotkey.ToString());
|
||||
}
|
||||
|
||||
break;
|
||||
case TrayButton.DebugFullModuleReport:
|
||||
AllocConsole();
|
||||
static string GpoRuleToString(GpoRuleConfigured g) => g switch
|
||||
{
|
||||
GpoRuleConfigured.WrongValue => "Wrong value",
|
||||
GpoRuleConfigured.Unavailable => "Unavailable",
|
||||
GpoRuleConfigured.NotConfigured => "Not configured",
|
||||
GpoRuleConfigured.Disabled => "Disabled",
|
||||
GpoRuleConfigured.Enabled => "Enabled",
|
||||
_ => "Unknown",
|
||||
};
|
||||
|
||||
Console.WriteLine("=============================");
|
||||
Console.WriteLine("=Full report of all modules:=");
|
||||
Console.WriteLine("=============================");
|
||||
foreach (var module in Runner.ModulesToLoad)
|
||||
{
|
||||
Console.WriteLine("Module name: " + module.Name);
|
||||
Console.WriteLine("Enabled: " + module.Enabled);
|
||||
Console.WriteLine("GPO configured: " + GpoRuleToString(module.GpoRuleConfigured));
|
||||
if (module is ProcessModuleAbstractClass pmac)
|
||||
{
|
||||
Console.WriteLine("Process name: " + pmac.ProcessName);
|
||||
Console.WriteLine("Process path: " + pmac.ProcessPath);
|
||||
Console.WriteLine("Launch options: " + pmac.LaunchOptions);
|
||||
Console.WriteLine("Launch arguments: " + pmac.ProcessArguments);
|
||||
Console.WriteLine("Is running: " + pmac.IsProcessRunning());
|
||||
}
|
||||
|
||||
if (module is IPowerToysModuleCustomActionsProvider ptmcap)
|
||||
{
|
||||
Console.WriteLine("Custom actions: " + string.Join(", ", ptmcap.CustomActions.Keys));
|
||||
}
|
||||
|
||||
if (module is IPowerToysModuleShortcutsProvider ptmscp)
|
||||
{
|
||||
Console.WriteLine("Shortcuts: " + string.Join(", ", ptmscp.Shortcuts.Select(s => s.Hotkey.ToString())));
|
||||
}
|
||||
|
||||
Console.WriteLine("Is subscribed to settings changes: " + (module is IPowerToysModuleSettingsChangedSubscriber));
|
||||
|
||||
Console.WriteLine("-----------------------------");
|
||||
}
|
||||
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
47
src/Runner/Models/IPowerToysModule.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
// 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.Text.Json;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
|
||||
namespace RunnerV2.Models
|
||||
{
|
||||
public interface IPowerToysModule
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the short name of the module. The same used as the name of the folder containing its settings.
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// This function is called when the module is enabled.
|
||||
/// </summary>
|
||||
public void Enable();
|
||||
|
||||
/// <summary>
|
||||
/// This function is called when the module is disabled.
|
||||
/// </summary>
|
||||
public void Disable();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the module is enabled.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value shall be read from the settings of the module in the module interface implementation.
|
||||
/// </remarks>
|
||||
public bool Enabled { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the GPO rule configured state for the module.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value shall be read from the GPO settings with the <see cref="GPOWrapper"/> class.
|
||||
/// </remarks>
|
||||
public GpoRuleConfigured GpoRuleConfigured { get; }
|
||||
}
|
||||
}
|
||||
17
src/Runner/Models/IPowerToysModuleCustomActionsProvider.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
// 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 RunnerV2.Models
|
||||
{
|
||||
internal interface IPowerToysModuleCustomActionsProvider
|
||||
{
|
||||
public Dictionary<string, Action<string>> CustomActions { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// 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 RunnerV2.Models
|
||||
{
|
||||
internal interface IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public void OnSettingsChanged();
|
||||
}
|
||||
}
|
||||
21
src/Runner/Models/IPowerToysModuleShortcutsProvider.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
// 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 Microsoft.PowerToys.Settings.UI.Library;
|
||||
|
||||
namespace RunnerV2.Models
|
||||
{
|
||||
internal interface IPowerToysModuleShortcutsProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a list of shortcuts, that shall be registered in the keyboard hook, and their associated actions.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If this property is not overridden, the module is considered to not have shortcuts.
|
||||
/// </remarks>
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; }
|
||||
}
|
||||
}
|
||||
186
src/Runner/Models/ProcessModuleAbstractClass.cs
Normal file
@@ -0,0 +1,186 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using ManagedCommon;
|
||||
using RunnerV2.Helpers;
|
||||
|
||||
namespace RunnerV2.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Base abstract class for modules that launch and manage external processes.
|
||||
/// </summary>
|
||||
internal abstract class ProcessModuleAbstractClass
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for launching a process.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum ProcessLaunchOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Only a single instance of the process should be running.
|
||||
/// </summary>
|
||||
SingletonProcess = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Elevate the process if the current process is elevated.
|
||||
/// </summary>
|
||||
ElevateIfApplicable = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Provide the runner process ID as the first argument to the launched process.
|
||||
/// </summary>
|
||||
RunnerProcessIdAsFirstArgument = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the application should not launch automatically when the specified module is enabled.
|
||||
/// </summary>
|
||||
SupressLaunchOnModuleEnabled = 8,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies that the process should be started using the operating system shell.
|
||||
/// </summary>
|
||||
UseShellExecute = 16,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the process should never exit automatically.
|
||||
/// </summary>
|
||||
/// <remarks>Use this value when using a helper process to launch an application like explorer.exe.</remarks>
|
||||
NeverExit = 32,
|
||||
|
||||
/// <summary>
|
||||
/// Suppresses UI when process is launched.
|
||||
/// </summary>
|
||||
HideUI = 64,
|
||||
|
||||
/// <summary>
|
||||
/// Sets the launched process to realtime priority.
|
||||
/// </summary>
|
||||
RealtimePriority = 128,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the process should never be launched with elevated privileges, even if the runner process is elevated.
|
||||
/// </summary>
|
||||
NeverElevate = 256,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the relative or absolute path to the process executable.
|
||||
/// </summary>
|
||||
public abstract string ProcessPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the process without the .exe extension.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Has no effect if the <see cref="LaunchOptions"/> has the <see cref="ProcessLaunchOptions.UseShellExecute"/> flag set.
|
||||
/// </remarks>
|
||||
public abstract string ProcessName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the arguments to pass to the process on launch.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If not overridden, no arguments are passed.
|
||||
/// If the <see cref="LaunchOptions"/> has the <see cref="ProcessLaunchOptions.RunnerProcessIdAsFirstArgument"/> flag is set, the runner process ID is prepended to these arguments.
|
||||
/// </remarks>
|
||||
public virtual string ProcessArguments { get; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the options used to configure how the process is launched.
|
||||
/// </summary>
|
||||
public abstract ProcessLaunchOptions LaunchOptions { get; }
|
||||
|
||||
public bool IsProcessRunning()
|
||||
{
|
||||
return Process.GetProcessesByName(ProcessName).Length > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that atleast one process is launched. If the process is already running, does nothing.
|
||||
/// </summary>
|
||||
public void EnsureLaunched()
|
||||
{
|
||||
Process[] processes = Process.GetProcessesByName(ProcessName);
|
||||
if (processes.Length > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LaunchProcess();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Launches the process with the specified options.
|
||||
/// </summary>
|
||||
/// <param name="isModuleEnableProcess">Specifies if the <see cref="Runner"/> class is currently calling this function as part of a module startup</param>
|
||||
public void LaunchProcess(bool isModuleEnableProcess = false)
|
||||
{
|
||||
if (isModuleEnableProcess && LaunchOptions.HasFlag(ProcessLaunchOptions.SupressLaunchOnModuleEnabled))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (LaunchOptions.HasFlag(ProcessLaunchOptions.SingletonProcess))
|
||||
{
|
||||
Process[] processes = Process.GetProcessesByName(ProcessName);
|
||||
if (processes.Length > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
string arguments = (LaunchOptions.HasFlag(ProcessLaunchOptions.RunnerProcessIdAsFirstArgument) ? Environment.ProcessId.ToString(CultureInfo.InvariantCulture) + (string.IsNullOrEmpty(ProcessArguments) ? string.Empty : " ") : string.Empty) + ProcessArguments;
|
||||
|
||||
if (ElevationHelper.IsProcessElevated() && LaunchOptions.HasFlag(ProcessLaunchOptions.NeverElevate))
|
||||
{
|
||||
PowerToys.Interop.Elevation.RunNonElevated(Path.GetFullPath(ProcessPath), arguments);
|
||||
return;
|
||||
}
|
||||
|
||||
Process? p = Process.Start(new ProcessStartInfo()
|
||||
{
|
||||
UseShellExecute = LaunchOptions.HasFlag(ProcessLaunchOptions.UseShellExecute),
|
||||
FileName = ProcessPath,
|
||||
Arguments = arguments,
|
||||
Verb = LaunchOptions.HasFlag(ProcessLaunchOptions.ElevateIfApplicable) && ElevationHelper.IsProcessElevated() ? "runas" : "open",
|
||||
});
|
||||
|
||||
if (LaunchOptions.HasFlag(ProcessLaunchOptions.RealtimePriority))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (p != null && !p.HasExited)
|
||||
{
|
||||
p.PriorityClass = ProcessPriorityClass.RealTime;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Failed to set realtime priority for process {ProcessName}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Schedules all processes with the specified <see cref="ProcessName"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the <see cref="LaunchOptions"/> has the <see cref="ProcessLaunchOptions.NeverExit"/> flag set, this function does nothing.
|
||||
/// </remarks>
|
||||
public void ProcessExit()
|
||||
{
|
||||
if (LaunchOptions.HasFlag(ProcessLaunchOptions.NeverExit))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ProcessHelper.ScheudleProcessKill(ProcessName);
|
||||
}
|
||||
}
|
||||
}
|
||||
45
src/Runner/Models/RegistryChangeSet.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
// 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 RunnerV2.Models
|
||||
{
|
||||
internal readonly struct RegistryChangeSet
|
||||
{
|
||||
public RegistryValueChange[] Changes { get; init; }
|
||||
|
||||
public readonly bool IsApplied => Changes.All(c => c.IsApplied);
|
||||
|
||||
public readonly bool Apply()
|
||||
{
|
||||
bool allApplied = true;
|
||||
foreach (var change in Changes)
|
||||
{
|
||||
allApplied = (change.Apply() || !change.Required) && allApplied;
|
||||
}
|
||||
|
||||
return allApplied;
|
||||
}
|
||||
|
||||
public readonly bool ApplyIfNotApplied() => IsApplied || Apply();
|
||||
|
||||
public readonly bool UnApplyIfApplied() => !IsApplied || UnApply();
|
||||
|
||||
public readonly bool UnApply()
|
||||
{
|
||||
bool allUnapplied = true;
|
||||
foreach (var change in Changes)
|
||||
{
|
||||
allUnapplied = (change.UnApply() || !change.Required) && allUnapplied;
|
||||
}
|
||||
|
||||
return allUnapplied;
|
||||
}
|
||||
}
|
||||
}
|
||||
124
src/Runner/Models/RegistryValueChange.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
// 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 ManagedCommon;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace RunnerV2.Models
|
||||
{
|
||||
internal readonly struct RegistryValueChange
|
||||
{
|
||||
public RegistryValueChange()
|
||||
{
|
||||
}
|
||||
|
||||
public required string KeyPath { get; init; }
|
||||
|
||||
public required string? KeyName { get; init; }
|
||||
|
||||
public bool Required { get; init; } = true;
|
||||
|
||||
public required object Value { get; init; }
|
||||
|
||||
public RegistryHive Scope { get; init; } = RegistryHive.CurrentUser;
|
||||
|
||||
private static RegistryValueKind ValueTypeToRegistryValueKind(object value)
|
||||
{
|
||||
return value switch
|
||||
{
|
||||
int => RegistryValueKind.DWord,
|
||||
long => RegistryValueKind.QWord,
|
||||
string => RegistryValueKind.String,
|
||||
string[] => RegistryValueKind.MultiString,
|
||||
byte[] => RegistryValueKind.Binary,
|
||||
_ => throw new ArgumentException("Unsupported value type"),
|
||||
};
|
||||
}
|
||||
|
||||
public readonly bool IsApplied
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
using RegistryKey? key = RegistryKey.OpenBaseKey(Scope, RegistryView.Default).OpenSubKey(KeyPath, false);
|
||||
return key != null && ValueTypeToRegistryValueKind(Value) == key.GetValueKind(KeyName) && Value.Equals(key.GetValue(KeyName));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError($"Testing if registry change \"{this}\" is applied failed.", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public readonly bool RequiresElevation
|
||||
{
|
||||
get => Scope == RegistryHive.LocalMachine;
|
||||
}
|
||||
|
||||
public readonly bool Apply()
|
||||
{
|
||||
try
|
||||
{
|
||||
using RegistryKey? key = RegistryKey.OpenBaseKey(Scope, RegistryView.Default).CreateSubKey(KeyPath, true);
|
||||
if (key == null)
|
||||
{
|
||||
Logger.LogError($"Applying registry change \"{this}\" failed because the registry key could not be created.");
|
||||
return false;
|
||||
}
|
||||
|
||||
key.SetValue(KeyName, Value, ValueTypeToRegistryValueKind(Value));
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError($"Applying registry change \"{this}\" failed.", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly bool UnApply()
|
||||
{
|
||||
try
|
||||
{
|
||||
using RegistryKey? key = RegistryKey.OpenBaseKey(Scope, RegistryView.Default).OpenSubKey(KeyPath, true);
|
||||
if (key == null)
|
||||
{
|
||||
Logger.LogError($"Unapplying registry change \"{this}\" failed because the registry key could not be opened.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (KeyName is not null)
|
||||
{
|
||||
key.DeleteValue(KeyName, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
key.SetValue(null, string.Empty); // Delete the default value
|
||||
}
|
||||
|
||||
// Check if the path doesn't contain anything and delete it if so
|
||||
if (key.GetValueNames().Length == 0 && key.GetSubKeyNames().Length == 0)
|
||||
{
|
||||
RegistryKey.OpenBaseKey(Scope, RegistryView.Default).DeleteSubKey(KeyPath, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError($"Unapplying registry change \"{this}\" failed.", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override readonly string ToString() => $"{RegistryKey.OpenBaseKey(Scope, RegistryView.Default).Name}\\{KeyPath}\\{KeyName}:{Value}";
|
||||
}
|
||||
}
|
||||
16
src/Runner/Models/SpecialMode.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
// 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 RunnerV2.Models
|
||||
{
|
||||
internal enum SpecialMode
|
||||
{
|
||||
None,
|
||||
Win32ToastNotificationCOMServer,
|
||||
DisableCantDragElevatedNotification,
|
||||
UpdateNow,
|
||||
ReportSuccessfulUpdate,
|
||||
CouldntToggleFileExplorerModulesNotification,
|
||||
}
|
||||
}
|
||||
102
src/Runner/ModuleInterfaces/AdvancedPasteModuleInterface.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
// 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.Json;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Interop;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class AdvancedPasteModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IDisposable, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "AdvancedPaste";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.AdvancedPaste;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredAdvancedPasteEnabledValue();
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
if (_ipc != null)
|
||||
{
|
||||
_ipc.Send(Constants.AdvancedPasteTerminateAppMessage());
|
||||
_ipc.End();
|
||||
_ipc = null;
|
||||
}
|
||||
}
|
||||
|
||||
private const string IpcName = @"\\.\pipe\PowerToys.AdvancedPaste";
|
||||
private TwoWayPipeMessageIPCManaged? _ipc;
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
_ipc = new TwoWayPipeMessageIPCManaged(@"\\.\pipe\PowerToys.AdvancedPast.Input", IpcName, (_) => { });
|
||||
_ipc.Start();
|
||||
|
||||
PopulateShortcuts();
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
PopulateShortcuts();
|
||||
}
|
||||
|
||||
public void PopulateShortcuts()
|
||||
{
|
||||
_ipc ??= new TwoWayPipeMessageIPCManaged(@"\\.\pipe\PowerToys.AdvancedPast.Input", @"\\.\pipe\PowerToys.AdvancedPaste", (_) => { });
|
||||
|
||||
Shortcuts.Clear();
|
||||
|
||||
AdvancedPasteSettings settings = SettingsUtils.Default.GetSettingsOrDefault<AdvancedPasteSettings>(Name);
|
||||
Shortcuts.Add((settings.Properties.AdvancedPasteUIShortcut, () =>
|
||||
_ipc.Send(Constants.AdvancedPasteShowUIMessage())
|
||||
));
|
||||
Shortcuts.Add((settings.Properties.PasteAsPlainTextShortcut, TryToPasteAsPlainText));
|
||||
Shortcuts.Add((settings.Properties.PasteAsMarkdownShortcut, () => _ipc.Send(Constants.AdvancedPasteMarkdownMessage())));
|
||||
Shortcuts.Add((settings.Properties.PasteAsJsonShortcut, () => _ipc.Send(Constants.AdvancedPasteJsonMessage())));
|
||||
|
||||
HotkeyAccessor[] hotkeyAccessors = settings.GetAllHotkeyAccessors();
|
||||
int additionalActionsCount = settings.Properties.AdditionalActions.GetAllActions().Count() - 2;
|
||||
for (int i = 0; i < additionalActionsCount; i++)
|
||||
{
|
||||
int scopedI = i;
|
||||
Shortcuts.Add((hotkeyAccessors[4 + i].Value, () => _ipc.Send(Constants.AdvancedPasteAdditionalActionMessage() + " " + (3 + scopedI))));
|
||||
}
|
||||
|
||||
for (int i = 4 + additionalActionsCount; i < hotkeyAccessors.Length; i++)
|
||||
{
|
||||
int scopedI = i;
|
||||
Shortcuts.Add((hotkeyAccessors[i].Value, () => _ipc.Send(Constants.AdvancedPasteCustomActionMessage() + " " + (scopedI - 4 - additionalActionsCount))));
|
||||
}
|
||||
}
|
||||
|
||||
private void TryToPasteAsPlainText()
|
||||
{
|
||||
PowerToys.Interop.Clipboard.PasteAsPlainText();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_ipc?.Dispose();
|
||||
}
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
public override string ProcessPath => "WinUI3Apps\\PowerToys.AdvancedPaste.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.AdvancedPaste";
|
||||
|
||||
public override string ProcessArguments => IpcName;
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument;
|
||||
}
|
||||
}
|
||||
59
src/Runner/ModuleInterfaces/AlwaysOnTopModuleInterface.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class AlwaysOnTopModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.AlwaysOnTop;
|
||||
|
||||
public string Name => "AlwaysOnTop";
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredAlwaysOnTopEnabledValue();
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
using var terminateEventWrapper = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.AlwaysOnTopTerminateEvent());
|
||||
terminateEventWrapper.Set();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
InitializeHotkey();
|
||||
}
|
||||
|
||||
private void InitializeHotkey()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
Shortcuts.Add((SettingsUtils.Default.GetSettings<AlwaysOnTopSettings>(Name).Properties.Hotkey.Value, () =>
|
||||
{
|
||||
using var pinEventWrapper = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.AlwaysOnTopPinEvent());
|
||||
pinEventWrapper.Set();
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
InitializeHotkey();
|
||||
}
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
public override string ProcessPath => "PowerToys.AlwaysOnTop.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.AlwaysOnTop";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument | ProcessLaunchOptions.ElevateIfApplicable;
|
||||
}
|
||||
}
|
||||
41
src/Runner/ModuleInterfaces/AwakeModuleInterface.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class AwakeModuleInterface : ProcessModuleAbstractClass, IPowerToysModule
|
||||
{
|
||||
public string Name => "Awake";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.Awake;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredAwakeEnabledValue();
|
||||
|
||||
public override string ProcessPath => "PowerToys.Awake.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.Awake";
|
||||
|
||||
public override string ProcessArguments => $"--use-pt-config --pid {Environment.ProcessId.ToString(CultureInfo.InvariantCulture)}";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
using var terminateEventWrapper = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.AwakeExitEvent());
|
||||
terminateEventWrapper.Set();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
80
src/Runner/ModuleInterfaces/CmdNotFoundModuleInterface.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using ManagedCommon;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class CmdNotFoundModuleInterface : IPowerToysModule
|
||||
{
|
||||
public string Name => "CmdNotFound";
|
||||
|
||||
public bool Enabled => true;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredCmdNotFoundEnabledValue();
|
||||
|
||||
public CmdNotFoundModuleInterface()
|
||||
{
|
||||
if (GpoRuleConfigured == GpoRuleConfigured.Disabled)
|
||||
{
|
||||
UninstallModule();
|
||||
}
|
||||
|
||||
if (GpoRuleConfigured == GpoRuleConfigured.Enabled)
|
||||
{
|
||||
InstallModule();
|
||||
}
|
||||
}
|
||||
|
||||
public void InstallModule()
|
||||
{
|
||||
Logger.LogInfo("Installing Command Not Found module invoked through GPO");
|
||||
|
||||
new Thread(async () =>
|
||||
{
|
||||
Process p = Process.Start("pwsh.exe", "-NoProfile -NonInteractive -NoLogo -WindowStyle Hidden -ExecutionPolicy Unrestricted -File \"" + Path.GetDirectoryName(Environment.ProcessPath) + "\\WinUI3Apps\\Assets\\Settings\\Scripts\\EnableModule.ps1" + "\"" + " -scriptPath \"" + Path.GetDirectoryName(Environment.ProcessPath) + "\"");
|
||||
await p.WaitForExitAsync();
|
||||
if (p.ExitCode == 0)
|
||||
{
|
||||
Logger.LogInfo("Command Not Found was successfully installed.");
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.LogInfo("Command Not Found failed to install with exit code: " + p.ExitCode);
|
||||
}).Start();
|
||||
}
|
||||
|
||||
public void UninstallModule()
|
||||
{
|
||||
Logger.LogInfo("Uninstalling Command Not Found module invoked through GPO");
|
||||
|
||||
new Thread(async () =>
|
||||
{
|
||||
Process p = Process.Start("pwsh.exe", "-NoProfile -NonInteractive -NoLogo -WindowStyle Hidden -ExecutionPolicy Unrestricted -File \"" + Path.GetDirectoryName(Environment.ProcessPath) + "\\WinUI3Apps\\Assets\\Settings\\Scripts\\DisableModule.ps1" + "\"" + " -scriptPath \"" + Path.GetDirectoryName(Environment.ProcessPath) + "\"");
|
||||
await p.WaitForExitAsync();
|
||||
if (p.ExitCode == 0)
|
||||
{
|
||||
Logger.LogInfo("Command Not Found was successfully uninstalled.");
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.LogInfo("Command Not Found failed to uninstall with exit code: " + p.ExitCode);
|
||||
}).Start();
|
||||
}
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
60
src/Runner/ModuleInterfaces/ColorPickerModuleInterface.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
// 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.Text.Json;
|
||||
using System.Threading;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class ColorPickerModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "ColorPicker";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettingsOrDefault<GeneralSettings>().Enabled.ColorPicker;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredColorPickerEnabledValue();
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
using var terminateEventWrapper = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.TerminateColorPickerSharedEvent());
|
||||
terminateEventWrapper.Set();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
}
|
||||
|
||||
private void InitializeShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
Shortcuts.Add((SettingsUtils.Default.GetSettings<ColorPickerSettings>(Name).Properties.ActivationShortcut, () =>
|
||||
{
|
||||
using var showUiEventWrapper = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ShowColorPickerSharedEvent());
|
||||
showUiEventWrapper.Set();
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
}
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
public override string ProcessPath => "PowerToys.ColorPickerUI.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.ColorPickerUI";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument;
|
||||
}
|
||||
}
|
||||
79
src/Runner/ModuleInterfaces/CommandPaletteModuleInterface.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Helpers;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class CommandPaletteModuleInterface : ProcessModuleAbstractClass, IPowerToysModule
|
||||
{
|
||||
private const string PackageName = "Microsoft.CommandPalette"
|
||||
#if DEBUG
|
||||
+ ".Dev"
|
||||
#endif
|
||||
;
|
||||
|
||||
public string Name => "CmdPal";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettingsOrDefault<GeneralSettings>().Enabled.CmdPal;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredCmdPalEnabledValue();
|
||||
|
||||
public override string ProcessPath => "explorer.exe";
|
||||
|
||||
public override string ProcessArguments => "x-cmdpal://background";
|
||||
|
||||
public override string ProcessName => string.Empty;
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.UseShellExecute | ProcessLaunchOptions.NeverExit;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
if (PackageHelper.GetRegisteredPackage(PackageName, false) is null)
|
||||
{
|
||||
try
|
||||
{
|
||||
string architectureString = RuntimeInformation.ProcessArchitecture == Architecture.X64 ? "x64" : "ARM64";
|
||||
#if DEBUG
|
||||
string[] msixFiles = PackageHelper.FindMsixFiles(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\WinUI3Apps\\CmdPal\\AppPackages\\Microsoft.CmdPal.UI_0.0.1.0_Debug_Test\\", false);
|
||||
string[] dependencies = PackageHelper.FindMsixFiles(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\WinUI3Apps\\CmdPal\\AppPackages\\Microsoft.CmdPal.UI_0.0.1.0_Debug_Test\\Dependencies\\" + architectureString + "\\", true);
|
||||
#else
|
||||
string[] msixFiles = PackageHelper.FindMsixFiles(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\WinUI3Apps\\CmdPal\\", false);
|
||||
string[] dependencies = PackageHelper.FindMsixFiles(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\WinUI3Apps\\CmdPal\\Dependencies\\", true);
|
||||
#endif
|
||||
|
||||
if (msixFiles.Length > 0)
|
||||
{
|
||||
if (!PackageHelper.InstallPackage(msixFiles[0], dependencies))
|
||||
{
|
||||
Logger.LogError("Failed to register Command Palette package.");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Exception occurred while enabling Command Palette package.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (PackageHelper.GetRegisteredPackage(PackageName, false) is null)
|
||||
{
|
||||
Logger.LogError("Command Palette package is not registered after attempting to enable it.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
68
src/Runner/ModuleInterfaces/CropAndLockModuleInterface.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
// 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.Text.Json;
|
||||
using System.Threading;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed partial class CropAndLockModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IDisposable, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "CropAndLock";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.CropAndLock;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredCropAndLockEnabledValue();
|
||||
|
||||
private EventWaitHandle _reparentEvent = new(false, EventResetMode.AutoReset, Constants.CropAndLockReparentEvent());
|
||||
private EventWaitHandle _thumbnailEvent = new(false, EventResetMode.AutoReset, Constants.CropAndLockThumbnailEvent());
|
||||
private EventWaitHandle _terminateEvent = new(false, EventResetMode.AutoReset, Constants.CropAndLockExitEvent());
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
_terminateEvent.Set();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
PopulateShortcuts();
|
||||
}
|
||||
|
||||
public void PopulateShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
var settings = SettingsUtils.Default.GetSettings<CropAndLockSettings>(Name);
|
||||
Shortcuts.Add((settings.Properties.ThumbnailHotkey.Value, () => _thumbnailEvent.Set()));
|
||||
Shortcuts.Add((settings.Properties.ReparentHotkey.Value, () => _reparentEvent.Set()));
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
PopulateShortcuts();
|
||||
}
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
public override string ProcessPath => "PowerToys.CropAndLock.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.CropAndLock";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
_reparentEvent.Dispose();
|
||||
_thumbnailEvent.Dispose();
|
||||
_terminateEvent.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
69
src/Runner/ModuleInterfaces/CursorWrapModuleInterface.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
// 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.Runtime.InteropServices;
|
||||
using System.Text.Json;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class CursorWrapModuleInterface : IPowerToysModule, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "CursorWrap";
|
||||
|
||||
private bool _hookActive;
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.CursorWrap;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredCursorWrapEnabledValue();
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
_hookActive = false;
|
||||
CursorWrapStopMouseHook();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
_hookActive = true;
|
||||
CursorWrapStartMouseHook();
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
}
|
||||
|
||||
private void InitializeShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
Shortcuts.Add((SettingsUtils.Default.GetSettings<CursorWrapSettings>(Name).Properties.DefaultActivationShortcut, () =>
|
||||
{
|
||||
if (_hookActive)
|
||||
{
|
||||
CursorWrapStopMouseHook();
|
||||
_hookActive = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
CursorWrapStartMouseHook();
|
||||
_hookActive = true;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
[DllImport("PowerToys.CursorWrap.dll")]
|
||||
private static extern bool CursorWrapStartMouseHook();
|
||||
|
||||
[DllImport("PowerToys.CursorWrap.dll")]
|
||||
private static extern bool CursorWrapStopMouseHook();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// 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.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class EnvironmentVariablesModuleInterface : ProcessModuleAbstractClass, IPowerToysModule
|
||||
{
|
||||
public string Name => "Environment Variables";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.EnvironmentVariables;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredEnvironmentVariablesEnabledValue();
|
||||
|
||||
public override string ProcessPath => "WinUI3Apps\\PowerToys.EnvironmentVariables.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.EnvironmentVariables";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SupressLaunchOnModuleEnabled | ProcessLaunchOptions.NeverExit;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
72
src/Runner/ModuleInterfaces/FancyZonesModuleInterface.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
// 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 Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class FancyZonesModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleCustomActionsProvider, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "FancyZones";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.FancyZones;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredFancyZonesEnabledValue();
|
||||
|
||||
public override string ProcessPath => "PowerToys.FancyZones.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.FancyZones";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument | ProcessLaunchOptions.HideUI;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
using var terminateEvent = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.AutoReset, Constants.FZEExitEvent());
|
||||
terminateEvent.Set();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
}
|
||||
|
||||
public Dictionary<string, Action<string>> CustomActions => new()
|
||||
{
|
||||
{
|
||||
"ToggledFZEditor",
|
||||
(_) =>
|
||||
{
|
||||
EnsureLaunched();
|
||||
using var invokeFZEditorEvent = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.AutoReset, Constants.FZEToggleEvent());
|
||||
invokeFZEditorEvent.Set();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
public void InitializeShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
var settings = SettingsUtils.Default.GetSettings<FancyZonesSettings>(Name);
|
||||
Shortcuts.Add((settings.Properties.FancyzonesEditorHotkey.Value, () =>
|
||||
{
|
||||
EnsureLaunched();
|
||||
using var invokeFZEditorEvent = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.AutoReset, Constants.FZEToggleEvent());
|
||||
invokeFZEditorEvent.Set();
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
}
|
||||
}
|
||||
}
|
||||
329
src/Runner/ModuleInterfaces/FileExplorerModuleInterface.cs
Normal file
@@ -0,0 +1,329 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class FileExplorerModuleInterface : IPowerToysModule, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
private record struct FileExplorerModule(Func<bool> IsEnabled, GpoRuleConfigured GpoRule, RegistryChangeSet RegistryChanges);
|
||||
|
||||
private static readonly List<FileExplorerModule> _fileExplorerModules;
|
||||
|
||||
private static readonly string[] ExtSVG = { ".svg" };
|
||||
private static readonly string[] ExtMarkdown = { ".md", ".markdown", ".mdown", ".mkdn", ".mkd", ".mdwn", ".mdtxt", ".mdtext" };
|
||||
private static readonly string[] ExtPDF = { ".pdf" };
|
||||
private static readonly string[] ExtGCode = { ".gcode" };
|
||||
private static readonly string[] ExtBGCode = { ".bgcode" };
|
||||
private static readonly string[] ExtSTL = { ".stl" };
|
||||
private static readonly string[] ExtQOI = { ".qoi" };
|
||||
|
||||
static FileExplorerModuleInterface()
|
||||
{
|
||||
static PowerPreviewProperties GetProperties() => SettingsUtils.Default.GetSettings<PowerPreviewSettings>(PowerPreviewSettings.ModuleName).Properties;
|
||||
|
||||
string installationPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
|
||||
|
||||
_fileExplorerModules = [
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnableBgcodePreview,
|
||||
GPOWrapper.GetConfiguredBgcodePreviewEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.PreviewHandler, "{0e6d5bdd-d5f8-4692-a089-8bb88cdd37f4}", "BgcodePreviewHandler", "Binary G-code Preview Handler", ExtBGCode)),
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnableBgcodeThumbnail,
|
||||
GPOWrapper.GetConfiguredBgcodeThumbnailsEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.ThumbnailProvider, "{5c93a1e4-99d0-4fb3-991c-6c296a27be21}", "BgcodeThumbnailProvider", "Binary G-code Thumbnail Provider", ExtBGCode)),
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnableGcodePreview,
|
||||
GPOWrapper.GetConfiguredGcodePreviewEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.PreviewHandler, "{A0257634-8812-4CE8-AF11-FA69ACAEAFAE}", "GcodePreviewHandler", "G-code Preview Handler", ExtGCode)),
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnableGcodeThumbnail,
|
||||
GPOWrapper.GetConfiguredGcodeThumbnailsEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.ThumbnailProvider, "{F2847CBE-CD03-4C83-A359-1A8052C1B9D5}", "GcodeThumbnailProvider", "G-code Thumbnail Provider", ExtGCode)),
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnableMdPreview,
|
||||
GPOWrapper.GetConfiguredMarkdownPreviewEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.PreviewHandler, "{60789D87-9C3C-44AF-B18C-3DE2C2820ED3}", "MarkdownPreviewHandler", "Markdown Preview Handler", ExtMarkdown)),
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnablePdfPreview,
|
||||
GPOWrapper.GetConfiguredPdfPreviewEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.PreviewHandler, "{A5A41CC7-02CB-41D4-8C9B-9087040D6098}", "PdfPreviewHandler", "PDF Preview Handler", ExtPDF)),
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnablePdfThumbnail,
|
||||
GPOWrapper.GetConfiguredPdfThumbnailsEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.ThumbnailProvider, "{D8BB9942-93BD-412D-87E4-33FAB214DC1A}", "PdfThumbnailProvider", "PDF Thumbnail Provider", ExtPDF)),
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnableQoiPreview,
|
||||
GPOWrapper.GetConfiguredQoiPreviewEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.PreviewHandler, "{729B72CD-B72E-4FE9-BCBF-E954B33FE699}", "QoiPreviewHandler", "QOI Preview Handler", ExtQOI)),
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnableQoiThumbnail,
|
||||
GPOWrapper.GetConfiguredQoiThumbnailsEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.ThumbnailProvider, "{AD856B15-D25E-4008-AFB7-AFAA55586188}", "QoiThumbnailProvider", "QOI Thumbnail Provider", ExtQOI, "image", "Picture")),
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnableStlThumbnail,
|
||||
GPOWrapper.GetConfiguredStlThumbnailsEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.ThumbnailProvider, "{77257004-6F25-4521-B602-50ECC6EC62A6}", "StlThumbnailProvider", "STL Thumbnail Provider", ExtSTL)),
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnableSvgPreview,
|
||||
GPOWrapper.GetConfiguredSvgPreviewEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.PreviewHandler, "{FCDD4EED-41AA-492F-8A84-31A1546226E0}", "SvgPreviewHandler", "SVG Preview Handler", ExtSVG)),
|
||||
new FileExplorerModule(
|
||||
() => GetProperties().EnableSvgThumbnail,
|
||||
GPOWrapper.GetConfiguredSvgThumbnailsEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(FileExplorerAddOnType.ThumbnailProvider, "{10144713-1526-46C9-88DA-1FB52807A9FF}", "SvgThumbnailProvider", "SVG Thumbnail Provider", ExtSVG, "image", "Picture")),
|
||||
GetMonacoFileExplorerModule(installationPath)
|
||||
];
|
||||
}
|
||||
|
||||
private static FileExplorerModule GetMonacoFileExplorerModule(string installationPath)
|
||||
{
|
||||
// .svgz is a binary file type that Monaco cannot handle, so we exclude it from the preview handler
|
||||
string[] extExclusions = [..ExtMarkdown, ..ExtSVG, ".svgz"];
|
||||
List<string> extensions = [];
|
||||
|
||||
string languagesFilePath = Path.Combine(installationPath, "Assets\\Monaco\\monaco_languages.json");
|
||||
|
||||
if (!File.Exists(languagesFilePath))
|
||||
{
|
||||
Logger.LogError("PowerPreviewModuleInterface: Unable to find monaco_languages.json file at " + languagesFilePath);
|
||||
goto returnLabel;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
JsonDocument jsonDocument = JsonDocument.Parse(File.ReadAllText(languagesFilePath));
|
||||
var list = jsonDocument.RootElement.GetProperty("list");
|
||||
|
||||
foreach (var item in list.EnumerateArray())
|
||||
{
|
||||
if (item.TryGetProperty("extensions", out JsonElement extensionsElement))
|
||||
{
|
||||
foreach (var ext in extensionsElement.EnumerateArray())
|
||||
{
|
||||
string extension = ext.GetString() ?? string.Empty;
|
||||
if (!string.IsNullOrEmpty(extension) && !extensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
extensions.Add(extension);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("PowerPreviewModuleInterface: Failed to parse monaco_languages.json file.", ex);
|
||||
}
|
||||
|
||||
returnLabel:
|
||||
return new FileExplorerModule(
|
||||
() => SettingsUtils.Default.GetSettings<PowerPreviewSettings>(PowerPreviewSettings.ModuleName).Properties.EnableMonacoPreview,
|
||||
GPOWrapper.GetConfiguredMonacoPreviewEnabledValue(),
|
||||
GetFileExplorerAddOnChangeSet(
|
||||
FileExplorerAddOnType.PreviewHandler,
|
||||
"{D8034CFA-F34B-41FE-AD45-62FCBB52A6DA}",
|
||||
"MonacoPreviewHandler",
|
||||
"Monaco Preview Handler",
|
||||
[.. extensions.Where(ext => !extExclusions.Contains(ext))]));
|
||||
}
|
||||
|
||||
private enum FileExplorerAddOnType
|
||||
{
|
||||
ThumbnailProvider,
|
||||
PreviewHandler,
|
||||
}
|
||||
|
||||
private static RegistryChangeSet GetFileExplorerAddOnChangeSet(FileExplorerAddOnType type, string handlerClsid, string className, string displayName, string[] fileTypes, string? perceivedType = null, string? fileKindType = null)
|
||||
{
|
||||
string installationPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
|
||||
string pathToHandler = Path.Combine(installationPath, "PowerToys.FileExplorerDllExporter.dll");
|
||||
string clsidPath = "Software\\Classes\\CLSID\\" + handlerClsid;
|
||||
string inprocServer32Path = clsidPath + "\\InprocServer32";
|
||||
|
||||
string assemblyKeyValue;
|
||||
int lastDotPos = className.LastIndexOf('.');
|
||||
|
||||
if (lastDotPos != -1)
|
||||
{
|
||||
assemblyKeyValue = string.Concat("PowerToys.", className.AsSpan(lastDotPos + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
assemblyKeyValue = "PowerToys." + className;
|
||||
}
|
||||
|
||||
assemblyKeyValue += $", Version={Assembly.GetExecutingAssembly().GetName().Version!}, Culture=neutral";
|
||||
|
||||
List<RegistryValueChange> changes = [
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = clsidPath,
|
||||
KeyName = "DisplayName",
|
||||
Value = displayName,
|
||||
},
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = clsidPath,
|
||||
KeyName = null,
|
||||
Value = className,
|
||||
},
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = inprocServer32Path,
|
||||
KeyName = null,
|
||||
Value = pathToHandler,
|
||||
},
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = inprocServer32Path,
|
||||
KeyName = "Assembly",
|
||||
Value = assemblyKeyValue,
|
||||
},
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = inprocServer32Path,
|
||||
KeyName = "Class",
|
||||
Value = className,
|
||||
},
|
||||
new RegistryValueChange
|
||||
{
|
||||
KeyPath = inprocServer32Path,
|
||||
KeyName = "ThreadingModel",
|
||||
Value = "Apartment",
|
||||
},
|
||||
];
|
||||
|
||||
foreach (string fileType in fileTypes)
|
||||
{
|
||||
string fileTypePath = "Software\\Classes\\" + fileType;
|
||||
string fileAssociationPath = fileTypePath + "\\shellex\\" + (type == FileExplorerAddOnType.PreviewHandler ? IPREVIEWHANDLERCLSID : ITHUMBNAILPROVIDERCLSID);
|
||||
|
||||
changes.Add(new RegistryValueChange
|
||||
{
|
||||
KeyPath = fileAssociationPath,
|
||||
KeyName = null,
|
||||
Value = handlerClsid,
|
||||
});
|
||||
|
||||
if (!string.IsNullOrEmpty(fileKindType))
|
||||
{
|
||||
// Registering a file type as a kind needs to be done at the HKEY_LOCAL_MACHINE level.
|
||||
// Make it optional as well so that we don't fail registering the handler if we can't write to HKEY_LOCAL_MACHINE.
|
||||
string kindPath = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\KindMap";
|
||||
changes.Add(new RegistryValueChange
|
||||
{
|
||||
KeyPath = kindPath,
|
||||
KeyName = fileType,
|
||||
Value = fileKindType,
|
||||
Required = false,
|
||||
});
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(perceivedType))
|
||||
{
|
||||
changes.Add(new RegistryValueChange
|
||||
{
|
||||
KeyPath = fileTypePath,
|
||||
KeyName = "PerceivedType",
|
||||
Value = perceivedType,
|
||||
});
|
||||
}
|
||||
|
||||
// this regfile registry key has precedence over Software\Classes\.reg for .reg files
|
||||
if (type == FileExplorerAddOnType.PreviewHandler && fileType.Equals(".reg", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
string regFilePath = "Software\\Classes\\regfile\\shellex\\" + IPREVIEWHANDLERCLSID;
|
||||
changes.Add(new RegistryValueChange
|
||||
{
|
||||
KeyPath = regFilePath,
|
||||
KeyName = null,
|
||||
Value = handlerClsid,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (type == FileExplorerAddOnType.PreviewHandler)
|
||||
{
|
||||
string previewHostClsid = "{6d2b5079-2f0b-48dd-ab7f-97cec514d30b}";
|
||||
string previewHandlerListPath = "(Software\\Microsoft\\Windows\\CurrentVersion\\PreviewHandlers)";
|
||||
changes.Add(new RegistryValueChange
|
||||
{
|
||||
KeyPath = clsidPath,
|
||||
KeyName = "AppID",
|
||||
Value = previewHostClsid,
|
||||
});
|
||||
|
||||
changes.Add(new RegistryValueChange
|
||||
{
|
||||
KeyPath = previewHandlerListPath,
|
||||
KeyName = handlerClsid,
|
||||
Value = displayName,
|
||||
});
|
||||
}
|
||||
|
||||
changes.Add(new RegistryValueChange
|
||||
{
|
||||
KeyPath = "Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved",
|
||||
KeyName = handlerClsid,
|
||||
Value = displayName,
|
||||
Required = false,
|
||||
});
|
||||
|
||||
return new RegistryChangeSet
|
||||
{
|
||||
Changes = [.. changes],
|
||||
};
|
||||
}
|
||||
|
||||
private const string ITHUMBNAILPROVIDERCLSID = "{E357FCCD-A995-4576-B01F-234630154E96}";
|
||||
private const string IPREVIEWHANDLERCLSID = "{8895b1c6-b41f-4c1c-a562-0d564250836f}";
|
||||
|
||||
public string Name => "File Explorer";
|
||||
|
||||
public bool Enabled => true;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GpoRuleConfigured.Unavailable;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
OnSettingsChanged();
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
foreach (FileExplorerModule submodule in _fileExplorerModules)
|
||||
{
|
||||
if (submodule.GpoRule == GpoRuleConfigured.Disabled)
|
||||
{
|
||||
submodule.RegistryChanges.UnApply();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (submodule.IsEnabled() || submodule.GpoRule == GpoRuleConfigured.Enabled)
|
||||
{
|
||||
submodule.RegistryChanges.Apply();
|
||||
}
|
||||
else
|
||||
{
|
||||
submodule.RegistryChanges.UnApply();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
41
src/Runner/ModuleInterfaces/FileLocksmithModuleInterface.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Helpers;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed partial class FileLocksmithModuleInterface : IPowerToysModule
|
||||
{
|
||||
public string Name => "FileLocksmith";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.FileLocksmith;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredFileLocksmithEnabledValue();
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
UpdateFileLocksmithRegistrationWin10(false);
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
UpdateFileLocksmithRegistrationWin10(true);
|
||||
if (Environment.OSVersion.Version.Build >= 22000)
|
||||
{
|
||||
PackageHelper.InstallPackage(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "WinUI3Apps", "FileLocksmithContextMenuPackage.msix"), [], true);
|
||||
}
|
||||
}
|
||||
|
||||
[LibraryImport("WinUI3Apps/PowerToys.FileLocksmithExt.dll")]
|
||||
private static partial void UpdateFileLocksmithRegistrationWin10([MarshalAs(UnmanagedType.Bool)]bool enabled);
|
||||
}
|
||||
}
|
||||
92
src/Runner/ModuleInterfaces/FindMyMouseModuleInterface.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
// 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.Runtime.InteropServices;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class FindMyMouseModuleInterface : IPowerToysModule, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "FindMyMouse";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.FindMyMouse;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredFindMyMouseEnabledValue();
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
FindMyMouseDisable();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
|
||||
var thread = new Thread(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
uint version = 0x00010008;
|
||||
int hr = MddBootstrapInitialize(version, 0, IntPtr.Zero);
|
||||
if (hr < 0)
|
||||
{
|
||||
throw new InvalidOperationException($"Windows app sdk could not be initialized for MouseJump. HR code:{hr}");
|
||||
}
|
||||
|
||||
FindMyMouseMain();
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
});
|
||||
thread.SetApartmentState(ApartmentState.STA);
|
||||
thread.Start();
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
NativeMethods.PostMessageW(GetSonarHwnd(), GetWmPrivSettingsChanged(), IntPtr.Zero, IntPtr.Zero);
|
||||
}
|
||||
|
||||
private void InitializeShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
|
||||
Shortcuts.Add((SettingsUtils.Default.GetSettings<FindMyMouseSettings>(Name).Properties.ActivationShortcut, () =>
|
||||
{
|
||||
NativeMethods.PostMessageW(GetSonarHwnd(), GetWmPrivShortcut(), IntPtr.Zero, IntPtr.Zero);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
[DllImport("PowerToys.FindMyMouse.dll")]
|
||||
public static extern void FindMyMouseMain();
|
||||
|
||||
[DllImport("PowerToys.FindMyMouse.dll")]
|
||||
public static extern void FindMyMouseDisable();
|
||||
|
||||
[DllImport("PowerToys.FindMyMouse.dll")]
|
||||
public static extern IntPtr GetSonarHwnd();
|
||||
|
||||
[DllImport("PowerToys.FindMyMouse.dll")]
|
||||
public static extern uint GetWmPrivShortcut();
|
||||
|
||||
[DllImport("PowerToys.FindMyMouse.dll")]
|
||||
public static extern uint GetWmPrivSettingsChanged();
|
||||
|
||||
[DllImport("Microsoft.WindowsAppRuntime.Bootstrap.dll", CharSet = CharSet.Unicode)]
|
||||
private static extern int MddBootstrapInitialize(uint majorMinorVersion, uint versionTag, IntPtr packageVersion);
|
||||
}
|
||||
}
|
||||
35
src/Runner/ModuleInterfaces/HostsModuleInterface.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
// 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 Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class HostsModuleInterface : ProcessModuleAbstractClass, IPowerToysModule
|
||||
{
|
||||
public bool Enabled => SettingsUtils.Default.GetSettingsOrDefault<GeneralSettings>().Enabled.Hosts;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredHostsFileEditorEnabledValue();
|
||||
|
||||
public string Name => "Hosts";
|
||||
|
||||
public override string ProcessPath => "WinUI3Apps\\PowerToys.Hosts.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.Hosts";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SupressLaunchOnModuleEnabled | ProcessLaunchOptions.NeverExit;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
42
src/Runner/ModuleInterfaces/ImageResizerModuleInterface.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using RunnerV2.Helpers;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed partial class ImageResizerModuleInterface : IPowerToysModule
|
||||
{
|
||||
public string Name => "ImageResizer";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.ImageResizer;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredImageResizerEnabledValue();
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
UpdateImageResizerRegistrationWin10(false);
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
UpdateImageResizerRegistrationWin10(true);
|
||||
AIHelper.DetectAiCapabilities(true);
|
||||
if (Environment.OSVersion.Version.Build >= 22000)
|
||||
{
|
||||
PackageHelper.InstallPackage(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "WinUI3Apps", "ImageResizerContextMenuPackage.msix"), [], true);
|
||||
}
|
||||
}
|
||||
|
||||
[LibraryImport("WinUI3Apps/PowerToys.ImageResizerExt.dll")]
|
||||
private static partial void UpdateImageResizerRegistrationWin10([MarshalAs(UnmanagedType.Bool)]bool enabled);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// 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.Threading;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class KeyboardManagerModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
private bool isRunning;
|
||||
|
||||
public string Name => "Keyboard Manager";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.KeyboardManager;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredKeyboardManagerEnabledValue();
|
||||
|
||||
public override string ProcessPath => "KeyboardManagerEngine\\PowerToys.KeyboardManagerEngine.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.KeyboardManagerEngine";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument | ProcessLaunchOptions.RealtimePriority;
|
||||
|
||||
public List<(HotkeySettings, Action)> Shortcuts { get; } = [];
|
||||
|
||||
private void InitializeShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
Shortcuts.Add((SettingsUtils.Default.GetSettings<KeyboardManagerSettings>(Name).Properties.ToggleShortcut, () =>
|
||||
{
|
||||
if (isRunning)
|
||||
{
|
||||
Disable();
|
||||
}
|
||||
else
|
||||
{
|
||||
Enable();
|
||||
}
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
isRunning = false;
|
||||
using var terminateEvent = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.TerminateKBMSharedEvent());
|
||||
terminateEvent.Set();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
if (!isRunning)
|
||||
{
|
||||
isRunning = true;
|
||||
InitializeShortcuts();
|
||||
EnsureLaunched();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
InitializeShortcuts();
|
||||
}
|
||||
}
|
||||
}
|
||||
60
src/Runner/ModuleInterfaces/LightSwitchModuleInterface.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
// 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 Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
using Settings.UI.Library;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class LightSwitchModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleShortcutsProvider
|
||||
{
|
||||
public string Name => "LightSwitch";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.LightSwitch;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredLightSwitchEnabledValue();
|
||||
|
||||
public override string ProcessPath => "LightSwitchService\\PowerToys.LightSwitchService.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.LightSwitchService";
|
||||
|
||||
public override string ProcessArguments => $"--pid {Environment.ProcessId}";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess;
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts
|
||||
{
|
||||
get => [(SettingsUtils.Default.GetSettings<LightSwitchSettings>(Name).Properties.ToggleThemeHotkey.Value, () =>
|
||||
{
|
||||
LightSwitchProperties properties = SettingsUtils.Default.GetSettings<LightSwitchSettings>(Name).Properties;
|
||||
EnsureLaunched();
|
||||
if (properties.ChangeSystem.Value)
|
||||
{
|
||||
ThemeHelper.SetSystemTheme(!ThemeHelper.GetCurrentSystemTheme());
|
||||
}
|
||||
|
||||
if (properties.ChangeApps.Value)
|
||||
{
|
||||
ThemeHelper.SetAppsTheme(!ThemeHelper.GetCurrentAppsTheme());
|
||||
}
|
||||
|
||||
using var manualOverrideEvent = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.AutoReset, Constants.LightSwitchManualOverrideEvent());
|
||||
manualOverrideEvent.Set();
|
||||
})];
|
||||
}
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
54
src/Runner/ModuleInterfaces/MeasureToolModuleInterface.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
// 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 Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.GPOWrapper;
|
||||
using PowerToys.Interop;
|
||||
using RunnerV2.Models;
|
||||
|
||||
namespace RunnerV2.ModuleInterfaces
|
||||
{
|
||||
internal sealed class MeasureToolModuleInterface : ProcessModuleAbstractClass, IPowerToysModule, IPowerToysModuleShortcutsProvider, IPowerToysModuleSettingsChangedSubscriber
|
||||
{
|
||||
public string Name => "Measure Tool";
|
||||
|
||||
public bool Enabled => SettingsUtils.Default.GetSettings<GeneralSettings>().Enabled.MeasureTool;
|
||||
|
||||
public GpoRuleConfigured GpoRuleConfigured => GPOWrapper.GetConfiguredScreenRulerEnabledValue();
|
||||
|
||||
public override string ProcessPath => "WinUI3Apps\\PowerToys.MeasureToolUI.exe";
|
||||
|
||||
public override string ProcessName => "PowerToys.MeasureToolUI";
|
||||
|
||||
public override ProcessLaunchOptions LaunchOptions => ProcessLaunchOptions.SingletonProcess | ProcessLaunchOptions.RunnerProcessIdAsFirstArgument | ProcessLaunchOptions.SupressLaunchOnModuleEnabled;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
PopulateShortcuts();
|
||||
}
|
||||
|
||||
public void OnSettingsChanged()
|
||||
{
|
||||
PopulateShortcuts();
|
||||
}
|
||||
|
||||
public List<(HotkeySettings Hotkey, Action Action)> Shortcuts { get; } = [];
|
||||
|
||||
private void PopulateShortcuts()
|
||||
{
|
||||
Shortcuts.Clear();
|
||||
Shortcuts.Add((SettingsUtils.Default.GetSettings<MeasureToolSettings>(Name).Properties.ActivationShortcut, () =>
|
||||
{
|
||||
LaunchProcess();
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||